about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiletest/compiletest.rc69
-rw-r--r--src/compiletest/header.rs41
-rw-r--r--src/compiletest/procsrv.rs14
-rw-r--r--src/compiletest/runtest.rs325
-rw-r--r--src/compiletest/util.rs6
-rw-r--r--src/etc/extract-tests.py6
-rw-r--r--src/etc/vim/after/syntax/rust.vim4
-rw-r--r--src/etc/vim/syntax/rust.vim6
-rw-r--r--src/libcore/at_vec.rs30
-rw-r--r--src/libcore/cell.rs23
-rw-r--r--src/libcore/char.rs6
-rw-r--r--src/libcore/clone.rs102
-rw-r--r--src/libcore/comm.rs15
-rw-r--r--src/libcore/core.rc43
-rw-r--r--src/libcore/either.rs27
-rw-r--r--src/libcore/hash.rs2
-rw-r--r--src/libcore/hashmap.rs21
-rw-r--r--src/libcore/io.rs17
-rw-r--r--src/libcore/iter.rs107
-rw-r--r--src/libcore/local_data.rs10
-rw-r--r--src/libcore/logging.rs1
-rw-r--r--src/libcore/num/f32.rs156
-rw-r--r--src/libcore/num/f64.rs155
-rw-r--r--src/libcore/num/float.rs155
-rw-r--r--src/libcore/num/int-template.rs10
-rw-r--r--src/libcore/num/num.rs7
-rw-r--r--src/libcore/num/strconv.rs39
-rw-r--r--src/libcore/num/uint-template.rs10
-rw-r--r--src/libcore/old_iter.rs84
-rw-r--r--src/libcore/option.rs21
-rw-r--r--src/libcore/os.rs87
-rw-r--r--src/libcore/path.rs4
-rw-r--r--src/libcore/pipes.rs23
-rw-r--r--src/libcore/prelude.rs2
-rw-r--r--src/libcore/ptr.rs8
-rw-r--r--src/libcore/repr.rs5
-rw-r--r--src/libcore/result.rs12
-rw-r--r--src/libcore/rt/local_services.rs4
-rw-r--r--src/libcore/rt/mod.rs1
-rw-r--r--src/libcore/rt/sched/mod.rs42
-rw-r--r--src/libcore/rt/stack.rs6
-rw-r--r--src/libcore/rt/test.rs2
-rw-r--r--src/libcore/rt/uv/mod.rs4
-rw-r--r--src/libcore/rt/uv/net.rs6
-rw-r--r--src/libcore/rt/uvio.rs8
-rw-r--r--src/libcore/rt/uvll.rs2
-rw-r--r--src/libcore/rt/work_queue.rs2
-rw-r--r--src/libcore/run.rs38
-rw-r--r--src/libcore/str.rs24
-rw-r--r--src/libcore/str/ascii.rs3
-rw-r--r--src/libcore/task/local_data_priv.rs6
-rw-r--r--src/libcore/task/mod.rs8
-rw-r--r--src/libcore/task/spawn.rs24
-rw-r--r--src/libcore/to_bytes.rs2
-rw-r--r--src/libcore/to_str.rs3
-rw-r--r--src/libcore/unstable.rs354
-rw-r--r--src/libcore/unstable/exchange_alloc.rs2
-rw-r--r--src/libcore/unstable/extfmt.rs36
-rw-r--r--src/libcore/unstable/global.rs31
-rw-r--r--src/libcore/unstable/intrinsics.rs76
-rw-r--r--src/libcore/unstable/mod.rs78
-rw-r--r--src/libcore/unstable/sync.rs285
-rw-r--r--src/libcore/unstable/weak_task.rs2
-rw-r--r--src/libcore/util.rs2
-rw-r--r--src/libcore/vec.rs293
-rw-r--r--src/libfuzzer/ast_match.rs4
-rw-r--r--src/libfuzzer/cycles.rs2
-rw-r--r--src/libfuzzer/fuzzer.rc4
-rw-r--r--src/libfuzzer/rand_util.rs6
-rw-r--r--src/librustc/README.txt8
-rw-r--r--src/librustc/back/link.rs1
-rw-r--r--src/librustc/back/rpath.rs6
-rw-r--r--src/librustc/driver/driver.rs22
-rw-r--r--src/librustc/driver/session.rs30
-rw-r--r--src/librustc/front/test.rs2
-rw-r--r--src/librustc/lib/llvm.rs3
-rw-r--r--src/librustc/metadata/common.rs2
-rw-r--r--src/librustc/metadata/csearch.rs22
-rw-r--r--src/librustc/metadata/decoder.rs99
-rw-r--r--src/librustc/metadata/encoder.rs32
-rw-r--r--src/librustc/metadata/filesearch.rs4
-rw-r--r--src/librustc/metadata/loader.rs4
-rw-r--r--src/librustc/metadata/tydecode.rs48
-rw-r--r--src/librustc/metadata/tyencode.rs15
-rw-r--r--src/librustc/middle/astencode.rs37
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs97
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs15
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs77
-rw-r--r--src/librustc/middle/borrowck/mod.rs12
-rw-r--r--src/librustc/middle/check_const.rs2
-rw-r--r--src/librustc/middle/check_match.rs18
-rw-r--r--src/librustc/middle/const_eval.rs2
-rw-r--r--src/librustc/middle/dataflow.rs3
-rw-r--r--src/librustc/middle/freevars.rs9
-rw-r--r--src/librustc/middle/kind.rs12
-rw-r--r--src/librustc/middle/lint.rs854
-rw-r--r--src/librustc/middle/liveness.rs163
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/moves.rs8
-rw-r--r--src/librustc/middle/region.rs12
-rw-r--r--src/librustc/middle/resolve.rs471
-rw-r--r--src/librustc/middle/resolve_stage0.rs132
-rw-r--r--src/librustc/middle/trans/_match.rs10
-rw-r--r--src/librustc/middle/trans/asm.rs19
-rw-r--r--src/librustc/middle/trans/base.rs45
-rw-r--r--src/librustc/middle/trans/build.rs4
-rw-r--r--src/librustc/middle/trans/cabi.rs6
-rw-r--r--src/librustc/middle/trans/cabi_arm.rs4
-rw-r--r--src/librustc/middle/trans/cabi_mips.rs4
-rw-r--r--src/librustc/middle/trans/cabi_x86_64.rs16
-rw-r--r--src/librustc/middle/trans/callee.rs24
-rw-r--r--src/librustc/middle/trans/common.rs10
-rw-r--r--src/librustc/middle/trans/datum.rs1
-rw-r--r--src/librustc/middle/trans/debuginfo.rs4
-rw-r--r--src/librustc/middle/trans/expr.rs6
-rw-r--r--src/librustc/middle/trans/foreign.rs11
-rw-r--r--src/librustc/middle/trans/inline.rs4
-rw-r--r--src/librustc/middle/trans/meth.rs80
-rw-r--r--src/librustc/middle/trans/monomorphize.rs1
-rw-r--r--src/librustc/middle/trans/reachable.rs2
-rw-r--r--src/librustc/middle/trans/reflect.rs21
-rw-r--r--src/librustc/middle/trans/shape.rs3
-rw-r--r--src/librustc/middle/trans/type_of.rs16
-rw-r--r--src/librustc/middle/trans/type_use.rs16
-rw-r--r--src/librustc/middle/ty.rs197
-rw-r--r--src/librustc/middle/typeck/astconv.rs258
-rw-r--r--src/librustc/middle/typeck/check/method.rs66
-rw-r--r--src/librustc/middle/typeck/check/mod.rs246
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs2
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs2
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs30
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs10
-rw-r--r--src/librustc/middle/typeck/coherence.rs47
-rw-r--r--src/librustc/middle/typeck/collect.rs116
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs222
-rw-r--r--src/librustc/middle/typeck/infer/glb.rs31
-rw-r--r--src/librustc/middle/typeck/infer/lattice.rs72
-rw-r--r--src/librustc/middle/typeck/infer/lub.rs17
-rw-r--r--src/librustc/middle/typeck/infer/region_inference.rs24
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs16
-rw-r--r--src/librustc/middle/typeck/infer/test.rs24
-rw-r--r--src/librustc/middle/typeck/infer/to_str.rs2
-rw-r--r--src/librustc/middle/typeck/mod.rs25
-rw-r--r--src/librustc/middle/typeck/rscope.rs12
-rw-r--r--src/librustc/util/enum_set.rs20
-rw-r--r--src/librustc/util/ppaux.rs28
-rw-r--r--src/librustdoc/attr_pass.rs15
-rw-r--r--src/librustdoc/markdown_index_pass.rs16
-rw-r--r--src/librustdoc/markdown_pass.rs15
-rw-r--r--src/librustdoc/markdown_writer.rs2
-rw-r--r--src/librustdoc/prune_hidden_pass.rs2
-rw-r--r--src/librustdoc/prune_private_pass.rs4
-rw-r--r--src/librustdoc/sort_item_type_pass.rs3
-rw-r--r--src/librustdoc/tystr_pass.rs46
-rw-r--r--src/librusti/rusti.rc129
-rw-r--r--src/librusti/wrapper.rs6
-rw-r--r--src/librustpkg/conditions.rs4
-rw-r--r--src/librustpkg/path_util.rs125
-rw-r--r--src/librustpkg/rustpkg.rc310
-rw-r--r--src/librustpkg/tests.rs116
-rw-r--r--src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/main.rs (renamed from src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/src/main.rs)0
-rw-r--r--src/librustpkg/testsuite/pass/src/external-crate/main.rs (renamed from src/librustpkg/testsuite/pass/src/external-crate/src/main.rs)0
-rw-r--r--src/librustpkg/util.rs366
-rw-r--r--src/librustpkg/workspace.rs8
-rw-r--r--src/libstd/arc.rs88
-rw-r--r--src/libstd/base64.rs8
-rw-r--r--src/libstd/bitv.rs6
-rw-r--r--src/libstd/dlist.rs34
-rw-r--r--src/libstd/ebml.rs56
-rw-r--r--src/libstd/fileinput.rs2
-rw-r--r--src/libstd/flatpipes.rs8
-rw-r--r--src/libstd/fun_treemap.rs51
-rw-r--r--src/libstd/future.rs4
-rw-r--r--src/libstd/getopts.rs8
-rw-r--r--src/libstd/json.rs36
-rw-r--r--src/libstd/list.rs4
-rw-r--r--src/libstd/md4.rs4
-rw-r--r--src/libstd/net_ip.rs15
-rw-r--r--src/libstd/net_tcp.rs30
-rw-r--r--src/libstd/num/bigint.rs42
-rw-r--r--src/libstd/num/rational.rs170
-rw-r--r--src/libstd/par.rs5
-rw-r--r--src/libstd/priority_queue.rs72
-rw-r--r--src/libstd/rc.rs181
-rw-r--r--src/libstd/rl.rs8
-rw-r--r--src/libstd/rope.rs4
-rw-r--r--src/libstd/sha1.rs6
-rw-r--r--src/libstd/sort.rs14
-rw-r--r--src/libstd/sort_stage0.rs14
-rw-r--r--src/libstd/std.rc1
-rw-r--r--src/libstd/sync.rs23
-rw-r--r--src/libstd/test.rs14
-rw-r--r--src/libstd/time.rs8
-rw-r--r--src/libstd/timer.rs8
-rw-r--r--src/libstd/treemap.rs4
-rw-r--r--src/libstd/uv_global_loop.rs4
-rw-r--r--src/libstd/uv_ll.rs143
-rw-r--r--src/libstd/workcache.rs4
-rw-r--r--src/libsyntax/abi.rs8
-rw-r--r--src/libsyntax/ast.rs373
-rw-r--r--src/libsyntax/ast_map.rs12
-rw-r--r--src/libsyntax/ast_util.rs30
-rw-r--r--src/libsyntax/codemap.rs67
-rw-r--r--src/libsyntax/diagnostic.rs8
-rw-r--r--src/libsyntax/ext/asm.rs8
-rw-r--r--src/libsyntax/ext/auto_encode.rs1488
-rw-r--r--src/libsyntax/ext/base.rs17
-rw-r--r--src/libsyntax/ext/build.rs307
-rw-r--r--src/libsyntax/ext/bytes.rs28
-rw-r--r--src/libsyntax/ext/deriving/clone.rs62
-rw-r--r--src/libsyntax/ext/deriving/cmp/eq.rs10
-rw-r--r--src/libsyntax/ext/deriving/cmp/ord.rs6
-rw-r--r--src/libsyntax/ext/deriving/cmp/totaleq.rs2
-rw-r--r--src/libsyntax/ext/deriving/cmp/totalord.rs11
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs9
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs328
-rw-r--r--src/libsyntax/ext/deriving/generic.rs154
-rw-r--r--src/libsyntax/ext/deriving/iter_bytes.rs12
-rw-r--r--src/libsyntax/ext/deriving/mod.rs25
-rw-r--r--src/libsyntax/ext/deriving/rand.rs2
-rw-r--r--src/libsyntax/ext/deriving/to_str.rs2
-rw-r--r--src/libsyntax/ext/deriving/ty.rs28
-rw-r--r--src/libsyntax/ext/expand.rs62
-rw-r--r--src/libsyntax/ext/fmt.rs2
-rw-r--r--src/libsyntax/ext/pipes/parse_proto.rs4
-rw-r--r--src/libsyntax/ext/pipes/proto.rs8
-rw-r--r--src/libsyntax/ext/quote.rs22
-rw-r--r--src/libsyntax/ext/trace_macros.rs4
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs41
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs12
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs14
-rw-r--r--src/libsyntax/fold.rs28
-rw-r--r--src/libsyntax/opt_vec.rs5
-rw-r--r--src/libsyntax/parse/comments.rs6
-rw-r--r--src/libsyntax/parse/common.rs43
-rw-r--r--src/libsyntax/parse/mod.rs19
-rw-r--r--src/libsyntax/parse/obsolete.rs24
-rw-r--r--src/libsyntax/parse/parser.rs407
-rw-r--r--src/libsyntax/parse/token.rs43
-rw-r--r--src/libsyntax/print/pp.rs20
-rw-r--r--src/libsyntax/print/pprust.rs141
-rw-r--r--src/libsyntax/syntax.rc2
-rw-r--r--src/libsyntax/visit.rs13
-rw-r--r--src/rustllvm/RustWrapper.cpp2
-rw-r--r--src/test/auxiliary/cci_iter_lib.rs2
-rw-r--r--src/test/auxiliary/cci_no_inline_lib.rs2
-rw-r--r--src/test/auxiliary/static-methods-crate.rs2
-rw-r--r--src/test/bench/graph500-bfs.rs8
-rw-r--r--src/test/bench/shootout-chameneos-redux.rs2
-rw-r--r--src/test/bench/shootout-k-nucleotide-pipes.rs8
-rw-r--r--src/test/bench/sudoku.rs10
-rw-r--r--src/test/bench/task-perf-jargon-metal-smoke.rs2
-rw-r--r--src/test/compile-fail/borrowck-rvalues-mutable-bad.rs38
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-element-loan.rs6
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-nesting.rs2
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs2
-rw-r--r--src/test/compile-fail/closure-bounds-not-builtin.rs8
-rw-r--r--src/test/compile-fail/closure-bounds-subtype.rs34
-rw-r--r--src/test/compile-fail/deprecated-auto-code.rs (renamed from src/test/compile-fail/deriving-obsolete.rs)10
-rw-r--r--src/test/compile-fail/import2.rs2
-rw-r--r--src/test/compile-fail/issue-2123.rs1
-rw-r--r--src/test/compile-fail/issue-2937.rs1
-rw-r--r--src/test/compile-fail/issue-3601.rs2
-rw-r--r--src/test/compile-fail/issue-3993-2.rs1
-rw-r--r--src/test/compile-fail/issue-3993-3.rs1
-rw-r--r--src/test/compile-fail/issue-3993.rs1
-rw-r--r--src/test/compile-fail/issue-5099.rs2
-rw-r--r--src/test/compile-fail/lint-impl-fn.rs37
-rw-r--r--src/test/compile-fail/lint-unused-imports.rs (renamed from src/test/compile-fail/unused-imports-warn.rs)0
-rw-r--r--src/test/compile-fail/lint-unused-mut-variables.rs (renamed from src/test/compile-fail/unused-mut-variables.rs)0
-rw-r--r--src/test/compile-fail/lint-unused-unsafe.rs (renamed from src/test/compile-fail/unused-unsafe.rs)6
-rw-r--r--src/test/compile-fail/liveness-dead.rs11
-rw-r--r--src/test/compile-fail/non-exhaustive-match-nested.rs4
-rw-r--r--src/test/compile-fail/noncopyable-match-pattern.rs2
-rw-r--r--src/test/compile-fail/super-at-top-level.rs3
-rw-r--r--src/test/compile-fail/tag-that-dare-not-speak-its-name.rs2
-rw-r--r--src/test/compile-fail/unresolved-import.rs10
-rw-r--r--src/test/compile-fail/unsafe-fn-autoderef.rs10
-rw-r--r--src/test/compile-fail/use-after-move-self-based-on-type.rs2
-rw-r--r--src/test/compile-fail/use-after-move-self.rs2
-rw-r--r--src/test/run-fail/alt-disc-bot.rs2
-rw-r--r--src/test/run-fail/alt-wildcards.rs4
-rw-r--r--src/test/run-fail/args-fail.rs4
-rw-r--r--src/test/run-fail/assert-eq-macro-fail.rs2
-rw-r--r--src/test/run-fail/binop-fail-2.rs2
-rw-r--r--src/test/run-fail/binop-fail.rs2
-rw-r--r--src/test/run-fail/bug-811.rs2
-rw-r--r--src/test/run-fail/die-macro-expr.rs2
-rw-r--r--src/test/run-fail/die-macro-pure.rs2
-rw-r--r--src/test/run-fail/die-macro.rs2
-rw-r--r--src/test/run-fail/doublefail.rs4
-rw-r--r--src/test/run-fail/explicit-fail-msg.rs2
-rw-r--r--src/test/run-fail/fail-arg.rs2
-rw-r--r--src/test/run-fail/fail-macro-owned.rs2
-rw-r--r--src/test/run-fail/fail-main.rs2
-rw-r--r--src/test/run-fail/fail-parens.rs2
-rw-r--r--src/test/run-fail/for-each-loop-fail.rs2
-rw-r--r--src/test/run-fail/if-check-fail.rs2
-rw-r--r--src/test/run-fail/if-cond-bot.rs2
-rw-r--r--src/test/run-fail/issue-3029.rs2
-rw-r--r--src/test/run-fail/issue-948.rs2
-rw-r--r--src/test/run-fail/linked-failure3.rs2
-rw-r--r--src/test/run-fail/rhs-type.rs2
-rw-r--r--src/test/run-fail/rt-log-trunc.rs2
-rw-r--r--src/test/run-fail/run-unexported-tests.rs2
-rw-r--r--src/test/run-fail/task-comm-recv-block.rs4
-rw-r--r--src/test/run-fail/unwind-alt.rs2
-rw-r--r--src/test/run-fail/unwind-lambda.rs2
-rw-r--r--src/test/run-fail/unwind-resource-fail.rs2
-rw-r--r--src/test/run-fail/unwind-resource-fail2.rs2
-rw-r--r--src/test/run-fail/unwind-resource-fail3.rs2
-rw-r--r--src/test/run-fail/while-body-fails.rs2
-rw-r--r--src/test/run-fail/while-fail.rs2
-rw-r--r--src/test/run-fail/zip-different-lengths.rs2
-rw-r--r--src/test/run-pass/alt-pattern-lit.rs2
-rw-r--r--src/test/run-pass/alt-range.rs16
-rw-r--r--src/test/run-pass/alt-ref-binding-in-guard-3256.rs2
-rw-r--r--src/test/run-pass/assignability-trait.rs6
-rw-r--r--src/test/run-pass/binary-minus-without-space.rs2
-rw-r--r--src/test/run-pass/block-arg.rs4
-rw-r--r--src/test/run-pass/borrowck-rvalues-mutable.rs30
-rw-r--r--src/test/run-pass/class-impl-very-parameterized-trait.rs4
-rw-r--r--src/test/run-pass/class-implements-multiple-traits.rs2
-rw-r--r--src/test/run-pass/cond-macro-no-default.rs23
-rw-r--r--src/test/run-pass/cond-macro.rs23
-rw-r--r--src/test/run-pass/deriving-clone-enum.rs7
-rw-r--r--src/test/run-pass/deriving-clone-generic-enum.rs17
-rw-r--r--src/test/run-pass/deriving-clone-generic-struct.rs6
-rw-r--r--src/test/run-pass/deriving-clone-generic-tuple-struct.rs16
-rw-r--r--src/test/run-pass/deriving-clone-struct.rs12
-rw-r--r--src/test/run-pass/expr-alt-box.rs4
-rw-r--r--src/test/run-pass/expr-alt-generic-box2.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic-unique1.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic-unique2.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic.rs2
-rw-r--r--src/test/run-pass/for-loop-fail.rs2
-rw-r--r--src/test/run-pass/hashmap-memory.rs2
-rw-r--r--src/test/run-pass/issue-2718.rs10
-rw-r--r--src/test/run-pass/nullable-pointer-iotareduction.rs6
-rw-r--r--src/test/run-pass/option_addition.rs2
-rw-r--r--src/test/run-pass/overload-index-operator.rs4
-rw-r--r--src/test/run-pass/pipe-bank-proto.rs12
-rw-r--r--src/test/run-pass/region-return-interior-of-option.rs2
-rw-r--r--src/test/run-pass/syntax-extension-bytes.rs16
-rw-r--r--src/test/run-pass/vec-each2_mut.rs38
-rw-r--r--src/test/run-pass/vec-self-append.rs8
-rw-r--r--src/test/run-pass/weird-exprs.rs2
347 files changed, 7101 insertions, 6677 deletions
diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc
index 7f691cc1995..dedf465b56d 100644
--- a/src/compiletest/compiletest.rc
+++ b/src/compiletest/compiletest.rc
@@ -10,9 +10,7 @@
 
 #[crate_type = "bin"];
 
-#[allow(vecs_implicitly_copyable)];
 #[allow(non_camel_case_types)];
-#[allow(deprecated_pattern)];
 
 extern mod std(vers = "0.7-pre");
 
@@ -43,8 +41,8 @@ pub mod errors;
 pub fn main() {
     let args = os::args();
     let config = parse_config(args);
-    log_config(config);
-    run_tests(config);
+    log_config(&config);
+    run_tests(&config);
 }
 
 pub fn parse_config(args: ~[~str]) -> config {
@@ -89,22 +87,23 @@ pub fn parse_config(args: ~[~str]) -> config {
         run_ignored: getopts::opt_present(matches, ~"ignored"),
         filter:
              if vec::len(matches.free) > 0u {
-                 option::Some(matches.free[0])
+                 option::Some(copy matches.free[0])
              } else { option::None },
         logfile: getopts::opt_maybe_str(matches, ~"logfile").map(|s| Path(*s)),
         runtool: getopts::opt_maybe_str(matches, ~"runtool"),
         rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"),
         jit: getopts::opt_present(matches, ~"jit"),
         newrt: getopts::opt_present(matches, ~"newrt"),
-        target: opt_str(getopts::opt_maybe_str(matches, ~"target")),
-        adb_path: opt_str(getopts::opt_maybe_str(matches, ~"adb-path")),
-        adb_test_dir: opt_str(getopts::opt_maybe_str(matches, ~"adb-test-dir")),
+        target: opt_str2(getopts::opt_maybe_str(matches, ~"target")).to_str(),
+        adb_path: opt_str2(getopts::opt_maybe_str(matches, ~"adb-path")).to_str(),
+        adb_test_dir:
+            opt_str2(getopts::opt_maybe_str(matches, ~"adb-test-dir")).to_str(),
         adb_device_status:
-            if (opt_str(getopts::opt_maybe_str(matches, ~"target")) ==
+            if (opt_str2(getopts::opt_maybe_str(matches, ~"target")) ==
                 ~"arm-linux-androideabi") {
-                if (opt_str(getopts::opt_maybe_str(matches, ~"adb-test-dir")) !=
+                if (opt_str2(getopts::opt_maybe_str(matches, ~"adb-test-dir")) !=
                     ~"(none)" &&
-                    opt_str(getopts::opt_maybe_str(matches, ~"adb-test-dir")) !=
+                    opt_str2(getopts::opt_maybe_str(matches, ~"adb-test-dir")) !=
                     ~"") { true }
                 else { false }
             } else { false },
@@ -112,7 +111,7 @@ pub fn parse_config(args: ~[~str]) -> config {
     }
 }
 
-pub fn log_config(config: config) {
+pub fn log_config(config: &config) {
     let c = config;
     logv(c, fmt!("configuration:"));
     logv(c, fmt!("compile_lib_path: %s", config.compile_lib_path));
@@ -123,9 +122,9 @@ pub fn log_config(config: config) {
     logv(c, fmt!("stage_id: %s", config.stage_id));
     logv(c, fmt!("mode: %s", mode_str(config.mode)));
     logv(c, fmt!("run_ignored: %b", config.run_ignored));
-    logv(c, fmt!("filter: %s", opt_str(config.filter)));
-    logv(c, fmt!("runtool: %s", opt_str(config.runtool)));
-    logv(c, fmt!("rustcflags: %s", opt_str(config.rustcflags)));
+    logv(c, fmt!("filter: %s", opt_str(&config.filter)));
+    logv(c, fmt!("runtool: %s", opt_str(&config.runtool)));
+    logv(c, fmt!("rustcflags: %s", opt_str(&config.rustcflags)));
     logv(c, fmt!("jit: %b", config.jit));
     logv(c, fmt!("newrt: %b", config.newrt));
     logv(c, fmt!("target: %s", config.target));
@@ -136,8 +135,18 @@ pub fn log_config(config: config) {
     logv(c, fmt!("\n"));
 }
 
-pub fn opt_str(maybestr: Option<~str>) -> ~str {
-    match maybestr { option::Some(s) => s, option::None => ~"(none)" }
+pub fn opt_str<'a>(maybestr: &'a Option<~str>) -> &'a str {
+    match *maybestr {
+        option::None => "(none)",
+        option::Some(ref s) => {
+            let s: &'a str = *s;
+            s
+        }
+    }
+}
+
+pub fn opt_str2(maybestr: Option<~str>) -> ~str {
+    match maybestr { None => ~"(none)", Some(s) => { s } }
 }
 
 pub fn str_opt(maybestr: ~str) -> Option<~str> {
@@ -151,7 +160,7 @@ pub fn str_mode(s: ~str) -> mode {
       ~"run-pass" => mode_run_pass,
       ~"pretty" => mode_pretty,
       ~"debug-info" => mode_debug_info,
-      _ => fail!(~"invalid mode")
+      _ => fail!("invalid mode")
     }
 }
 
@@ -165,16 +174,16 @@ pub fn mode_str(mode: mode) -> ~str {
     }
 }
 
-pub fn run_tests(config: config) {
+pub fn run_tests(config: &config) {
     let opts = test_opts(config);
     let tests = make_tests(config);
     let res = test::run_tests_console(&opts, tests);
-    if !res { fail!(~"Some tests failed"); }
+    if !res { fail!("Some tests failed"); }
 }
 
-pub fn test_opts(config: config) -> test::TestOpts {
+pub fn test_opts(config: &config) -> test::TestOpts {
     test::TestOpts {
-        filter: config.filter,
+        filter: copy config.filter,
         run_ignored: config.run_ignored,
         logfile: copy config.logfile,
         run_tests: true,
@@ -184,7 +193,7 @@ pub fn test_opts(config: config) -> test::TestOpts {
     }
 }
 
-pub fn make_tests(config: config) -> ~[test::TestDescAndFn] {
+pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] {
     debug!("making tests from %s",
            config.src_base.to_str());
     let mut tests = ~[];
@@ -198,7 +207,7 @@ pub fn make_tests(config: config) -> ~[test::TestDescAndFn] {
     tests
 }
 
-pub fn is_test(config: config, testfile: &Path) -> bool {
+pub fn is_test(config: &config, testfile: &Path) -> bool {
     // Pretty-printer does not work with .rc files yet
     let valid_extensions =
         match config.mode {
@@ -221,7 +230,7 @@ pub fn is_test(config: config, testfile: &Path) -> bool {
     return valid;
 }
 
-pub fn make_test(config: config, testfile: &Path) -> test::TestDescAndFn {
+pub fn make_test(config: &config, testfile: &Path) -> test::TestDescAndFn {
     test::TestDescAndFn {
         desc: test::TestDesc {
             name: make_test_name(config, testfile),
@@ -232,13 +241,15 @@ pub fn make_test(config: config, testfile: &Path) -> test::TestDescAndFn {
     }
 }
 
-pub fn make_test_name(config: config, testfile: &Path) -> test::TestName {
+pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName {
     test::DynTestName(fmt!("[%s] %s",
                            mode_str(config.mode),
                            testfile.to_str()))
 }
 
-pub fn make_test_closure(config: config, testfile: &Path) -> test::TestFn {
-    let testfile = testfile.to_str();
-    test::DynTestFn(|| runtest::run(config, testfile))
+pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn {
+    use core::cell::Cell;
+    let config = Cell(copy *config);
+    let testfile = Cell(testfile.to_str());
+    test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) })
 }
diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs
index 7e617aa0006..b1f4c9f515b 100644
--- a/src/compiletest/header.rs
+++ b/src/compiletest/header.rs
@@ -52,12 +52,14 @@ pub fn load_props(testfile: &Path) -> TestProps {
             pp_exact = parse_pp_exact(ln, testfile);
         }
 
-        for parse_aux_build(ln).each |ab| {
-            aux_builds.push(*ab);
+        match parse_aux_build(ln) {
+            Some(ab) => { aux_builds.push(ab); }
+            None => {}
         }
 
-        for parse_exec_env(ln).each |ee| {
-            exec_env.push(*ee);
+        match parse_exec_env(ln) {
+            Some(ee) => { exec_env.push(ee); }
+            None => {}
         }
 
         match parse_debugger_cmd(ln) {
@@ -81,7 +83,7 @@ pub fn load_props(testfile: &Path) -> TestProps {
     };
 }
 
-pub fn is_test_ignored(config: config, testfile: &Path) -> bool {
+pub fn is_test_ignored(config: &config, testfile: &Path) -> bool {
     for iter_header(testfile) |ln| {
         if parse_name_directive(ln, ~"xfail-test") { return true; }
         if parse_name_directive(ln, xfail_target()) { return true; }
@@ -111,44 +113,47 @@ fn iter_header(testfile: &Path, it: &fn(~str) -> bool) -> bool {
     return true;
 }
 
-fn parse_error_pattern(line: ~str) -> Option<~str> {
+fn parse_error_pattern(line: &str) -> Option<~str> {
     parse_name_value_directive(line, ~"error-pattern")
 }
 
-fn parse_aux_build(line: ~str) -> Option<~str> {
+fn parse_aux_build(line: &str) -> Option<~str> {
     parse_name_value_directive(line, ~"aux-build")
 }
 
-fn parse_compile_flags(line: ~str) -> Option<~str> {
+fn parse_compile_flags(line: &str) -> Option<~str> {
     parse_name_value_directive(line, ~"compile-flags")
 }
 
-fn parse_debugger_cmd(line: ~str) -> Option<~str> {
+fn parse_debugger_cmd(line: &str) -> Option<~str> {
     parse_name_value_directive(line, ~"debugger")
 }
 
-fn parse_check_line(line: ~str) -> Option<~str> {
+fn parse_check_line(line: &str) -> Option<~str> {
     parse_name_value_directive(line, ~"check")
 }
 
-fn parse_exec_env(line: ~str) -> Option<(~str, ~str)> {
+fn parse_exec_env(line: &str) -> Option<(~str, ~str)> {
     do parse_name_value_directive(line, ~"exec-env").map |nv| {
         // nv is either FOO or FOO=BAR
         let mut strs = ~[];
         for str::each_splitn_char(*nv, '=', 1u) |s| { strs.push(s.to_owned()); }
         match strs.len() {
-          1u => (strs[0], ~""),
-          2u => (strs[0], strs[1]),
-          n => fail!(fmt!("Expected 1 or 2 strings, not %u", n))
+          1u => (strs.pop(), ~""),
+          2u => {
+              let end = strs.pop();
+              (strs.pop(), end)
+          }
+          n => fail!("Expected 1 or 2 strings, not %u", n)
         }
     }
 }
 
-fn parse_pp_exact(line: ~str, testfile: &Path) -> Option<Path> {
+fn parse_pp_exact(line: &str, testfile: &Path) -> Option<Path> {
     match parse_name_value_directive(line, ~"pp-exact") {
       Some(s) => Some(Path(s)),
       None => {
-        if parse_name_directive(line, ~"pp-exact") {
+        if parse_name_directive(line, "pp-exact") {
             Some(testfile.file_path())
         } else {
             None
@@ -157,11 +162,11 @@ fn parse_pp_exact(line: ~str, testfile: &Path) -> Option<Path> {
     }
 }
 
-fn parse_name_directive(line: ~str, directive: ~str) -> bool {
+fn parse_name_directive(line: &str, directive: &str) -> bool {
     str::contains(line, directive)
 }
 
-fn parse_name_value_directive(line: ~str,
+fn parse_name_value_directive(line: &str,
                               directive: ~str) -> Option<~str> {
     let keycolon = directive + ~":";
     match str::find_str(line, keycolon) {
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index fe08cf1201b..71efa5596a8 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -14,7 +14,7 @@ use core::run::spawn_process;
 use core::run;
 
 #[cfg(target_os = "win32")]
-fn target_env(lib_path: ~str, prog: ~str) -> ~[(~str,~str)] {
+fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
 
     let mut env = os::env();
 
@@ -27,7 +27,7 @@ fn target_env(lib_path: ~str, prog: ~str) -> ~[(~str,~str)] {
         if k == ~"PATH" { (~"PATH", v + ~";" + lib_path + ~";" + aux_path) }
         else { (k,v) }
     };
-    if str::ends_with(prog, ~"rustc.exe") {
+    if str::ends_with(prog, "rustc.exe") {
         env.push((~"RUST_THREADS", ~"1"));
     }
     return env;
@@ -36,16 +36,16 @@ fn target_env(lib_path: ~str, prog: ~str) -> ~[(~str,~str)] {
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
-fn target_env(_lib_path: ~str, _prog: ~str) -> ~[(~str,~str)] {
+fn target_env(_lib_path: &str, _prog: &str) -> ~[(~str,~str)] {
     ~[]
 }
 
-struct Result {status: int, out: ~str, err: ~str}
+pub struct Result {status: int, out: ~str, err: ~str}
 
 // FIXME (#2659): This code is duplicated in core::run::program_output
-pub fn run(lib_path: ~str,
-           prog: ~str,
-           args: ~[~str],
+pub fn run(lib_path: &str,
+           prog: &str,
+           args: &[~str],
            env: ~[(~str, ~str)],
            input: Option<~str>) -> Result {
     let pipe_in = os::pipe();
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 62c2612f2dd..d58c2e596bd 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -30,40 +30,40 @@ pub fn run(config: config, testfile: ~str) {
     let props = load_props(&testfile);
     debug!("loaded props");
     match config.mode {
-      mode_compile_fail => run_cfail_test(config, props, &testfile),
-      mode_run_fail => run_rfail_test(config, props, &testfile),
-      mode_run_pass => run_rpass_test(config, props, &testfile),
-      mode_pretty => run_pretty_test(config, props, &testfile),
-      mode_debug_info => run_debuginfo_test(config, props, &testfile)
+      mode_compile_fail => run_cfail_test(&config, &props, &testfile),
+      mode_run_fail => run_rfail_test(&config, &props, &testfile),
+      mode_run_pass => run_rpass_test(&config, &props, &testfile),
+      mode_pretty => run_pretty_test(&config, &props, &testfile),
+      mode_debug_info => run_debuginfo_test(&config, &props, &testfile)
     }
 }
 
-fn run_cfail_test(config: config, props: TestProps, testfile: &Path) {
+fn run_cfail_test(config: &config, props: &TestProps, testfile: &Path) {
     let ProcRes = compile_test(config, props, testfile);
 
     if ProcRes.status == 0 {
-        fatal_ProcRes(~"compile-fail test compiled successfully!", ProcRes);
+        fatal_ProcRes(~"compile-fail test compiled successfully!", &ProcRes);
     }
 
-    check_correct_failure_status(ProcRes);
+    check_correct_failure_status(&ProcRes);
 
     let expected_errors = errors::load_errors(testfile);
     if !expected_errors.is_empty() {
         if !props.error_patterns.is_empty() {
             fatal(~"both error pattern and expected errors specified");
         }
-        check_expected_errors(expected_errors, testfile, ProcRes);
+        check_expected_errors(expected_errors, testfile, &ProcRes);
     } else {
-        check_error_patterns(props, testfile, ProcRes);
+        check_error_patterns(props, testfile, &ProcRes);
     }
 }
 
-fn run_rfail_test(config: config, props: TestProps, testfile: &Path) {
+fn run_rfail_test(config: &config, props: &TestProps, testfile: &Path) {
     let ProcRes = if !config.jit {
         let ProcRes = compile_test(config, props, testfile);
 
         if ProcRes.status != 0 {
-            fatal_ProcRes(~"compilation failed!", ProcRes);
+            fatal_ProcRes(~"compilation failed!", &ProcRes);
         }
 
         exec_compiled_test(config, props, testfile)
@@ -74,26 +74,26 @@ fn run_rfail_test(config: config, props: TestProps, testfile: &Path) {
     // The value our Makefile configures valgrind to return on failure
     static valgrind_err: int = 100;
     if ProcRes.status == valgrind_err {
-        fatal_ProcRes(~"run-fail test isn't valgrind-clean!", ProcRes);
+        fatal_ProcRes(~"run-fail test isn't valgrind-clean!", &ProcRes);
     }
 
     match config.target {
 
         ~"arm-linux-androideabi" => {
             if (config.adb_device_status) {
-                check_correct_failure_status(ProcRes);
-                check_error_patterns(props, testfile, ProcRes);
+                check_correct_failure_status(&ProcRes);
+                check_error_patterns(props, testfile, &ProcRes);
             }
         }
 
         _=> {
-            check_correct_failure_status(ProcRes);
-            check_error_patterns(props, testfile, ProcRes);
+            check_correct_failure_status(&ProcRes);
+            check_error_patterns(props, testfile, &ProcRes);
         }
     }
 }
 
-fn check_correct_failure_status(ProcRes: ProcRes) {
+fn check_correct_failure_status(ProcRes: &ProcRes) {
     // The value the rust runtime returns on failure
     static rust_err: int = 101;
     if ProcRes.status != rust_err {
@@ -104,27 +104,27 @@ fn check_correct_failure_status(ProcRes: ProcRes) {
     }
 }
 
-fn run_rpass_test(config: config, props: TestProps, testfile: &Path) {
+fn run_rpass_test(config: &config, props: &TestProps, testfile: &Path) {
     if !config.jit {
         let mut ProcRes = compile_test(config, props, testfile);
 
         if ProcRes.status != 0 {
-            fatal_ProcRes(~"compilation failed!", ProcRes);
+            fatal_ProcRes(~"compilation failed!", &ProcRes);
         }
 
         ProcRes = exec_compiled_test(config, props, testfile);
 
         if ProcRes.status != 0 {
-            fatal_ProcRes(~"test run failed!", ProcRes);
+            fatal_ProcRes(~"test run failed!", &ProcRes);
         }
     } else {
         let ProcRes = jit_test(config, props, testfile);
 
-        if ProcRes.status != 0 { fatal_ProcRes(~"jit failed!", ProcRes); }
+        if ProcRes.status != 0 { fatal_ProcRes(~"jit failed!", &ProcRes); }
     }
 }
 
-fn run_pretty_test(config: config, props: TestProps, testfile: &Path) {
+fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
     if props.pp_exact.is_some() {
         logv(config, ~"testing for exact pretty-printing");
     } else { logv(config, ~"testing for converging pretty-printing"); }
@@ -137,32 +137,33 @@ fn run_pretty_test(config: config, props: TestProps, testfile: &Path) {
     let mut round = 0;
     while round < rounds {
         logv(config, fmt!("pretty-printing round %d", round));
-        let ProcRes = print_source(config, testfile, srcs[round]);
+        let ProcRes = print_source(config, testfile, copy srcs[round]);
 
         if ProcRes.status != 0 {
             fatal_ProcRes(fmt!("pretty-printing failed in round %d", round),
-                          ProcRes);
+                          &ProcRes);
         }
 
-        srcs.push(ProcRes.stdout);
+        let ProcRes{ stdout, _ } = ProcRes;
+        srcs.push(stdout);
         round += 1;
     }
 
     let mut expected =
         match props.pp_exact {
-          Some(file) => {
-            let filepath = testfile.dir_path().push_rel(&file);
+          Some(ref file) => {
+            let filepath = testfile.dir_path().push_rel(file);
             io::read_whole_file_str(&filepath).get()
           }
-          None => { srcs[vec::len(srcs) - 2u] }
+          None => { copy srcs[srcs.len() - 2u] }
         };
-    let mut actual = srcs[vec::len(srcs) - 1u];
+    let mut actual = copy srcs[srcs.len() - 1u];
 
     if props.pp_exact.is_some() {
         // Now we have to care about line endings
         let cr = ~"\r";
-        actual = str::replace(actual, cr, ~"");
-        expected = str::replace(expected, cr, ~"");
+        actual = str::replace(actual, cr, "");
+        expected = str::replace(expected, cr, "");
     }
 
     compare_source(expected, actual);
@@ -171,23 +172,22 @@ fn run_pretty_test(config: config, props: TestProps, testfile: &Path) {
     let ProcRes = typecheck_source(config, props, testfile, actual);
 
     if ProcRes.status != 0 {
-        fatal_ProcRes(~"pretty-printed source does not typecheck", ProcRes);
+        fatal_ProcRes(~"pretty-printed source does not typecheck", &ProcRes);
     }
 
     return;
 
-    fn print_source(config: config, testfile: &Path, src: ~str) -> ProcRes {
+    fn print_source(config: &config, testfile: &Path, src: ~str) -> ProcRes {
         compose_and_run(config, testfile, make_pp_args(config, testfile),
                         ~[], config.compile_lib_path, Some(src))
     }
 
-    fn make_pp_args(config: config, _testfile: &Path) -> ProcArgs {
-        let prog = config.rustc_path;
+    fn make_pp_args(config: &config, _testfile: &Path) -> ProcArgs {
         let args = ~[~"-", ~"--pretty", ~"normal"];
-        return ProcArgs {prog: prog.to_str(), args: args};
+        return ProcArgs {prog: config.rustc_path.to_str(), args: args};
     }
 
-    fn compare_source(expected: ~str, actual: ~str) {
+    fn compare_source(expected: &str, actual: &str) {
         if expected != actual {
             error(~"pretty-printed source does not match expected source");
             let msg =
@@ -207,46 +207,45 @@ actual:\n\
         }
     }
 
-    fn typecheck_source(config: config, props: TestProps,
+    fn typecheck_source(config: &config, props: &TestProps,
                         testfile: &Path, src: ~str) -> ProcRes {
-        compose_and_run_compiler(
-            config, props, testfile,
-            make_typecheck_args(config, props, testfile),
-            Some(src))
+        let args = make_typecheck_args(config, props, testfile);
+        compose_and_run_compiler(config, props, testfile, args, Some(src))
     }
 
-    fn make_typecheck_args(config: config, props: TestProps, testfile: &Path) -> ProcArgs {
-        let prog = config.rustc_path;
+    fn make_typecheck_args(config: &config, props: &TestProps, testfile: &Path) -> ProcArgs {
         let mut args = ~[~"-",
                          ~"--no-trans", ~"--lib",
                          ~"-L", config.build_base.to_str(),
                          ~"-L",
                          aux_output_dir_name(config, testfile).to_str()];
-        args += split_maybe_args(config.rustcflags);
-        args += split_maybe_args(props.compile_flags);
-        return ProcArgs {prog: prog.to_str(), args: args};
+        args += split_maybe_args(&config.rustcflags);
+        args += split_maybe_args(&props.compile_flags);
+        return ProcArgs {prog: config.rustc_path.to_str(), args: args};
     }
 }
 
-fn run_debuginfo_test(config: config, props: TestProps, testfile: &Path) {
+fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
     // do not optimize debuginfo tests
-    let config = match config.rustcflags {
-        Some(flags) => config {
-            rustcflags: Some(str::replace(flags, ~"-O", ~"")),
-            .. config
+    let mut config = match config.rustcflags {
+        Some(ref flags) => config {
+            rustcflags: Some(str::replace(*flags, ~"-O", ~"")),
+            .. copy *config
         },
-        None => config
+        None => copy *config
     };
+    let config = &mut config;
+    let cmds = str::connect(props.debugger_cmds, "\n");
+    let check_lines = copy props.check_lines;
 
     // compile test file (it shoud have 'compile-flags:-g' in the header)
     let mut ProcRes = compile_test(config, props, testfile);
     if ProcRes.status != 0 {
-        fatal_ProcRes(~"compilation failed!", ProcRes);
+        fatal_ProcRes(~"compilation failed!", &ProcRes);
     }
 
     // write debugger script
-    let script_str = str::append(str::connect(props.debugger_cmds, "\n"),
-                                 ~"\nquit\n");
+    let script_str = str::append(cmds, "\nquit\n");
     debug!("script_str = %s", script_str);
     dump_output_file(config, testfile, script_str, ~"debugger.script");
 
@@ -265,13 +264,13 @@ fn run_debuginfo_test(config: config, props: TestProps, testfile: &Path) {
         fatal(~"gdb failed to execute");
     }
 
-    let num_check_lines = vec::len(props.check_lines);
+    let num_check_lines = check_lines.len();
     if num_check_lines > 0 {
         // check if each line in props.check_lines appears in the
         // output (in order)
         let mut i = 0u;
         for str::each_line(ProcRes.stdout) |line| {
-            if props.check_lines[i].trim() == line.trim() {
+            if check_lines[i].trim() == line.trim() {
                 i += 1u;
             }
             if i == num_check_lines {
@@ -281,14 +280,14 @@ fn run_debuginfo_test(config: config, props: TestProps, testfile: &Path) {
         }
         if i != num_check_lines {
             fatal_ProcRes(fmt!("line not found in debugger output: %s"
-                               props.check_lines[i]), ProcRes);
+                               check_lines[i]), &ProcRes);
         }
     }
 }
 
-fn check_error_patterns(props: TestProps,
+fn check_error_patterns(props: &TestProps,
                         testfile: &Path,
-                        ProcRes: ProcRes) {
+                        ProcRes: &ProcRes) {
     if vec::is_empty(props.error_patterns) {
         fatal(~"no error pattern specified in " + testfile.to_str());
     }
@@ -298,26 +297,26 @@ fn check_error_patterns(props: TestProps,
     }
 
     let mut next_err_idx = 0u;
-    let mut next_err_pat = props.error_patterns[next_err_idx];
+    let mut next_err_pat = &props.error_patterns[next_err_idx];
     let mut done = false;
     for str::each_line(ProcRes.stderr) |line| {
-        if str::contains(line, next_err_pat) {
-            debug!("found error pattern %s", next_err_pat);
+        if str::contains(line, *next_err_pat) {
+            debug!("found error pattern %s", *next_err_pat);
             next_err_idx += 1u;
-            if next_err_idx == vec::len(props.error_patterns) {
+            if next_err_idx == props.error_patterns.len() {
                 debug!("found all error patterns");
                 done = true;
                 break;
             }
-            next_err_pat = props.error_patterns[next_err_idx];
+            next_err_pat = &props.error_patterns[next_err_idx];
         }
     }
     if done { return; }
 
     let missing_patterns =
         vec::slice(props.error_patterns, next_err_idx,
-                   vec::len(props.error_patterns));
-    if vec::len(missing_patterns) == 1u {
+                   props.error_patterns.len());
+    if missing_patterns.len() == 1u {
         fatal_ProcRes(fmt!("error pattern '%s' not found!",
                            missing_patterns[0]), ProcRes);
     } else {
@@ -330,11 +329,11 @@ fn check_error_patterns(props: TestProps,
 
 fn check_expected_errors(expected_errors: ~[errors::ExpectedError],
                          testfile: &Path,
-                         ProcRes: ProcRes) {
+                         ProcRes: &ProcRes) {
 
     // true if we found the error in question
     let mut found_flags = vec::from_elem(
-        vec::len(expected_errors), false);
+        expected_errors.len(), false);
 
     if ProcRes.status == 0 {
         fatal(~"process did not return an error status");
@@ -378,16 +377,16 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError],
         }
     }
 
-    for uint::range(0u, vec::len(found_flags)) |i| {
+    for uint::range(0u, found_flags.len()) |i| {
         if !found_flags[i] {
-            let ee = expected_errors[i];
+            let ee = &expected_errors[i];
             fatal_ProcRes(fmt!("expected %s on line %u not found: %s",
                                ee.kind, ee.line, ee.msg), ProcRes);
         }
     }
 }
 
-fn is_compiler_error_or_warning(line: ~str) -> bool {
+fn is_compiler_error_or_warning(line: &str) -> bool {
     let mut i = 0u;
     return
         scan_until_char(line, ':', &mut i) &&
@@ -401,11 +400,11 @@ fn is_compiler_error_or_warning(line: ~str) -> bool {
         scan_char(line, ':', &mut i) &&
         scan_integer(line, &mut i) &&
         scan_char(line, ' ', &mut i) &&
-        (scan_string(line, ~"error", &mut i) ||
-         scan_string(line, ~"warning", &mut i));
+        (scan_string(line, "error", &mut i) ||
+         scan_string(line, "warning", &mut i));
 }
 
-fn scan_until_char(haystack: ~str, needle: char, idx: &mut uint) -> bool {
+fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool {
     if *idx >= haystack.len() {
         return false;
     }
@@ -417,7 +416,7 @@ fn scan_until_char(haystack: ~str, needle: char, idx: &mut uint) -> bool {
     return true;
 }
 
-fn scan_char(haystack: ~str, needle: char, idx: &mut uint) -> bool {
+fn scan_char(haystack: &str, needle: char, idx: &mut uint) -> bool {
     if *idx >= haystack.len() {
         return false;
     }
@@ -429,7 +428,7 @@ fn scan_char(haystack: ~str, needle: char, idx: &mut uint) -> bool {
     return true;
 }
 
-fn scan_integer(haystack: ~str, idx: &mut uint) -> bool {
+fn scan_integer(haystack: &str, idx: &mut uint) -> bool {
     let mut i = *idx;
     while i < haystack.len() {
         let range = str::char_range_at(haystack, i);
@@ -445,7 +444,7 @@ fn scan_integer(haystack: ~str, idx: &mut uint) -> bool {
     return true;
 }
 
-fn scan_string(haystack: ~str, needle: ~str, idx: &mut uint) -> bool {
+fn scan_string(haystack: &str, needle: &str, idx: &mut uint) -> bool {
     let mut haystack_i = *idx;
     let mut needle_i = 0u;
     while needle_i < needle.len() {
@@ -466,34 +465,29 @@ struct ProcArgs {prog: ~str, args: ~[~str]}
 
 struct ProcRes {status: int, stdout: ~str, stderr: ~str, cmdline: ~str}
 
-fn compile_test(config: config, props: TestProps,
+fn compile_test(config: &config, props: &TestProps,
                 testfile: &Path) -> ProcRes {
     compile_test_(config, props, testfile, [])
 }
 
-fn jit_test(config: config, props: TestProps, testfile: &Path) -> ProcRes {
+fn jit_test(config: &config, props: &TestProps, testfile: &Path) -> ProcRes {
     compile_test_(config, props, testfile, [~"--jit"])
 }
 
-fn compile_test_(config: config, props: TestProps,
+fn compile_test_(config: &config, props: &TestProps,
                  testfile: &Path, extra_args: &[~str]) -> ProcRes {
     let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
-    compose_and_run_compiler(
-        config, props, testfile,
-        make_compile_args(config, props, link_args + extra_args,
-                          make_exe_name, testfile),
-        None)
+    let args = make_compile_args(config, props, link_args + extra_args,
+                                 make_exe_name, testfile);
+    compose_and_run_compiler(config, props, testfile, args, None)
 }
 
-fn exec_compiled_test(config: config, props: TestProps,
+fn exec_compiled_test(config: &config, props: &TestProps,
                       testfile: &Path) -> ProcRes {
 
     // If testing the new runtime then set the RUST_NEWRT env var
-    let env = if config.newrt {
-        props.exec_env + ~[(~"RUST_NEWRT", ~"1")]
-    } else {
-        props.exec_env
-    };
+    let env = copy props.exec_env;
+    let env = if config.newrt { env + &[(~"RUST_NEWRT", ~"1")] } else { env };
 
     match config.target {
 
@@ -515,8 +509,8 @@ fn exec_compiled_test(config: config, props: TestProps,
 }
 
 fn compose_and_run_compiler(
-    config: config,
-    props: TestProps,
+    config: &config,
+    props: &TestProps,
     testfile: &Path,
     args: ProcArgs,
     input: Option<~str>) -> ProcRes {
@@ -539,7 +533,7 @@ fn compose_and_run_compiler(
             fatal_ProcRes(
                 fmt!("auxiliary build of %s failed to compile: ",
                      abs_ab.to_str()),
-                auxres);
+                &auxres);
         }
 
         match config.target {
@@ -561,78 +555,70 @@ fn compose_and_run_compiler(
 fn ensure_dir(path: &Path) {
     if os::path_is_dir(path) { return; }
     if !os::make_dir(path, 0x1c0i32) {
-        fail!(fmt!("can't make dir %s", path.to_str()));
+        fail!("can't make dir %s", path.to_str());
     }
 }
 
-fn compose_and_run(config: config, testfile: &Path,
-                   ProcArgs: ProcArgs,
+fn compose_and_run(config: &config, testfile: &Path,
+                   ProcArgs{ args, prog }: ProcArgs,
                    procenv: ~[(~str, ~str)],
-                   lib_path: ~str,
+                   lib_path: &str,
                    input: Option<~str>) -> ProcRes {
     return program_output(config, testfile, lib_path,
-                       ProcArgs.prog, ProcArgs.args, procenv, input);
+                          prog, args, procenv, input);
 }
 
-fn make_compile_args(config: config, props: TestProps, extras: ~[~str],
-                     xform: &fn(config, (&Path)) -> Path,
+fn make_compile_args(config: &config, props: &TestProps, extras: ~[~str],
+                     xform: &fn(&config, (&Path)) -> Path,
                      testfile: &Path) -> ProcArgs {
-    let prog = config.rustc_path;
     let mut args = ~[testfile.to_str(),
                      ~"-o", xform(config, testfile).to_str(),
                      ~"-L", config.build_base.to_str()]
         + extras;
-    args += split_maybe_args(config.rustcflags);
-    args += split_maybe_args(props.compile_flags);
-    return ProcArgs {prog: prog.to_str(), args: args};
+    args += split_maybe_args(&config.rustcflags);
+    args += split_maybe_args(&props.compile_flags);
+    return ProcArgs {prog: config.rustc_path.to_str(), args: args};
 }
 
-fn make_lib_name(config: config, auxfile: &Path, testfile: &Path) -> Path {
+fn make_lib_name(config: &config, auxfile: &Path, testfile: &Path) -> Path {
     // what we return here is not particularly important, as it
     // happens; rustc ignores everything except for the directory.
     let auxname = output_testname(auxfile);
     aux_output_dir_name(config, testfile).push_rel(&auxname)
 }
 
-fn make_exe_name(config: config, testfile: &Path) -> Path {
+fn make_exe_name(config: &config, testfile: &Path) -> Path {
     Path(output_base_name(config, testfile).to_str() +
             str::to_owned(os::EXE_SUFFIX))
 }
 
-fn make_run_args(config: config, _props: TestProps, testfile: &Path) ->
+fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) ->
    ProcArgs {
-    let toolargs = {
-            // If we've got another tool to run under (valgrind),
-            // then split apart its command
-            let runtool =
-                match config.runtool {
-                  Some(s) => Some(s),
-                  None => None
-                };
-            split_maybe_args(runtool)
-        };
+    // If we've got another tool to run under (valgrind),
+    // then split apart its command
+    let toolargs = split_maybe_args(&config.runtool);
 
-    let args = toolargs + ~[make_exe_name(config, testfile).to_str()];
-    return ProcArgs {prog: args[0],
-                     args: vec::slice(args, 1, args.len()).to_vec()};
+    let mut args = toolargs + ~[make_exe_name(config, testfile).to_str()];
+    let prog = args.shift();
+    return ProcArgs {prog: prog, args: args};
 }
 
-fn split_maybe_args(argstr: Option<~str>) -> ~[~str] {
+fn split_maybe_args(argstr: &Option<~str>) -> ~[~str] {
     fn rm_whitespace(v: ~[~str]) -> ~[~str] {
         v.filtered(|s| !str::is_whitespace(*s))
     }
 
-    match argstr {
-        Some(s) => {
+    match *argstr {
+        Some(ref s) => {
             let mut ss = ~[];
-            for str::each_split_char(s, ' ') |s| { ss.push(s.to_owned()) }
+            for str::each_split_char(*s, ' ') |s| { ss.push(s.to_owned()) }
             rm_whitespace(ss)
         }
         None => ~[]
     }
 }
 
-fn program_output(config: config, testfile: &Path, lib_path: ~str, prog: ~str,
+fn program_output(config: &config, testfile: &Path, lib_path: &str, prog: ~str,
                   args: ~[~str], env: ~[(~str, ~str)],
                   input: Option<~str>) -> ProcRes {
     let cmdline =
@@ -641,11 +627,12 @@ fn program_output(config: config, testfile: &Path, lib_path: ~str, prog: ~str,
             logv(config, fmt!("executing %s", cmdline));
             cmdline
         };
-    let res = procsrv::run(lib_path, prog, args, env, input);
-    dump_output(config, testfile, res.out, res.err);
-    return ProcRes {status: res.status,
-         stdout: res.out,
-         stderr: res.err,
+    let procsrv::Result{ out, err, status } =
+            procsrv::run(lib_path, prog, args, env, input);
+    dump_output(config, testfile, out, err);
+    return ProcRes {status: status,
+         stdout: out,
+         stderr: err,
          cmdline: cmdline};
 }
 
@@ -653,41 +640,41 @@ fn program_output(config: config, testfile: &Path, lib_path: ~str, prog: ~str,
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
 #[cfg(target_os = "freebsd")]
-fn make_cmdline(_libpath: ~str, prog: ~str, args: ~[~str]) -> ~str {
+fn make_cmdline(_libpath: &str, prog: &str, args: &[~str]) -> ~str {
     fmt!("%s %s", prog, str::connect(args, ~" "))
 }
 
 #[cfg(target_os = "win32")]
-fn make_cmdline(libpath: ~str, prog: ~str, args: ~[~str]) -> ~str {
+fn make_cmdline(libpath: &str, prog: &str, args: &[~str]) -> ~str {
     fmt!("%s %s %s", lib_path_cmd_prefix(libpath), prog,
          str::connect(args, ~" "))
 }
 
 // Build the LD_LIBRARY_PATH variable as it would be seen on the command line
 // for diagnostic purposes
-fn lib_path_cmd_prefix(path: ~str) -> ~str {
+fn lib_path_cmd_prefix(path: &str) -> ~str {
     fmt!("%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path))
 }
 
-fn dump_output(config: config, testfile: &Path, out: ~str, err: ~str) {
-    dump_output_file(config, testfile, out, ~"out");
-    dump_output_file(config, testfile, err, ~"err");
+fn dump_output(config: &config, testfile: &Path, out: &str, err: &str) {
+    dump_output_file(config, testfile, out, "out");
+    dump_output_file(config, testfile, err, "err");
     maybe_dump_to_stdout(config, out, err);
 }
 
-fn dump_output_file(config: config, testfile: &Path,
-                    out: ~str, extension: ~str) {
+fn dump_output_file(config: &config, testfile: &Path,
+                    out: &str, extension: &str) {
     let outfile = make_out_name(config, testfile, extension);
     let writer =
         io::file_writer(&outfile, ~[io::Create, io::Truncate]).get();
     writer.write_str(out);
 }
 
-fn make_out_name(config: config, testfile: &Path, extension: ~str) -> Path {
+fn make_out_name(config: &config, testfile: &Path, extension: &str) -> Path {
     output_base_name(config, testfile).with_filetype(extension)
 }
 
-fn aux_output_dir_name(config: config, testfile: &Path) -> Path {
+fn aux_output_dir_name(config: &config, testfile: &Path) -> Path {
     output_base_name(config, testfile).with_filetype("libaux")
 }
 
@@ -695,13 +682,13 @@ fn output_testname(testfile: &Path) -> Path {
     Path(testfile.filestem().get())
 }
 
-fn output_base_name(config: config, testfile: &Path) -> Path {
+fn output_base_name(config: &config, testfile: &Path) -> Path {
     config.build_base
         .push_rel(&output_testname(testfile))
         .with_filetype(config.stage_id)
 }
 
-fn maybe_dump_to_stdout(config: config, out: ~str, err: ~str) {
+fn maybe_dump_to_stdout(config: &config, out: &str, err: &str) {
     if config.verbose {
         let sep1 = fmt!("------%s------------------------------", ~"stdout");
         let sep2 = fmt!("------%s------------------------------", ~"stderr");
@@ -718,7 +705,7 @@ fn error(err: ~str) { io::stdout().write_line(fmt!("\nerror: %s", err)); }
 
 fn fatal(err: ~str) -> ! { error(err); fail!(); }
 
-fn fatal_ProcRes(err: ~str, ProcRes: ProcRes) -> ! {
+fn fatal_ProcRes(err: ~str, ProcRes: &ProcRes) -> ! {
     let msg =
         fmt!("\n\
 error: %s\n\
@@ -737,21 +724,20 @@ stderr:\n\
     fail!();
 }
 
-fn _arm_exec_compiled_test(config: config, props: TestProps,
+fn _arm_exec_compiled_test(config: &config, props: &TestProps,
                       testfile: &Path) -> ProcRes {
 
     let args = make_run_args(config, props, testfile);
-    let cmdline = make_cmdline(~"", args.prog, args.args);
+    let cmdline = make_cmdline("", args.prog, args.args);
 
     // get bare program string
     let mut tvec = ~[];
-    let tstr = args.prog;
-    for str::each_split_char(tstr, '/') |ts| { tvec.push(ts.to_owned()) }
+    for str::each_split_char(args.prog, '/') |ts| { tvec.push(ts.to_owned()) }
     let prog_short = tvec.pop();
 
     // copy to target
-    let copy_result = procsrv::run(~"", config.adb_path,
-        ~[~"push", args.prog, config.adb_test_dir],
+    let copy_result = procsrv::run("", config.adb_path,
+        [~"push", copy args.prog, copy config.adb_test_dir],
         ~[(~"",~"")], Some(~""));
 
     if config.verbose {
@@ -767,7 +753,6 @@ fn _arm_exec_compiled_test(config: config, props: TestProps,
     // to stdout and stderr separately but to stdout only
     let mut newargs_out = ~[];
     let mut newargs_err = ~[];
-    let subargs = args.args;
     newargs_out.push(~"shell");
     newargs_err.push(~"shell");
 
@@ -780,7 +765,7 @@ fn _arm_exec_compiled_test(config: config, props: TestProps,
     newcmd_err.push_str(fmt!("LD_LIBRARY_PATH=%s %s/%s",
         config.adb_test_dir, config.adb_test_dir, prog_short));
 
-    for vec::each(subargs) |tv| {
+    for args.args.each |tv| {
         newcmd_out.push_str(" ");
         newcmd_err.push_str(" ");
         newcmd_out.push_str(tv.to_owned());
@@ -793,26 +778,28 @@ fn _arm_exec_compiled_test(config: config, props: TestProps,
     newargs_out.push(newcmd_out);
     newargs_err.push(newcmd_err);
 
-    let exe_result_out = procsrv::run(~"", config.adb_path,
-        newargs_out, ~[(~"",~"")], Some(~""));
-    let exe_result_err = procsrv::run(~"", config.adb_path,
-        newargs_err, ~[(~"",~"")], Some(~""));
+    let procsrv::Result{ out: out_out, err: _out_err, status: out_status } =
+            procsrv::run(~"", config.adb_path, newargs_out, ~[(~"",~"")],
+                         Some(~""));
+    let procsrv::Result{ out: err_out, err: _err_err, status: _err_status } =
+            procsrv::run(~"", config.adb_path, newargs_err, ~[(~"",~"")],
+                         Some(~""));
 
-    dump_output(config, testfile, exe_result_out.out, exe_result_err.out);
+    dump_output(config, testfile, out_out, err_out);
 
-    match exe_result_err.out {
-        ~"" => ProcRes {status: exe_result_out.status, stdout: exe_result_out.out,
-            stderr: exe_result_err.out, cmdline: cmdline },
-        _   => ProcRes {status: 101, stdout: exe_result_out.out,
-            stderr: exe_result_err.out, cmdline: cmdline }
+    match err_out {
+        ~"" => ProcRes {status: out_status, stdout: out_out,
+            stderr: err_out, cmdline: cmdline },
+        _   => ProcRes {status: 101, stdout: out_out,
+            stderr: err_out, cmdline: cmdline }
     }
 }
 
-fn _dummy_exec_compiled_test(config: config, props: TestProps,
+fn _dummy_exec_compiled_test(config: &config, props: &TestProps,
                       testfile: &Path) -> ProcRes {
 
     let args = make_run_args(config, props, testfile);
-    let cmdline = make_cmdline(~"", args.prog, args.args);
+    let cmdline = make_cmdline("", args.prog, args.args);
 
     match config.mode {
         mode_run_fail => ProcRes {status: 101, stdout: ~"",
@@ -822,7 +809,7 @@ fn _dummy_exec_compiled_test(config: config, props: TestProps,
     }
 }
 
-fn _arm_push_aux_shared_library(config: config, testfile: &Path) {
+fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
     let tstr = aux_output_dir_name(config, testfile).to_str();
 
     for os::list_dir_path(&Path(tstr)).each |file| {
@@ -830,7 +817,7 @@ fn _arm_push_aux_shared_library(config: config, testfile: &Path) {
         if (file.filetype() == Some(~".so")) {
 
             let copy_result = procsrv::run(~"", config.adb_path,
-                ~[~"push", file.to_str(), config.adb_test_dir],
+                ~[~"push", file.to_str(), copy config.adb_test_dir],
                 ~[(~"",~"")], Some(~""));
 
             if config.verbose {
diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs
index 51579c33e9a..05e5d902a47 100644
--- a/src/compiletest/util.rs
+++ b/src/compiletest/util.rs
@@ -12,7 +12,7 @@ use common::config;
 
 use core::os::getenv;
 
-pub fn make_new_path(path: ~str) -> ~str {
+pub fn make_new_path(path: &str) -> ~str {
 
     // Windows just uses PATH as the library search path, so we have to
     // maintain the current value while adding our own
@@ -20,7 +20,7 @@ pub fn make_new_path(path: ~str) -> ~str {
       Some(curr) => {
         fmt!("%s%s%s", path, path_div(), curr)
       }
-      None => path
+      None => path.to_str()
     }
 }
 
@@ -42,7 +42,7 @@ pub fn path_div() -> ~str { ~":" }
 #[cfg(target_os = "win32")]
 pub fn path_div() -> ~str { ~";" }
 
-pub fn logv(config: config, s: ~str) {
+pub fn logv(config: &config, s: ~str) {
     debug!("%s", s);
     if config.verbose { io::println(s); }
 }
diff --git a/src/etc/extract-tests.py b/src/etc/extract-tests.py
index 5754d234afb..12740a5616b 100644
--- a/src/etc/extract-tests.py
+++ b/src/etc/extract-tests.py
@@ -60,7 +60,6 @@ while cur < len(lines):
             if not re.search(r"\bextern mod std\b", block):
                 block = "extern mod std;\n" + block
             block = """#[ forbid(ctypes) ];
-#[ forbid(deprecated_mode) ];
 #[ forbid(deprecated_pattern) ];
 #[ forbid(implicit_copies) ];
 #[ forbid(non_implicitly_copyable_typarams) ];
@@ -68,12 +67,9 @@ while cur < len(lines):
 #[ forbid(type_limits) ];
 #[ forbid(unrecognized_lint) ];
 #[ forbid(unused_imports) ];
-#[ forbid(vecs_implicitly_copyable) ];
 #[ forbid(while_true) ];
 
-#[ warn(deprecated_self) ];
-#[ warn(non_camel_case_types) ];
-#[ warn(structural_records) ];\n
+#[ warn(non_camel_case_types) ];\n
 """ + block
             if xfail:
                 block = "// xfail-test\n" + block
diff --git a/src/etc/vim/after/syntax/rust.vim b/src/etc/vim/after/syntax/rust.vim
index 75afe3d0368..1ab8394e565 100644
--- a/src/etc/vim/after/syntax/rust.vim
+++ b/src/etc/vim/after/syntax/rust.vim
@@ -11,10 +11,6 @@ syn match rustRightArrowHead contained ">" conceal cchar= 
 syn match rustRightArrowTail contained "-" conceal cchar=⟶
 syn match rustNiceOperator "->" contains=rustRightArrowHead,rustRightArrowTail
 
-syn match rustLeftRightArrowHead contained ">" conceal cchar= 
-syn match rustLeftRightArrowTail contained "<-" conceal cchar=⟷
-syn match rustNiceOperator "<->" contains=rustLeftRightArrowHead,rustLeftRightArrowTail
-
 syn match rustFatRightArrowHead contained ">" conceal cchar= 
 syn match rustFatRightArrowTail contained "=" conceal cchar=⟹
 syn match rustNiceOperator "=>" contains=rustFatRightArrowHead,rustFatRightArrowTail
diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim
index 3b5324f5cce..cd794df0a8d 100644
--- a/src/etc/vim/syntax/rust.vim
+++ b/src/etc/vim/syntax/rust.vim
@@ -15,7 +15,7 @@ syn keyword   rustOperator    as
 
 syn keyword   rustKeyword     break copy do drop extern
 syn keyword   rustKeyword     for if impl let log
-syn keyword   rustKeyword     copy do drop extern
+syn keyword   rustKeyword     copy do extern
 syn keyword   rustKeyword     for impl let log
 syn keyword   rustKeyword     loop mod once priv pub
 syn keyword   rustKeyword     return
@@ -28,8 +28,8 @@ syn keyword   rustStorage     const mut ref static
 syn match     rustIdentifier  contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
 syn match     rustFuncName    "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
 
-" Reserved words
-"syn keyword   rustKeyword     m32 m64 m128 f80 f16 f128 be " These are obsolete
+" reserved
+syn keyword   rustKeyword     be
 
 syn keyword   rustType        int uint float char bool u8 u16 u32 u64 f32
 syn keyword   rustType        f64 i8 i16 i32 i64 str Self
diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs
index a3981dd8491..93bbf8fb662 100644
--- a/src/libcore/at_vec.rs
+++ b/src/libcore/at_vec.rs
@@ -11,8 +11,10 @@
 //! Managed vectors
 
 use cast::transmute;
+use container::Container;
 use kinds::Copy;
 use old_iter;
+use old_iter::BaseIter;
 use option::Option;
 use sys;
 use uint;
@@ -147,7 +149,7 @@ pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> @[T] {
  * Creates and initializes an immutable managed vector by moving all the
  * elements from an owned vector.
  */
-pub fn from_owned<T>(v: ~[T]) -> @[T] {
+pub fn to_managed_consume<T>(v: ~[T]) -> @[T] {
     let mut av = @[];
     unsafe {
         raw::reserve(&mut av, v.len());
@@ -162,7 +164,7 @@ pub fn from_owned<T>(v: ~[T]) -> @[T] {
  * Creates and initializes an immutable managed vector by copying all the
  * elements of a slice.
  */
-pub fn from_slice<T:Copy>(v: &[T]) -> @[T] {
+pub fn to_managed<T:Copy>(v: &[T]) -> @[T] {
     from_fn(v.len(), |i| v[i])
 }
 
@@ -302,20 +304,20 @@ mod test {
     }
 
     #[test]
-    fn test_from_owned() {
-        assert!(from_owned::<int>(~[]) == @[]);
-        assert!(from_owned(~[true]) == @[true]);
-        assert!(from_owned(~[1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]);
-        assert!(from_owned(~[~"abc", ~"123"]) == @[~"abc", ~"123"]);
-        assert!(from_owned(~[~[42]]) == @[~[42]]);
+    fn test_to_managed_consume() {
+        assert!(to_managed_consume::<int>(~[]) == @[]);
+        assert!(to_managed_consume(~[true]) == @[true]);
+        assert!(to_managed_consume(~[1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]);
+        assert!(to_managed_consume(~[~"abc", ~"123"]) == @[~"abc", ~"123"]);
+        assert!(to_managed_consume(~[~[42]]) == @[~[42]]);
     }
 
     #[test]
-    fn test_from_slice() {
-        assert!(from_slice::<int>([]) == @[]);
-        assert!(from_slice([true]) == @[true]);
-        assert!(from_slice([1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]);
-        assert!(from_slice([@"abc", @"123"]) == @[@"abc", @"123"]);
-        assert!(from_slice([@[42]]) == @[@[42]]);
+    fn test_to_managed() {
+        assert!(to_managed::<int>([]) == @[]);
+        assert!(to_managed([true]) == @[true]);
+        assert!(to_managed([1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]);
+        assert!(to_managed([@"abc", @"123"]) == @[@"abc", @"123"]);
+        assert!(to_managed([@[42]]) == @[@[42]]);
     }
 }
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 18e75fb1aa9..87e8d0525e5 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -21,10 +21,17 @@ Similar to a mutable option type, but friendlier.
 */
 
 #[mutable]
+#[deriving(Clone)]
 pub struct Cell<T> {
     priv value: Option<T>
 }
 
+impl<T: DeepClone> DeepClone for Cell<T> {
+    fn deep_clone(&self) -> Cell<T> {
+        Cell{value: self.value.deep_clone()}
+    }
+}
+
 impl<T:cmp::Eq> cmp::Eq for Cell<T> {
     fn eq(&self, other: &Cell<T>) -> bool {
         (self.value) == (other.value)
@@ -44,21 +51,21 @@ pub fn empty_cell<T>() -> Cell<T> {
 pub impl<T> Cell<T> {
     /// Yields the value, failing if the cell is empty.
     fn take(&self) -> T {
-        let self = unsafe { transmute_mut(self) };
-        if self.is_empty() {
-            fail!(~"attempt to take an empty cell");
+        let this = unsafe { transmute_mut(self) };
+        if this.is_empty() {
+            fail!("attempt to take an empty cell");
         }
 
-        replace(&mut self.value, None).unwrap()
+        replace(&mut this.value, None).unwrap()
     }
 
     /// Returns the value, failing if the cell is full.
     fn put_back(&self, value: T) {
-        let self = unsafe { transmute_mut(self) };
-        if !self.is_empty() {
-            fail!(~"attempt to put a value back into a full cell");
+        let this = unsafe { transmute_mut(self) };
+        if !this.is_empty() {
+            fail!("attempt to put a value back into a full cell");
         }
-        self.value = Some(value);
+        this.value = Some(value);
     }
 
     /// Returns true if the cell is empty and false if the cell is full.
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index a9c46b81f86..68f283f1ad8 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -145,7 +145,7 @@ pub fn is_digit_radix(c: char, radix: uint) -> bool {
 #[inline]
 pub fn to_digit(c: char, radix: uint) -> Option<uint> {
     if radix > 36 {
-        fail!(fmt!("to_digit: radix %? is to high (maximum 36)", radix));
+        fail!("to_digit: radix %? is to high (maximum 36)", radix);
     }
     let val = match c {
       '0' .. '9' => c as uint - ('0' as uint),
@@ -168,7 +168,7 @@ pub fn to_digit(c: char, radix: uint) -> Option<uint> {
 #[inline]
 pub fn from_digit(num: uint, radix: uint) -> Option<char> {
     if radix > 36 {
-        fail!(fmt!("from_digit: radix %? is to high (maximum 36)", num));
+        fail!("from_digit: radix %? is to high (maximum 36)", num);
     }
     if num < radix {
         if num < 10 {
@@ -241,7 +241,7 @@ pub fn len_utf8_bytes(c: char) -> uint {
     else if code < max_two_b { 2u }
     else if code < max_three_b { 3u }
     else if code < max_four_b { 4u }
-    else { fail!(~"invalid character!") }
+    else { fail!("invalid character!") }
 }
 
 #[cfg(not(test))]
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 9da970918b0..4d2b5998b44 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -22,18 +22,15 @@ by convention implementing the `Clone` trait and calling the
 
 */
 
+use core::kinds::Const;
+
 pub trait Clone {
-    /// Return a deep copy of the owned object tree. Managed boxes are cloned with a shallow copy.
+    /// Return a deep copy of the owned object tree. Types with shared ownership like managed boxes
+    /// are cloned with a shallow copy.
     fn clone(&self) -> Self;
 }
 
-impl Clone for () {
-    /// Return a copy of the value.
-    #[inline(always)]
-    fn clone(&self) -> () { () }
-}
-
-impl<T:Clone> Clone for ~T {
+impl<T: Clone> Clone for ~T {
     /// Return a deep copy of the owned box.
     #[inline(always)]
     fn clone(&self) -> ~T { ~(**self).clone() }
@@ -51,10 +48,16 @@ impl<T> Clone for @mut T {
     fn clone(&self) -> @mut T { *self }
 }
 
+impl<'self, T> Clone for &'self T {
+    /// Return a shallow copy of the borrowed pointer.
+    #[inline(always)]
+    fn clone(&self) -> &'self T { *self }
+}
+
 macro_rules! clone_impl(
     ($t:ty) => {
         impl Clone for $t {
-            /// Return a copy of the value.
+            /// Return a deep copy of the value.
             #[inline(always)]
             fn clone(&self) -> $t { *self }
         }
@@ -77,28 +80,103 @@ clone_impl!(float)
 clone_impl!(f32)
 clone_impl!(f64)
 
+clone_impl!(())
 clone_impl!(bool)
 clone_impl!(char)
 
+pub trait DeepClone {
+    /// Return a deep copy of the object tree. Types with shared ownership are also copied via a
+    /// deep copy, unlike `Clone`.
+    fn deep_clone(&self) -> Self;
+}
+
+impl<T: DeepClone> DeepClone for ~T {
+    /// Return a deep copy of the owned box.
+    #[inline(always)]
+    fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }
+}
+
+// FIXME: #6525: should also be implemented for `T: Owned + DeepClone`
+impl<T: Const + DeepClone> DeepClone for @T {
+    /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing
+    /// a deep clone of a potentially cyclical type.
+    #[inline(always)]
+    fn deep_clone(&self) -> @T { @(**self).deep_clone() }
+}
+
+// FIXME: #6525: should also be implemented for `T: Owned + DeepClone`
+impl<T: Const + DeepClone> DeepClone for @mut T {
+    /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing
+    /// a deep clone of a potentially cyclical type.
+    #[inline(always)]
+    fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }
+}
+
+macro_rules! deep_clone_impl(
+    ($t:ty) => {
+        impl DeepClone for $t {
+            /// Return a deep copy of the value.
+            #[inline(always)]
+            fn deep_clone(&self) -> $t { *self }
+        }
+    }
+)
+
+deep_clone_impl!(int)
+deep_clone_impl!(i8)
+deep_clone_impl!(i16)
+deep_clone_impl!(i32)
+deep_clone_impl!(i64)
+
+deep_clone_impl!(uint)
+deep_clone_impl!(u8)
+deep_clone_impl!(u16)
+deep_clone_impl!(u32)
+deep_clone_impl!(u64)
+
+deep_clone_impl!(float)
+deep_clone_impl!(f32)
+deep_clone_impl!(f64)
+
+deep_clone_impl!(())
+deep_clone_impl!(bool)
+deep_clone_impl!(char)
+
 #[test]
 fn test_owned_clone() {
-    let a: ~int = ~5i;
+    let a = ~5i;
     let b: ~int = a.clone();
     assert!(a == b);
 }
 
 #[test]
 fn test_managed_clone() {
-    let a: @int = @5i;
+    let a = @5i;
     let b: @int = a.clone();
     assert!(a == b);
 }
 
 #[test]
+fn test_managed_mut_deep_clone() {
+    let x = @mut 5i;
+    let y: @mut int = x.deep_clone();
+    *x = 20;
+    assert_eq!(*y, 5);
+}
+
+#[test]
 fn test_managed_mut_clone() {
-    let a: @mut int = @mut 5i;
+    let a = @mut 5i;
     let b: @mut int = a.clone();
     assert!(a == b);
     *b = 10;
     assert!(a == b);
 }
+
+#[test]
+fn test_borrowed_clone() {
+    let x = 5i;
+    let y: &int = &x;
+    let z: &int = (&y).clone();
+    assert_eq!(*z, 5);
+}
diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs
index b1f60ec4690..34c60202b3f 100644
--- a/src/libcore/comm.rs
+++ b/src/libcore/comm.rs
@@ -13,14 +13,15 @@ Message passing
 */
 
 use cast::{transmute, transmute_mut};
+use container::Container;
 use either::{Either, Left, Right};
 use kinds::Owned;
 use option::{Option, Some, None};
 use uint;
-use unstable;
 use vec;
-use unstable::Exclusive;
+use vec::OwnedVector;
 use util::replace;
+use unstable::sync::{Exclusive, exclusive};
 
 use pipes::{recv, try_recv, wait_many, peek, PacketHeader};
 
@@ -209,7 +210,7 @@ impl<T: Owned> Peekable<T> for Port<T> {
             let mut endp = replace(self_endp, None);
             let peek = match endp {
                 Some(ref mut endp) => peek(endp),
-                None => fail!(~"peeking empty stream")
+                None => fail!("peeking empty stream")
             };
             *self_endp = endp;
             peek
@@ -221,7 +222,7 @@ impl<T: Owned> Selectable for Port<T> {
     fn header(&mut self) -> *mut PacketHeader {
             match self.endp {
                 Some(ref mut endp) => endp.header(),
-                None => fail!(~"peeking empty stream")
+                None => fail!("peeking empty stream")
             }
     }
 }
@@ -304,7 +305,7 @@ pub struct SharedChan<T> {
 impl<T: Owned> SharedChan<T> {
     /// Converts a `chan` into a `shared_chan`.
     pub fn new(c: Chan<T>) -> SharedChan<T> {
-        SharedChan { ch: unstable::exclusive(c) }
+        SharedChan { ch: exclusive(c) }
     }
 }
 
@@ -521,7 +522,7 @@ pub fn select2i<A:Selectable, B:Selectable>(a: &mut A, b: &mut B)
     match wait_many(endpoints) {
         0 => Left(()),
         1 => Right(()),
-        _ => fail!(~"wait returned unexpected index"),
+        _ => fail!("wait returned unexpected index"),
     }
 }
 
@@ -577,7 +578,7 @@ impl<T:Owned,
 #[cfg(test)]
 mod test {
     use either::Right;
-    use super::{Chan, Port, oneshot, recv_one, stream};
+    use super::{Chan, Port, oneshot, stream};
 
     #[test]
     fn test_select2() {
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index d029fbc07f6..96b5e1b781d 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -68,48 +68,6 @@ they contained the following prologue:
 #[cfg(test)] pub use ops = realcore::ops;
 #[cfg(test)] pub use cmp = realcore::cmp;
 
-/* Reexported core operators */
-
-pub use kinds::{Const, Copy, Owned};
-pub use ops::{Drop};
-pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
-pub use ops::{BitAnd, BitOr, BitXor};
-pub use ops::{Shl, Shr, Index};
-
-
-/* Reexported types and traits */
-
-pub use option::{Option, Some, None};
-pub use result::{Result, Ok, Err};
-
-pub use path::Path;
-pub use path::GenericPath;
-pub use path::WindowsPath;
-pub use path::PosixPath;
-
-pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
-pub use str::{StrSlice};
-pub use container::{Container, Mutable};
-pub use vec::{CopyableVector, ImmutableVector};
-pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
-pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
-pub use old_iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
-pub use old_iter::{CopyableOrderedIter, CopyableNonstrictIter};
-pub use old_iter::{ExtendedMutableIter};
-pub use iter::Times;
-
-pub use num::{Num, NumCast};
-pub use num::{Orderable, Signed, Unsigned, Round};
-pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
-pub use num::{Integer, Fractional, Real, RealExt};
-pub use num::{Bitwise, BitCount, Bounded};
-pub use num::{Primitive, Int, Float};
-
-pub use ptr::Ptr;
-pub use from_str::FromStr;
-pub use to_str::ToStr;
-pub use clone::Clone;
-
 // On Linux, link to the runtime with -lrt.
 #[cfg(target_os = "linux")]
 #[doc(hidden)]
@@ -238,6 +196,7 @@ pub mod util;
 /* Unsupported interfaces */
 
 // Private APIs
+#[path = "unstable/mod.rs"]
 pub mod unstable;
 
 /* For internal use, not exported */
diff --git a/src/libcore/either.rs b/src/libcore/either.rs
index 957e848b5e7..8c16f5c6482 100644
--- a/src/libcore/either.rs
+++ b/src/libcore/either.rs
@@ -10,11 +10,14 @@
 
 //! A type that represents one of two alternatives
 
+use container::Container;
 use cmp::Eq;
 use kinds::Copy;
+use old_iter::BaseIter;
 use result::Result;
 use result;
 use vec;
+use vec::OwnedVector;
 
 /// The either type
 #[deriving(Clone, Eq)]
@@ -132,7 +135,7 @@ pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
 
     match eith {
         Left(x) => x,
-        Right(_) => fail!(~"either::unwrap_left Right")
+        Right(_) => fail!("either::unwrap_left Right")
     }
 }
 
@@ -142,7 +145,7 @@ pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
 
     match eith {
         Right(x) => x,
-        Left(_) => fail!(~"either::unwrap_right Left")
+        Left(_) => fail!("either::unwrap_right Left")
     }
 }
 
@@ -198,14 +201,14 @@ fn test_lefts() {
 fn test_lefts_none() {
     let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
     let result = lefts(input);
-    assert_eq!(vec::len(result), 0u);
+    assert_eq!(result.len(), 0u);
 }
 
 #[test]
 fn test_lefts_empty() {
     let input: ~[Either<int, int>] = ~[];
     let result = lefts(input);
-    assert_eq!(vec::len(result), 0u);
+    assert_eq!(result.len(), 0u);
 }
 
 #[test]
@@ -219,14 +222,14 @@ fn test_rights() {
 fn test_rights_none() {
     let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
     let result = rights(input);
-    assert_eq!(vec::len(result), 0u);
+    assert_eq!(result.len(), 0u);
 }
 
 #[test]
 fn test_rights_empty() {
     let input: ~[Either<int, int>] = ~[];
     let result = rights(input);
-    assert_eq!(vec::len(result), 0u);
+    assert_eq!(result.len(), 0u);
 }
 
 #[test]
@@ -244,22 +247,22 @@ fn test_partition() {
 fn test_partition_no_lefts() {
     let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
     let (lefts, rights) = partition(input);
-    assert_eq!(vec::len(lefts), 0u);
-    assert_eq!(vec::len(rights), 2u);
+    assert_eq!(lefts.len(), 0u);
+    assert_eq!(rights.len(), 2u);
 }
 
 #[test]
 fn test_partition_no_rights() {
     let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
     let (lefts, rights) = partition(input);
-    assert_eq!(vec::len(lefts), 2u);
-    assert_eq!(vec::len(rights), 0u);
+    assert_eq!(lefts.len(), 2u);
+    assert_eq!(rights.len(), 0u);
 }
 
 #[test]
 fn test_partition_empty() {
     let input: ~[Either<int, int>] = ~[];
     let (lefts, rights) = partition(input);
-    assert_eq!(vec::len(lefts), 0u);
-    assert_eq!(vec::len(rights), 0u);
+    assert_eq!(lefts.len(), 0u);
+    assert_eq!(rights.len(), 0u);
 }
diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs
index 75b3b6bb566..cb02364d725 100644
--- a/src/libcore/hash.rs
+++ b/src/libcore/hash.rs
@@ -21,6 +21,8 @@
 
 #[cfg(stage0)]
 use cast;
+use container::Container;
+use old_iter::BaseIter;
 use rt::io::Writer;
 use to_bytes::IterBytes;
 use uint;
diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs
index 590d4ab3bcb..d9912813cf9 100644
--- a/src/libcore/hashmap.rs
+++ b/src/libcore/hashmap.rs
@@ -17,7 +17,6 @@ use container::{Container, Mutable, Map, Set};
 use cmp::{Eq, Equiv};
 use hash::Hash;
 use old_iter::BaseIter;
-use hash::Hash;
 use old_iter;
 use option::{None, Option, Some};
 use rand::RngUtil;
@@ -200,7 +199,7 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
     fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V {
         match self.buckets[idx] {
             Some(ref bkt) => &bkt.value,
-            None => fail!(~"HashMap::find: internal logic error"),
+            None => fail!("HashMap::find: internal logic error"),
         }
     }
 
@@ -217,7 +216,7 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
     /// True if there was no previous entry with that key
     fn insert_internal(&mut self, hash: uint, k: K, v: V) -> Option<V> {
         match self.bucket_for_key_with_hash(hash, &k) {
-            TableFull => { fail!(~"Internal logic error"); }
+            TableFull => { fail!("Internal logic error"); }
             FoundHole(idx) => {
                 debug!("insert fresh (%?->%?) at idx %?, hash %?",
                        k, v, idx, hash);
@@ -230,7 +229,7 @@ priv impl<K:Hash + Eq,V> HashMap<K, V> {
                 debug!("insert overwrite (%?->%?) at idx %?, hash %?",
                        k, v, idx, hash);
                 match self.buckets[idx] {
-                    None => { fail!(~"insert_internal: Internal logic error") }
+                    None => { fail!("insert_internal: Internal logic error") }
                     Some(ref mut b) => {
                         b.hash = hash;
                         b.key = k;
@@ -500,7 +499,7 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
 
         let hash = k.hash_keyed(self.k0, self.k1) as uint;
         let idx = match self.bucket_for_key_with_hash(hash, &k) {
-            TableFull => fail!(~"Internal logic error"),
+            TableFull => fail!("Internal logic error"),
             FoundEntry(idx) => idx,
             FoundHole(idx) => {
                 self.buckets[idx] = Some(Bucket{hash: hash, key: k,
@@ -531,7 +530,7 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
 
         let hash = k.hash_keyed(self.k0, self.k1) as uint;
         let idx = match self.bucket_for_key_with_hash(hash, &k) {
-            TableFull => fail!(~"Internal logic error"),
+            TableFull => fail!("Internal logic error"),
             FoundEntry(idx) => idx,
             FoundHole(idx) => {
                 self.buckets[idx] = Some(Bucket{hash: hash, key: k,
@@ -560,7 +559,7 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
 
         let hash = k.hash_keyed(self.k0, self.k1) as uint;
         let idx = match self.bucket_for_key_with_hash(hash, &k) {
-            TableFull => fail!(~"Internal logic error"),
+            TableFull => fail!("Internal logic error"),
             FoundEntry(idx) => idx,
             FoundHole(idx) => {
                 let v = f(&k);
@@ -592,7 +591,7 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
 
         let hash = k.hash_keyed(self.k0, self.k1) as uint;
         let idx = match self.bucket_for_key_with_hash(hash, &k) {
-            TableFull => fail!(~"Internal logic error"),
+            TableFull => fail!("Internal logic error"),
             FoundEntry(idx) => idx,
             FoundHole(idx) => {
                 let v = f(&k);
@@ -623,7 +622,7 @@ pub impl<K: Hash + Eq, V> HashMap<K, V> {
     fn get<'a>(&'a self, k: &K) -> &'a V {
         match self.find(k) {
             Some(v) => v,
-            None => fail!(fmt!("No entry found for key: %?", k)),
+            None => fail!("No entry found for key: %?", k),
         }
     }
 
@@ -825,6 +824,10 @@ pub impl <T:Hash + Eq> HashSet<T> {
     fn consume(&mut self, f: &fn(T)) {
         self.map.consume(|k, _| f(k))
     }
+
+    fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
+      self.map.contains_key_equiv(value)
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libcore/io.rs b/src/libcore/io.rs
index f444eb272f2..7b7d278380f 100644
--- a/src/libcore/io.rs
+++ b/src/libcore/io.rs
@@ -16,6 +16,7 @@ Basic input/output
 
 use result::Result;
 
+use container::Container;
 use int;
 use libc;
 use libc::{c_int, c_long, c_void, size_t, ssize_t};
@@ -24,11 +25,15 @@ use os;
 use cast;
 use path::Path;
 use ops::Drop;
+use old_iter::{BaseIter, CopyableIter};
 use ptr;
 use result;
 use str;
+use str::StrSlice;
+use to_str::ToStr;
 use uint;
 use vec;
+use vec::{OwnedVector, OwnedCopyableVector};
 
 #[allow(non_camel_case_types)] // not sure what to do about this
 pub type fd_t = c_int;
@@ -668,10 +673,10 @@ impl<T:Reader> ReaderUtil for T {
 
     fn read_char(&self) -> char {
         let c = self.read_chars(1);
-        if vec::len(c) == 0 {
+        if c.len() == 0 {
             return -1 as char; // FIXME will this stay valid? // #2004
         }
-        assert!((vec::len(c) == 1));
+        assert!(c.len() == 1);
         return c[0];
     }
 
@@ -1797,7 +1802,7 @@ mod tests {
     fn test_readchars_empty() {
         do io::with_str_reader(~"") |inp| {
             let res : ~[char] = inp.read_chars(128);
-            assert!((vec::len(res) == 0));
+            assert!(res.len() == 0);
         }
     }
 
@@ -1836,10 +1841,10 @@ mod tests {
         fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
             do io::with_str_reader(s) |inp| {
                 let res : ~[char] = inp.read_chars(len);
-                if (len <= vec::len(ivals)) {
-                    assert!((vec::len(res) == len));
+                if len <= ivals.len() {
+                    assert!(res.len() == len);
                 }
-                assert!(vec::slice(ivals, 0u, vec::len(res)) ==
+                assert!(vec::slice(ivals, 0u, res.len()) ==
                              vec::map(res, |x| *x as int));
             }
         }
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index d5649d3dfd2..ae4af3812d2 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -42,6 +42,9 @@ much easier to implement.
 
 #[cfg(not(stage0))] use cmp::Ord;
 #[cfg(not(stage0))] use option::{Option, Some, None};
+#[cfg(not(stage0))] use vec::OwnedVector;
+#[cfg(not(stage0))] use num::{One, Zero};
+#[cfg(not(stage0))] use ops::{Add, Mul};
 
 #[cfg(stage0)]
 pub trait Times {
@@ -211,6 +214,81 @@ pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
     result
 }
 
+/**
+ * Reduce an iterator to an accumulated value.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
+ * ~~~~
+ */
+#[cfg(not(stage0))]
+#[inline]
+pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
+    let mut result = start;
+    for iter |x| {
+        f(&mut result, x);
+    }
+    result
+}
+
+/**
+ * Reduce an iterator to an accumulated value.
+ *
+ * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
+ * forces the iterator to yield borrowed pointers.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
+ *     fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
+ * }
+ * ~~~~
+ */
+#[cfg(not(stage0))]
+#[inline]
+pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
+    let mut result = start;
+    for iter |x| {
+        f(&mut result, x);
+    }
+    result
+}
+
+/**
+ * Return the sum of the items yielding by an iterator.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs: ~[int] = ~[1, 2, 3, 4];
+ * assert_eq!(do sum |f| { xs.each(f) }, 10);
+ * ~~~~
+ */
+#[cfg(not(stage0))]
+#[inline(always)]
+pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
+    fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
+}
+
+/**
+ * Return the product of the items yielded by an iterator.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs: ~[int] = ~[1, 2, 3, 4];
+ * assert_eq!(do product |f| { xs.each(f) }, 24);
+ * ~~~~
+ */
+#[cfg(not(stage0))]
+#[inline(always)]
+pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
+    fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -253,4 +331,33 @@ mod tests {
         let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
         assert_eq!(min(|f| xs.each(f)).unwrap(), &-5);
     }
+
+    #[test]
+    fn test_fold() {
+        assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
+    }
+
+    #[test]
+    fn test_sum() {
+        let xs: ~[int] = ~[1, 2, 3, 4];
+        assert_eq!(do sum |f| { xs.each(f) }, 10);
+    }
+
+    #[test]
+    fn test_empty_sum() {
+        let xs: ~[int] = ~[];
+        assert_eq!(do sum |f| { xs.each(f) }, 0);
+    }
+
+    #[test]
+    fn test_product() {
+        let xs: ~[int] = ~[1, 2, 3, 4];
+        assert_eq!(do product |f| { xs.each(f) }, 24);
+    }
+
+    #[test]
+    fn test_empty_product() {
+        let xs: ~[int] = ~[];
+        assert_eq!(do product |f| { xs.each(f) }, 1);
+    }
 }
diff --git a/src/libcore/local_data.rs b/src/libcore/local_data.rs
index d4b02a0ad9b..2cbf8b9f05e 100644
--- a/src/libcore/local_data.rs
+++ b/src/libcore/local_data.rs
@@ -132,15 +132,15 @@ fn test_tls_modify() {
         fn my_key(_x: @~str) { }
         local_data_modify(my_key, |data| {
             match data {
-                Some(@ref val) => fail!(~"unwelcome value: " + *val),
-                None       => Some(@~"first data")
+                Some(@ref val) => fail!("unwelcome value: %s", *val),
+                None           => Some(@~"first data")
             }
         });
         local_data_modify(my_key, |data| {
             match data {
                 Some(@~"first data") => Some(@~"next data"),
-                Some(@ref val)           => fail!(~"wrong value: " + *val),
-                None                 => fail!(~"missing value")
+                Some(@ref val)       => fail!("wrong value: %s", *val),
+                None                 => fail!("missing value")
             }
         });
         assert!(*(local_data_pop(my_key).get()) == ~"next data");
@@ -223,4 +223,4 @@ fn test_static_pointer() {
         static VALUE: int = 0;
         local_data_set(key, @&VALUE);
     }
-}
\ No newline at end of file
+}
diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs
index 69ecad56a8f..cea827298af 100644
--- a/src/libcore/logging.rs
+++ b/src/libcore/logging.rs
@@ -45,6 +45,7 @@ pub fn console_off() {
 #[cfg(not(test))]
 #[lang="log_type"]
 pub fn log_type<T>(level: u32, object: &T) {
+    use container::Container;
     use cast::transmute;
     use io;
     use libc;
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index a872a6388ba..4a3ec3528f2 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -10,6 +10,7 @@
 
 //! Operations and constants for `f32`
 
+use libc::c_int;
 use num::{Zero, One, strconv};
 use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
 use prelude::*;
@@ -413,6 +414,12 @@ impl Trigonometric for f32 {
 
     #[inline(always)]
     fn atan2(&self, other: f32) -> f32 { atan2(*self, other) }
+
+    /// Simultaneously computes the sine and cosine of the number
+    #[inline(always)]
+    fn sin_cos(&self) -> (f32, f32) {
+        (self.sin(), self.cos())
+    }
 }
 
 impl Exponential for f32 {
@@ -450,6 +457,57 @@ impl Hyperbolic for f32 {
 
     #[inline(always)]
     fn tanh(&self) -> f32 { tanh(*self) }
+
+    ///
+    /// Inverse hyperbolic sine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic sine of `self` will be returned
+    /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity`
+    /// - `NaN` if `self` is `NaN`
+    ///
+    #[inline(always)]
+    fn asinh(&self) -> f32 {
+        match *self {
+            neg_infinity => neg_infinity,
+            x => (x + ((x * x) + 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic cosine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic cosine of `self` will be returned
+    /// - `infinity` if `self` is `infinity`
+    /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn acosh(&self) -> f32 {
+        match *self {
+            x if x < 1.0 => Float::NaN(),
+            x => (x + ((x * x) - 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic tangent
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic tangent of `self` will be returned
+    /// - `self` if `self` is `0.0` or `-0.0`
+    /// - `infinity` if `self` is `1.0`
+    /// - `neg_infinity` if `self` is `-1.0`
+    /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0`
+    ///   (including `infinity` and `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn atanh(&self) -> f32 {
+        0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p()
+    }
 }
 
 impl Real for f32 {
@@ -620,6 +678,25 @@ impl Float for f32 {
     #[inline(always)]
     fn max_10_exp() -> int { 38 }
 
+    /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
+    #[inline(always)]
+    fn ldexp(x: f32, exp: int) -> f32 {
+        ldexp(x, exp as c_int)
+    }
+
+    ///
+    /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
+    ///
+    /// - `self = x * pow(2, exp)`
+    /// - `0.5 <= abs(x) < 1.0`
+    ///
+    #[inline(always)]
+    fn frexp(&self) -> (f32, int) {
+        let mut exp = 0;
+        let x = frexp(*self, &mut exp);
+        (x, exp as int)
+    }
+
     ///
     /// Returns the exponential of the number, minus `1`, in a way that is accurate
     /// even if the number is close to zero
@@ -701,7 +778,7 @@ pub fn to_str_hex(num: f32) -> ~str {
 pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
     let (r, special) = strconv::to_str_common(
         &num, rdx, true, strconv::SignNeg, strconv::DigAll);
-    if special { fail!(~"number has a special value, \
+    if special { fail!("number has a special value, \
                       try to_str_radix_special() if those are expected") }
     r
 }
@@ -973,6 +1050,43 @@ mod tests {
     }
 
     #[test]
+    fn test_asinh() {
+        assert_eq!(0.0f32.asinh(), 0.0f32);
+        assert_eq!((-0.0f32).asinh(), -0.0f32);
+        assert_eq!(Float::infinity::<f32>().asinh(), Float::infinity::<f32>());
+        assert_eq!(Float::neg_infinity::<f32>().asinh(), Float::neg_infinity::<f32>());
+        assert!(Float::NaN::<f32>().asinh().is_NaN());
+        assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32);
+        assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32);
+    }
+
+    #[test]
+    fn test_acosh() {
+        assert_eq!(1.0f32.acosh(), 0.0f32);
+        assert!(0.999f32.acosh().is_NaN());
+        assert_eq!(Float::infinity::<f32>().acosh(), Float::infinity::<f32>());
+        assert!(Float::neg_infinity::<f32>().acosh().is_NaN());
+        assert!(Float::NaN::<f32>().acosh().is_NaN());
+        assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32);
+        assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32);
+    }
+
+    #[test]
+    fn test_atanh() {
+        assert_eq!(0.0f32.atanh(), 0.0f32);
+        assert_eq!((-0.0f32).atanh(), -0.0f32);
+        assert_eq!(1.0f32.atanh(), Float::infinity::<f32>());
+        assert_eq!((-1.0f32).atanh(), Float::neg_infinity::<f32>());
+        assert!(2f64.atanh().atanh().is_NaN());
+        assert!((-2f64).atanh().atanh().is_NaN());
+        assert!(Float::infinity::<f64>().atanh().is_NaN());
+        assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
+        assert!(Float::NaN::<f32>().atanh().is_NaN());
+        assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32);
+        assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32);
+    }
+
+    #[test]
     fn test_real_consts() {
         assert_approx_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
         assert_approx_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
@@ -1091,4 +1205,44 @@ mod tests {
         assert_eq!(1e-37f32.classify(), FPNormal);
         assert_eq!(1e-38f32.classify(), FPSubnormal);
     }
+
+    #[test]
+    fn test_ldexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f32 = from_str_hex("1p-123").unwrap();
+        let f2: f32 = from_str_hex("1p-111").unwrap();
+        assert_eq!(Float::ldexp(1f32, -123), f1);
+        assert_eq!(Float::ldexp(1f32, -111), f2);
+
+        assert_eq!(Float::ldexp(0f32, -123), 0f32);
+        assert_eq!(Float::ldexp(-0f32, -123), -0f32);
+        assert_eq!(Float::ldexp(Float::infinity::<f32>(), -123),
+                   Float::infinity::<f32>());
+        assert_eq!(Float::ldexp(Float::neg_infinity::<f32>(), -123),
+                   Float::neg_infinity::<f32>());
+        assert!(Float::ldexp(Float::NaN::<f32>(), -123).is_NaN());
+    }
+
+    #[test]
+    fn test_frexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f32 = from_str_hex("1p-123").unwrap();
+        let f2: f32 = from_str_hex("1p-111").unwrap();
+        let (x1, exp1) = f1.frexp();
+        let (x2, exp2) = f2.frexp();
+        assert_eq!((x1, exp1), (0.5f32, -122));
+        assert_eq!((x2, exp2), (0.5f32, -110));
+        assert_eq!(Float::ldexp(x1, exp1), f1);
+        assert_eq!(Float::ldexp(x2, exp2), f2);
+
+        assert_eq!(0f32.frexp(), (0f32, 0));
+        assert_eq!((-0f32).frexp(), (-0f32, 0));
+        assert_eq!(match Float::infinity::<f32>().frexp() { (x, _) => x },
+                   Float::infinity::<f32>())
+        assert_eq!(match Float::neg_infinity::<f32>().frexp() { (x, _) => x },
+                   Float::neg_infinity::<f32>())
+        assert!(match Float::NaN::<f32>().frexp() { (x, _) => x.is_NaN() })
+    }
 }
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 8a17ae91934..e370f43a003 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -426,6 +426,12 @@ impl Trigonometric for f64 {
 
     #[inline(always)]
     fn atan2(&self, other: f64) -> f64 { atan2(*self, other) }
+
+    /// Simultaneously computes the sine and cosine of the number
+    #[inline(always)]
+    fn sin_cos(&self) -> (f64, f64) {
+        (self.sin(), self.cos())
+    }
 }
 
 impl Exponential for f64 {
@@ -463,6 +469,57 @@ impl Hyperbolic for f64 {
 
     #[inline(always)]
     fn tanh(&self) -> f64 { tanh(*self) }
+
+    ///
+    /// Inverse hyperbolic sine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic sine of `self` will be returned
+    /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity`
+    /// - `NaN` if `self` is `NaN`
+    ///
+    #[inline(always)]
+    fn asinh(&self) -> f64 {
+        match *self {
+            neg_infinity => neg_infinity,
+            x => (x + ((x * x) + 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic cosine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic cosine of `self` will be returned
+    /// - `infinity` if `self` is `infinity`
+    /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn acosh(&self) -> f64 {
+        match *self {
+            x if x < 1.0 => Float::NaN(),
+            x => (x + ((x * x) - 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic tangent
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic tangent of `self` will be returned
+    /// - `self` if `self` is `0.0` or `-0.0`
+    /// - `infinity` if `self` is `1.0`
+    /// - `neg_infinity` if `self` is `-1.0`
+    /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0`
+    ///   (including `infinity` and `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn atanh(&self) -> f64 {
+        0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p()
+    }
 }
 
 impl Real for f64 {
@@ -663,6 +720,25 @@ impl Float for f64 {
     #[inline(always)]
     fn max_10_exp() -> int { 308 }
 
+    /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
+    #[inline(always)]
+    fn ldexp(x: f64, exp: int) -> f64 {
+        ldexp(x, exp as c_int)
+    }
+
+    ///
+    /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
+    ///
+    /// - `self = x * pow(2, exp)`
+    /// - `0.5 <= abs(x) < 1.0`
+    ///
+    #[inline(always)]
+    fn frexp(&self) -> (f64, int) {
+        let mut exp = 0;
+        let x = frexp(*self, &mut exp);
+        (x, exp as int)
+    }
+
     ///
     /// Returns the exponential of the number, minus `1`, in a way that is accurate
     /// even if the number is close to zero
@@ -744,7 +820,7 @@ pub fn to_str_hex(num: f64) -> ~str {
 pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
     let (r, special) = strconv::to_str_common(
         &num, rdx, true, strconv::SignNeg, strconv::DigAll);
-    if special { fail!(~"number has a special value, \
+    if special { fail!("number has a special value, \
                       try to_str_radix_special() if those are expected") }
     r
 }
@@ -1020,6 +1096,43 @@ mod tests {
     }
 
     #[test]
+    fn test_asinh() {
+        assert_eq!(0.0f64.asinh(), 0.0f64);
+        assert_eq!((-0.0f64).asinh(), -0.0f64);
+        assert_eq!(Float::infinity::<f64>().asinh(), Float::infinity::<f64>());
+        assert_eq!(Float::neg_infinity::<f64>().asinh(), Float::neg_infinity::<f64>());
+        assert!(Float::NaN::<f64>().asinh().is_NaN());
+        assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64);
+        assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64);
+    }
+
+    #[test]
+    fn test_acosh() {
+        assert_eq!(1.0f64.acosh(), 0.0f64);
+        assert!(0.999f64.acosh().is_NaN());
+        assert_eq!(Float::infinity::<f64>().acosh(), Float::infinity::<f64>());
+        assert!(Float::neg_infinity::<f64>().acosh().is_NaN());
+        assert!(Float::NaN::<f64>().acosh().is_NaN());
+        assert_approx_eq!(2.0f64.acosh(), 1.31695789692481670862504634730796844f64);
+        assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64);
+    }
+
+    #[test]
+    fn test_atanh() {
+        assert_eq!(0.0f64.atanh(), 0.0f64);
+        assert_eq!((-0.0f64).atanh(), -0.0f64);
+        assert_eq!(1.0f64.atanh(), Float::infinity::<f64>());
+        assert_eq!((-1.0f64).atanh(), Float::neg_infinity::<f64>());
+        assert!(2f64.atanh().atanh().is_NaN());
+        assert!((-2f64).atanh().atanh().is_NaN());
+        assert!(Float::infinity::<f64>().atanh().is_NaN());
+        assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
+        assert!(Float::NaN::<f64>().atanh().is_NaN());
+        assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64);
+        assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64);
+    }
+
+    #[test]
     fn test_real_consts() {
         assert_approx_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
         assert_approx_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
@@ -1137,4 +1250,44 @@ mod tests {
         assert_eq!(1e-307f64.classify(), FPNormal);
         assert_eq!(1e-308f64.classify(), FPSubnormal);
     }
+
+    #[test]
+    fn test_ldexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f64 = from_str_hex("1p-123").unwrap();
+        let f2: f64 = from_str_hex("1p-111").unwrap();
+        assert_eq!(Float::ldexp(1f64, -123), f1);
+        assert_eq!(Float::ldexp(1f64, -111), f2);
+
+        assert_eq!(Float::ldexp(0f64, -123), 0f64);
+        assert_eq!(Float::ldexp(-0f64, -123), -0f64);
+        assert_eq!(Float::ldexp(Float::infinity::<f64>(), -123),
+                   Float::infinity::<f64>());
+        assert_eq!(Float::ldexp(Float::neg_infinity::<f64>(), -123),
+                   Float::neg_infinity::<f64>());
+        assert!(Float::ldexp(Float::NaN::<f64>(), -123).is_NaN());
+    }
+
+    #[test]
+    fn test_frexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f64 = from_str_hex("1p-123").unwrap();
+        let f2: f64 = from_str_hex("1p-111").unwrap();
+        let (x1, exp1) = f1.frexp();
+        let (x2, exp2) = f2.frexp();
+        assert_eq!((x1, exp1), (0.5f64, -122));
+        assert_eq!((x2, exp2), (0.5f64, -110));
+        assert_eq!(Float::ldexp(x1, exp1), f1);
+        assert_eq!(Float::ldexp(x2, exp2), f2);
+
+        assert_eq!(0f64.frexp(), (0f64, 0));
+        assert_eq!((-0f64).frexp(), (-0f64, 0));
+        assert_eq!(match Float::infinity::<f64>().frexp() { (x, _) => x },
+                   Float::infinity::<f64>())
+        assert_eq!(match Float::neg_infinity::<f64>().frexp() { (x, _) => x },
+                   Float::neg_infinity::<f64>())
+        assert!(match Float::NaN::<f64>().frexp() { (x, _) => x.is_NaN() })
+    }
 }
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index e6a2ed7ea97..681aafaab88 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -133,7 +133,7 @@ pub fn to_str_hex(num: float) -> ~str {
 pub fn to_str_radix(num: float, radix: uint) -> ~str {
     let (r, special) = strconv::to_str_common(
         &num, radix, true, strconv::SignNeg, strconv::DigAll);
-    if special { fail!(~"number has a special value, \
+    if special { fail!("number has a special value, \
                          try to_str_radix_special() if those are expected") }
     r
 }
@@ -530,6 +530,14 @@ impl Trigonometric for float {
     fn atan2(&self, other: float) -> float {
         (*self as f64).atan2(other as f64) as float
     }
+
+    /// Simultaneously computes the sine and cosine of the number
+    #[inline(always)]
+    fn sin_cos(&self) -> (float, float) {
+        match (*self as f64).sin_cos() {
+            (s, c) => (s as float, c as float)
+        }
+    }
 }
 
 impl Exponential for float {
@@ -585,6 +593,51 @@ impl Hyperbolic for float {
     fn tanh(&self) -> float {
         (*self as f64).tanh() as float
     }
+
+    ///
+    /// Inverse hyperbolic sine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic sine of `self` will be returned
+    /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity`
+    /// - `NaN` if `self` is `NaN`
+    ///
+    #[inline(always)]
+    fn asinh(&self) -> float {
+        (*self as f64).asinh() as float
+    }
+
+    ///
+    /// Inverse hyperbolic cosine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic cosine of `self` will be returned
+    /// - `infinity` if `self` is `infinity`
+    /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn acosh(&self) -> float {
+        (*self as f64).acosh() as float
+    }
+
+    ///
+    /// Inverse hyperbolic tangent
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic tangent of `self` will be returned
+    /// - `self` if `self` is `0.0` or `-0.0`
+    /// - `infinity` if `self` is `1.0`
+    /// - `neg_infinity` if `self` is `-1.0`
+    /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0`
+    ///   (including `infinity` and `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn atanh(&self) -> float {
+        (*self as f64).atanh() as float
+    }
 }
 
 impl Real for float {
@@ -836,6 +889,25 @@ impl Float for float {
     #[inline(always)]
     fn max_10_exp() -> int { Float::max_10_exp::<f64>() }
 
+    /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
+    #[inline(always)]
+    fn ldexp(x: float, exp: int) -> float {
+        Float::ldexp(x as f64, exp) as float
+    }
+
+    ///
+    /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
+    ///
+    /// - `self = x * pow(2, exp)`
+    /// - `0.5 <= abs(x) < 1.0`
+    ///
+    #[inline(always)]
+    fn frexp(&self) -> (float, int) {
+        match (*self as f64).frexp() {
+            (x, exp) => (x as float, exp)
+        }
+    }
+
     ///
     /// Returns the exponential of the number, minus `1`, in a way that is accurate
     /// even if the number is close to zero
@@ -850,7 +922,9 @@ impl Float for float {
     /// than if the operations were performed separately
     ///
     #[inline(always)]
-    fn ln_1p(&self) -> float { (*self as f64).ln_1p() as float }
+    fn ln_1p(&self) -> float {
+        (*self as f64).ln_1p() as float
+    }
 
     ///
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
@@ -973,6 +1047,43 @@ mod tests {
     }
 
     #[test]
+    fn test_asinh() {
+        assert_eq!(0.0f.asinh(), 0.0f);
+        assert_eq!((-0.0f).asinh(), -0.0f);
+        assert_eq!(Float::infinity::<float>().asinh(), Float::infinity::<float>());
+        assert_eq!(Float::neg_infinity::<float>().asinh(), Float::neg_infinity::<float>());
+        assert!(Float::NaN::<float>().asinh().is_NaN());
+        assert_approx_eq!(2.0f.asinh(), 1.443635475178810342493276740273105f);
+        assert_approx_eq!((-2.0f).asinh(), -1.443635475178810342493276740273105f);
+    }
+
+    #[test]
+    fn test_acosh() {
+        assert_eq!(1.0f.acosh(), 0.0f);
+        assert!(0.999f.acosh().is_NaN());
+        assert_eq!(Float::infinity::<float>().acosh(), Float::infinity::<float>());
+        assert!(Float::neg_infinity::<float>().acosh().is_NaN());
+        assert!(Float::NaN::<float>().acosh().is_NaN());
+        assert_approx_eq!(2.0f.acosh(), 1.31695789692481670862504634730796844f);
+        assert_approx_eq!(3.0f.acosh(), 1.76274717403908605046521864995958461f);
+    }
+
+    #[test]
+    fn test_atanh() {
+        assert_eq!(0.0f.atanh(), 0.0f);
+        assert_eq!((-0.0f).atanh(), -0.0f);
+        assert_eq!(1.0f.atanh(), Float::infinity::<float>());
+        assert_eq!((-1.0f).atanh(), Float::neg_infinity::<float>());
+        assert!(2f64.atanh().atanh().is_NaN());
+        assert!((-2f64).atanh().atanh().is_NaN());
+        assert!(Float::infinity::<f64>().atanh().is_NaN());
+        assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
+        assert!(Float::NaN::<float>().atanh().is_NaN());
+        assert_approx_eq!(0.5f.atanh(), 0.54930614433405484569762261846126285f);
+        assert_approx_eq!((-0.5f).atanh(), -0.54930614433405484569762261846126285f);
+    }
+
+    #[test]
     fn test_real_consts() {
         assert_approx_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
         assert_approx_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
@@ -1093,6 +1204,46 @@ mod tests {
     }
 
     #[test]
+    fn test_ldexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: float = from_str_hex("1p-123").unwrap();
+        let f2: float = from_str_hex("1p-111").unwrap();
+        assert_eq!(Float::ldexp(1f, -123), f1);
+        assert_eq!(Float::ldexp(1f, -111), f2);
+
+        assert_eq!(Float::ldexp(0f, -123), 0f);
+        assert_eq!(Float::ldexp(-0f, -123), -0f);
+        assert_eq!(Float::ldexp(Float::infinity::<float>(), -123),
+                   Float::infinity::<float>());
+        assert_eq!(Float::ldexp(Float::neg_infinity::<float>(), -123),
+                   Float::neg_infinity::<float>());
+        assert!(Float::ldexp(Float::NaN::<float>(), -123).is_NaN());
+    }
+
+    #[test]
+    fn test_frexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: float = from_str_hex("1p-123").unwrap();
+        let f2: float = from_str_hex("1p-111").unwrap();
+        let (x1, exp1) = f1.frexp();
+        let (x2, exp2) = f2.frexp();
+        assert_eq!((x1, exp1), (0.5f, -122));
+        assert_eq!((x2, exp2), (0.5f, -110));
+        assert_eq!(Float::ldexp(x1, exp1), f1);
+        assert_eq!(Float::ldexp(x2, exp2), f2);
+
+        assert_eq!(0f.frexp(), (0f, 0));
+        assert_eq!((-0f).frexp(), (-0f, 0));
+        assert_eq!(match Float::infinity::<float>().frexp() { (x, _) => x },
+                   Float::infinity::<float>())
+        assert_eq!(match Float::neg_infinity::<float>().frexp() { (x, _) => x },
+                   Float::neg_infinity::<float>())
+        assert!(match Float::NaN::<float>().frexp() { (x, _) => x.is_NaN() })
+    }
+
+    #[test]
     pub fn test_to_str_exact_do_decimal() {
         let s = to_str_exact(5.0, 4u);
         assert_eq!(s, ~"5.0000");
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs
index f2bba6a4639..348f72f9f0a 100644
--- a/src/libcore/num/int-template.rs
+++ b/src/libcore/num/int-template.rs
@@ -89,7 +89,7 @@ pub fn gt(x: T, y: T) -> bool { x > y }
 pub fn _range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) -> bool {
     let mut i = start;
     if step == 0 {
-        fail!(~"range_step called with step == 0");
+        fail!("range_step called with step == 0");
     } else if step > 0 { // ascending
         while i < stop {
             if !it(i) { return false; }
@@ -923,16 +923,16 @@ mod tests {
 
         // None of the `fail`s should execute.
         for range(10,0) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
         for range_rev(0,10) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
         for range_step(10,0,1) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
         for range_step(0,10,-1) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
     }
 
diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs
index 50ba55039d4..c661e7ea1f8 100644
--- a/src/libcore/num/num.rs
+++ b/src/libcore/num/num.rs
@@ -118,6 +118,7 @@ pub trait Trigonometric {
     fn acos(&self) -> Self;
     fn atan(&self) -> Self;
     fn atan2(&self, other: Self) -> Self;
+    fn sin_cos(&self) -> (Self, Self);
 }
 
 pub trait Exponential {
@@ -133,6 +134,9 @@ pub trait Hyperbolic: Exponential {
     fn sinh(&self) -> Self;
     fn cosh(&self) -> Self;
     fn tanh(&self) -> Self;
+    fn asinh(&self) -> Self;
+    fn acosh(&self) -> Self;
+    fn atanh(&self) -> Self;
 }
 
 ///
@@ -281,6 +285,9 @@ pub trait Float: Real
     fn min_10_exp() -> int;
     fn max_10_exp() -> int;
 
+    fn ldexp(x: Self, exp: int) -> Self;
+    fn frexp(&self) -> (Self, int);
+
     fn exp_m1(&self) -> Self;
     fn ln_1p(&self) -> Self;
     fn mul_add(&self, a: Self, b: Self) -> Self;
diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs
index c16a29f8295..1d65b84b7ce 100644
--- a/src/libcore/num/strconv.rs
+++ b/src/libcore/num/strconv.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use container::Container;
 use core::cmp::{Ord, Eq};
 use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use option::{None, Option, Some};
@@ -15,6 +16,8 @@ use char;
 use str;
 use kinds::Copy;
 use vec;
+use vec::{CopyableVector, ImmutableVector};
+use vec::OwnedVector;
 use num::{NumCast, Zero, One, cast, pow_with_uint};
 use f64;
 
@@ -175,11 +178,9 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
         num: &T, radix: uint, negative_zero: bool,
         sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
     if (radix as int) < 2 {
-        fail!(fmt!("to_str_bytes_common: radix %? to low, \
-                   must lie in the range [2, 36]", radix));
+        fail!("to_str_bytes_common: radix %? to low, must lie in the range [2, 36]", radix);
     } else if radix as int > 36 {
-        fail!(fmt!("to_str_bytes_common: radix %? to high, \
-                   must lie in the range [2, 36]", radix));
+        fail!("to_str_bytes_common: radix %? to high, must lie in the range [2, 36]", radix);
     }
 
     let _0: T = Zero::zero();
@@ -441,20 +442,20 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
         ) -> Option<T> {
     match exponent {
         ExpDec if radix >= DIGIT_E_RADIX       // decimal exponent 'e'
-          => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \
-                        use of 'e' as decimal exponent", radix)),
+          => fail!("from_str_bytes_common: radix %? incompatible with \
+                    use of 'e' as decimal exponent", radix),
         ExpBin if radix >= DIGIT_P_RADIX       // binary exponent 'p'
-          => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \
-                        use of 'p' as binary exponent", radix)),
+          => fail!("from_str_bytes_common: radix %? incompatible with \
+                    use of 'p' as binary exponent", radix),
         _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
-          => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \
-                        special values 'inf' and 'NaN'", radix)),
+          => fail!("from_str_bytes_common: radix %? incompatible with \
+                    special values 'inf' and 'NaN'", radix),
         _ if (radix as int) < 2
-          => fail!(fmt!("from_str_bytes_common: radix %? to low, \
-                        must lie in the range [2, 36]", radix)),
+          => fail!("from_str_bytes_common: radix %? to low, \
+                    must lie in the range [2, 36]", radix),
         _ if (radix as int) > 36
-          => fail!(fmt!("from_str_bytes_common: radix %? to high, \
-                        must lie in the range [2, 36]", radix)),
+          => fail!("from_str_bytes_common: radix %? to high, \
+                    must lie in the range [2, 36]", radix),
         _ => ()
     }
 
@@ -486,11 +487,11 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
         }
     }
 
-    let (start, accum_positive) = match buf[0] {
-      '-' as u8 if !negative => return None,
-      '-' as u8 => (1u, false),
-      '+' as u8 => (1u, true),
-       _        => (0u, true)
+    let (start, accum_positive) = match buf[0] as char {
+      '-' if !negative => return None,
+      '-' => (1u, false),
+      '+' => (1u, true),
+       _  => (0u, true)
     };
 
     // Initialize accumulator with signed zero for floating point parsing to
diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs
index 1c115ee5072..da0815c264b 100644
--- a/src/libcore/num/uint-template.rs
+++ b/src/libcore/num/uint-template.rs
@@ -57,7 +57,7 @@ pub fn _range_step(start: T,
                    it: &fn(T) -> bool) -> bool {
     let mut i = start;
     if step == 0 {
-        fail!(~"range_step called with step == 0");
+        fail!("range_step called with step == 0");
     }
     if step >= 0 {
         while i < stop {
@@ -630,16 +630,16 @@ mod tests {
 
         // None of the `fail`s should execute.
         for range(0,0) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
         for range_rev(0,0) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
         for range_step(10,0,1) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
         for range_step(0,1,-10) |_i| {
-            fail!(~"unreachable");
+            fail!("unreachable");
         }
     }
 
diff --git a/src/libcore/old_iter.rs b/src/libcore/old_iter.rs
index a596b07dc78..7cffcb10a53 100644
--- a/src/libcore/old_iter.rs
+++ b/src/libcore/old_iter.rs
@@ -116,66 +116,72 @@ pub trait Buildable<A> {
 }
 
 #[inline(always)]
-pub fn _eachi<A,IA:BaseIter<A>>(self: &IA, blk: &fn(uint, &A) -> bool) -> bool {
+pub fn _eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
     let mut i = 0;
-    for self.each |a| {
-        if !blk(i, a) { return false; }
+    for this.each |a| {
+        if !blk(i, a) {
+            return false;
+        }
         i += 1;
     }
     return true;
 }
 
 #[cfg(stage0)]
-pub fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: &fn(uint, &A) -> bool) {
-    _eachi(self, blk);
+pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) {
+    _eachi(this, blk);
 }
 #[cfg(not(stage0))]
-pub fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: &fn(uint, &A) -> bool) -> bool {
-    _eachi(self, blk)
+pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
+    _eachi(this, blk)
 }
 
 #[inline(always)]
-pub fn all<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
-    for self.each |a| {
-        if !blk(a) { return false; }
+pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
+    for this.each |a| {
+        if !blk(a) {
+            return false;
+        }
     }
     return true;
 }
 
 #[inline(always)]
-pub fn any<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
-    for self.each |a| {
-        if blk(a) { return true; }
+pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
+    for this.each |a| {
+        if blk(a) {
+            return true;
+        }
     }
     return false;
 }
 
 #[inline(always)]
-pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: &IA,
+pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(this: &IA,
                                             prd: &fn(&A) -> bool)
                                          -> ~[A] {
-    do vec::build_sized_opt(self.size_hint()) |push| {
-        for self.each |a| {
+    do vec::build_sized_opt(this.size_hint()) |push| {
+        for this.each |a| {
             if prd(a) { push(*a); }
         }
     }
 }
 
 #[inline(always)]
-pub fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA, op: &fn(&A) -> B) -> ~[B] {
-    do vec::build_sized_opt(self.size_hint()) |push| {
-        for self.each |a| {
+pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] {
+    do vec::build_sized_opt(this.size_hint()) |push| {
+        for this.each |a| {
             push(op(a));
         }
     }
 }
 
 #[inline(always)]
-pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(self: &IA,
+pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA,
                                                           op: &fn(&A) -> IB)
                                                        -> ~[B] {
     do vec::build |push| {
-        for self.each |a| {
+        for this.each |a| {
             for op(a).each |&b| {
                 push(b);
             }
@@ -184,31 +190,31 @@ pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(self: &IA,
 }
 
 #[inline(always)]
-pub fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B, blk: &fn(&B, &A) -> B)
+pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B)
                               -> B {
     let mut b = b0;
-    for self.each |a| {
+    for this.each |a| {
         b = blk(&b, a);
     }
     b
 }
 
 #[inline(always)]
-pub fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
-    map_to_vec(self, |&x| x)
+pub fn to_vec<A:Copy,IA:BaseIter<A>>(this: &IA) -> ~[A] {
+    map_to_vec(this, |&x| x)
 }
 
 #[inline(always)]
-pub fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
-    for self.each |a| {
+pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool {
+    for this.each |a| {
         if *a == *x { return true; }
     }
     return false;
 }
 
 #[inline(always)]
-pub fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
-    do foldl(self, 0) |count, value| {
+pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint {
+    do foldl(this, 0) |count, value| {
         if *value == *x {
             *count + 1
         } else {
@@ -218,10 +224,10 @@ pub fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
 }
 
 #[inline(always)]
-pub fn position<A,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
+pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
                                -> Option<uint> {
     let mut i = 0;
-    for self.each |a| {
+    for this.each |a| {
         if f(a) { return Some(i); }
         i += 1;
     }
@@ -253,8 +259,8 @@ pub fn repeat(times: uint, blk: &fn() -> bool) -> bool {
 }
 
 #[inline(always)]
-pub fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
-    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
+pub fn min<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A {
+    match do foldl::<A,Option<A>,IA>(this, None) |a, b| {
         match a {
           &Some(ref a_) if *a_ < *b => {
              *(a)
@@ -263,13 +269,13 @@ pub fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
         }
     } {
         Some(val) => val,
-        None => fail!(~"min called on empty iterator")
+        None => fail!("min called on empty iterator")
     }
 }
 
 #[inline(always)]
-pub fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
-    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
+pub fn max<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A {
+    match do foldl::<A,Option<A>,IA>(this, None) |a, b| {
         match a {
           &Some(ref a_) if *a_ > *b => {
               *(a)
@@ -278,14 +284,14 @@ pub fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
         }
     } {
         Some(val) => val,
-        None => fail!(~"max called on empty iterator")
+        None => fail!("max called on empty iterator")
     }
 }
 
 #[inline(always)]
-pub fn find<A:Copy,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
+pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
                                 -> Option<A> {
-    for self.each |i| {
+    for this.each |i| {
         if f(i) { return Some(*i) }
     }
     return None;
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 7cb40876705..5aee3077e48 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -48,6 +48,8 @@ use util;
 use num::Zero;
 use old_iter::{BaseIter, MutableIter, ExtendedIter};
 use old_iter;
+use str::StrSlice;
+use clone::DeepClone;
 
 #[cfg(test)] use str;
 
@@ -58,6 +60,15 @@ pub enum Option<T> {
     Some(T),
 }
 
+impl<T: DeepClone> DeepClone for Option<T> {
+    fn deep_clone(&self) -> Option<T> {
+        match *self {
+            Some(ref x) => Some(x.deep_clone()),
+            None => None
+        }
+    }
+}
+
 impl<T:Ord> Ord for Option<T> {
     fn lt(&self, other: &Option<T>) -> bool {
         match (self, other) {
@@ -264,7 +275,7 @@ pub impl<T> Option<T> {
     fn get_ref<'a>(&'a self) -> &'a T {
         match *self {
           Some(ref x) => x,
-          None => fail!(~"option::get_ref none")
+          None => fail!("option::get_ref none")
         }
     }
 
@@ -286,7 +297,7 @@ pub impl<T> Option<T> {
     fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
         match *self {
           Some(ref mut x) => x,
-          None => fail!(~"option::get_mut_ref none")
+          None => fail!("option::get_mut_ref none")
         }
     }
 
@@ -310,7 +321,7 @@ pub impl<T> Option<T> {
          */
         match self {
           Some(x) => x,
-          None => fail!(~"option::unwrap none")
+          None => fail!("option::unwrap none")
         }
     }
 
@@ -324,7 +335,7 @@ pub impl<T> Option<T> {
      */
     #[inline(always)]
     fn swap_unwrap(&mut self) -> T {
-        if self.is_none() { fail!(~"option::swap_unwrap none") }
+        if self.is_none() { fail!("option::swap_unwrap none") }
         util::replace(self, None).unwrap()
     }
 
@@ -364,7 +375,7 @@ pub impl<T:Copy> Option<T> {
     fn get(self) -> T {
         match self {
           Some(copy x) => return x,
-          None => fail!(~"option::get none")
+          None => fail!("option::get none")
         }
     }
 
diff --git a/src/libcore/os.rs b/src/libcore/os.rs
index 030b7ec3e42..b97b32330de 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -152,7 +152,7 @@ FIXME #4726: It would probably be appropriate to make this a real global
 */
 fn with_env_lock<T>(f: &fn() -> T) -> T {
     use unstable::global::global_data_clone_create;
-    use unstable::{Exclusive, exclusive};
+    use unstable::sync::{Exclusive, exclusive};
 
     struct SharedValue(());
     type ValueMutex = Exclusive<SharedValue>;
@@ -178,8 +178,7 @@ pub fn env() -> ~[(~str,~str)] {
             };
             let ch = GetEnvironmentStringsA();
             if (ch as uint == 0) {
-                fail!(fmt!("os::env() failure getting env string from OS: %s",
-                           os::last_os_error()));
+                fail!("os::env() failure getting env string from OS: %s", os::last_os_error());
             }
             let mut curr_ptr: uint = ch as uint;
             let mut result = ~[];
@@ -196,13 +195,12 @@ pub fn env() -> ~[(~str,~str)] {
         }
         #[cfg(unix)]
         unsafe fn get_env_pairs() -> ~[~str] {
-            extern mod rustrt {
+            extern {
                 unsafe fn rust_env_pairs() -> **libc::c_char;
             }
-            let environ = rustrt::rust_env_pairs();
+            let environ = rust_env_pairs();
             if (environ as uint == 0) {
-                fail!(fmt!("os::env() failure getting env string from OS: %s",
-                           os::last_os_error()));
+                fail!("os::env() failure getting env string from OS: %s", os::last_os_error());
             }
             let mut result = ~[];
             ptr::array_each(environ, |e| {
@@ -291,6 +289,33 @@ pub fn setenv(n: &str, v: &str) {
     }
 }
 
+/// Remove a variable from the environment entirely
+pub fn unsetenv(n: &str) {
+    #[cfg(unix)]
+    fn _unsetenv(n: &str) {
+        unsafe {
+            do with_env_lock {
+                do str::as_c_str(n) |nbuf| {
+                    libc::funcs::posix01::unistd::unsetenv(nbuf);
+                }
+            }
+        }
+    }
+    #[cfg(windows)]
+    fn _unsetenv(n: &str) {
+        unsafe {
+            do with_env_lock {
+                use os::win32::as_utf16_p;
+                do as_utf16_p(n) |nbuf| {
+                    libc::SetEnvironmentVariableW(nbuf, ptr::null());
+                }
+            }
+        }
+    }
+
+    _unsetenv(n);
+}
+
 pub fn fdopen(fd: c_int) -> *FILE {
     unsafe {
         return do as_c_charp("r") |modebuf| {
@@ -412,7 +437,7 @@ pub fn self_exe_path() -> Option<Path> {
                            KERN_PROC as c_int,
                            KERN_PROC_PATHNAME as c_int, -1 as c_int];
                 let mut sz = sz;
-                sysctl(vec::raw::to_ptr(mib), vec::len(mib) as ::libc::c_uint,
+                sysctl(vec::raw::to_ptr(mib), mib.len() as ::libc::c_uint,
                        buf as *mut c_void, &mut sz, ptr::null(),
                        0u as size_t) == (0 as c_int)
             }
@@ -685,9 +710,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
         unsafe fn get_list(p: &Path) -> ~[~str] {
             use libc::{dirent_t};
             use libc::{opendir, readdir, closedir};
-            extern mod rustrt {
-                unsafe fn rust_list_dir_val(ptr: *dirent_t)
-                    -> *libc::c_char;
+            extern {
+                unsafe fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
             }
             let input = p.to_str();
             let mut strings = ~[];
@@ -698,10 +722,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
         debug!("os::list_dir -- opendir() SUCCESS");
                 let mut entry_ptr = readdir(dir_ptr);
                 while (entry_ptr as uint != 0) {
-                    strings.push(
-                        str::raw::from_c_str(
-                            rustrt::rust_list_dir_val(
-                                entry_ptr)));
+                    strings.push(str::raw::from_c_str(rust_list_dir_val(
+                        entry_ptr)));
                     entry_ptr = readdir(dir_ptr);
                 }
                 closedir(dir_ptr);
@@ -729,7 +751,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
             };
             use unstable::exchange_alloc::{malloc_raw, free_raw};
             #[nolink]
-            extern mod rustrt {
+            extern {
                 unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
                 unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void)
                     -> *u16;
@@ -737,8 +759,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
             fn star(p: &Path) -> Path { p.push("*") }
             do as_utf16_p(star(p).to_str()) |path_ptr| {
                 let mut strings = ~[];
-                let wfd_ptr = malloc_raw(
-                    rustrt::rust_list_dir_wfd_size() as uint);
+                let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
                 let find_handle =
                     FindFirstFileW(
                         path_ptr,
@@ -746,11 +767,9 @@ pub fn list_dir(p: &Path) -> ~[~str] {
                 if find_handle as int != INVALID_HANDLE_VALUE {
                     let mut more_files = 1 as libc::c_int;
                     while more_files != 0 {
-                        let fp_buf = rustrt::rust_list_dir_wfd_fp_buf(
-                            wfd_ptr);
+                        let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr);
                         if fp_buf as uint == 0 {
-                            fail!(~"os::list_dir() failure:"+
-                                  ~" got null ptr from wfd");
+                            fail!("os::list_dir() failure: got null ptr from wfd");
                         }
                         else {
                             let fp_vec = vec::from_buf(
@@ -860,7 +879,7 @@ pub fn change_dir(p: &Path) -> bool {
 /// is otherwise unsuccessful.
 pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
     use unstable::global::global_data_clone_create;
-    use unstable::{Exclusive, exclusive};
+    use unstable::sync::{Exclusive, exclusive};
 
     fn key(_: Exclusive<()>) { }
 
@@ -1067,7 +1086,7 @@ pub fn last_os_error() -> ~str {
             let err = strerror_r(errno() as c_int, &mut buf[0],
                                  TMPBUF_SZ as size_t);
             if err < 0 {
-                fail!(~"strerror_r failure");
+                fail!("strerror_r failure");
             }
 
             str::raw::from_c_str(&buf[0])
@@ -1105,7 +1124,7 @@ pub fn last_os_error() -> ~str {
                                      &mut buf[0], TMPBUF_SZ as DWORD,
                                      ptr::null());
             if res == 0 {
-                fail!(fmt!("[%?] FormatMessage failure", errno()));
+                fail!("[%?] FormatMessage failure", errno());
             }
 
             str::raw::from_c_str(&buf[0])
@@ -1309,7 +1328,7 @@ pub fn glob(pattern: &str) -> ~[Path] {
 /// Returns a vector of Path objects that match the given glob pattern
 #[cfg(target_os = "win32")]
 pub fn glob(pattern: &str) -> ~[Path] {
-    fail!(~"glob() is unimplemented on Windows")
+    fail!("glob() is unimplemented on Windows")
 }
 
 #[cfg(target_os = "macos")]
@@ -1420,7 +1439,7 @@ mod tests {
     use option::Some;
     use option;
     use os::{as_c_charp, env, getcwd, getenv, make_absolute, real_args};
-    use os::{remove_file, setenv};
+    use os::{remove_file, setenv, unsetenv};
     use os;
     use path::Path;
     use rand::RngUtil;
@@ -1457,6 +1476,14 @@ mod tests {
     }
 
     #[test]
+    fn test_unsetenv() {
+        let n = make_rand_name();
+        setenv(n, ~"VALUE");
+        unsetenv(n);
+        assert!(getenv(n) == option::None);
+    }
+
+    #[test]
     #[ignore(cfg(windows))]
     #[ignore]
     fn test_setenv_overwrite() {
@@ -1498,7 +1525,7 @@ mod tests {
     #[ignore]
     fn test_env_getenv() {
         let e = env();
-        assert!(vec::len(e) > 0u);
+        assert!(e.len() > 0u);
         for e.each |p| {
             let (n, v) = copy *p;
             debug!(copy n);
@@ -1589,7 +1616,7 @@ mod tests {
     fn list_dir() {
         let dirs = os::list_dir(&Path("."));
         // Just assuming that we've got some contents in the current directory
-        assert!((vec::len(dirs) > 0u));
+        assert!(dirs.len() > 0u);
 
         for dirs.each |dir| {
             debug!(copy *dir);
@@ -1643,7 +1670,7 @@ mod tests {
           let in_mode = in.get_mode();
           let rs = os::copy_file(&in, &out);
           if (!os::path_exists(&in)) {
-            fail!(fmt!("%s doesn't exist", in.to_str()));
+            fail!("%s doesn't exist", in.to_str());
           }
           assert!((rs));
           let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
diff --git a/src/libcore/path.rs b/src/libcore/path.rs
index c6c164c2728..2015c5474be 100644
--- a/src/libcore/path.rs
+++ b/src/libcore/path.rs
@@ -14,12 +14,16 @@ Cross-platform file path handling
 
 */
 
+use container::Container;
 use cmp::Eq;
 use libc;
 use option::{None, Option, Some};
 use str;
+use str::StrSlice;
 use to_str::ToStr;
 use ascii::{AsciiCast, AsciiStr};
+use old_iter::BaseIter;
+use vec::OwnedVector;
 
 #[cfg(windows)]
 pub use Path = self::WindowsPath;
diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs
index 9b664b334ba..c0cf4c052c5 100644
--- a/src/libcore/pipes.rs
+++ b/src/libcore/pipes.rs
@@ -82,6 +82,7 @@ bounded and unbounded protocols allows for less code duplication.
 
 */
 
+use container::Container;
 use cast::{forget, transmute, transmute_copy};
 use either::{Either, Left, Right};
 use kinds::Owned;
@@ -91,8 +92,10 @@ use option::{None, Option, Some};
 use unstable::finally::Finally;
 use unstable::intrinsics;
 use ptr;
+use ptr::Ptr;
 use task;
 use vec;
+use vec::OwnedVector;
 use util::replace;
 
 static SPIN_COUNT: uint = 0;
@@ -278,7 +281,7 @@ fn wait_event(this: *rust_task) -> *libc::c_void {
 
         let killed = rustrt::task_wait_event(this, &mut event);
         if killed && !task::failing() {
-            fail!(~"killed")
+            fail!("killed")
         }
         event
     }
@@ -362,7 +365,7 @@ pub fn send<T,Tbuffer>(mut p: SendPacketBuffered<T,Tbuffer>,
             //unsafe { forget(p); }
             return true;
         }
-        Full => fail!(~"duplicate send"),
+        Full => fail!("duplicate send"),
         Blocked => {
             debug!("waking up task for %?", p_);
             let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
@@ -475,7 +478,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
             debug!("woke up, p.state = %?", copy p.header.state);
           }
           Blocked => if first {
-            fail!(~"blocking on already blocked packet")
+            fail!("blocking on already blocked packet")
           },
           Full => {
             let payload = replace(&mut p.payload, None);
@@ -511,7 +514,7 @@ pub fn peek<T:Owned,Tb:Owned>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
     unsafe {
         match (*p.header()).state {
             Empty | Terminated => false,
-            Blocked => fail!(~"peeking on blocked packet"),
+            Blocked => fail!("peeking on blocked packet"),
             Full => true
         }
     }
@@ -540,7 +543,7 @@ fn sender_terminate<T:Owned>(p: *mut Packet<T>) {
       }
       Full => {
         // This is impossible
-        fail!(~"you dun goofed")
+        fail!("you dun goofed")
       }
       Terminated => {
         assert!(p.header.blocked_task.is_null());
@@ -606,7 +609,7 @@ pub fn wait_many<T: Selectable>(pkts: &mut [T]) -> uint {
                     (*p).state = old;
                     break;
                 }
-                Blocked => fail!(~"blocking on blocked packet"),
+                Blocked => fail!("blocking on blocked packet"),
                 Empty => ()
             }
         }
@@ -701,7 +704,7 @@ pub impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
                 let header = ptr::to_mut_unsafe_ptr(&mut packet.header);
                 header
             },
-            None => fail!(~"packet already consumed")
+            None => fail!("packet already consumed")
         }
     }
 
@@ -755,7 +758,7 @@ impl<T:Owned,Tbuffer:Owned> Selectable for RecvPacketBuffered<T, Tbuffer> {
                 let header = ptr::to_mut_unsafe_ptr(&mut packet.header);
                 header
             },
-            None => fail!(~"packet already consumed")
+            None => fail!("packet already consumed")
         }
     }
 }
@@ -813,7 +816,7 @@ pub fn select2<A:Owned,Ab:Owned,B:Owned,Bb:Owned>(
     match i {
         0 => Left((try_recv(a), b)),
         1 => Right((a, try_recv(b))),
-        _ => fail!(~"select2 return an invalid packet")
+        _ => fail!("select2 return an invalid packet")
     }
 }
 
@@ -837,7 +840,7 @@ pub fn select2i<A:Selectable,B:Selectable>(a: &mut A, b: &mut B)
     match wait_many(endpoints) {
         0 => Left(()),
         1 => Right(()),
-        _ => fail!(~"wait returned unexpected index")
+        _ => fail!("wait returned unexpected index")
     }
 }
 
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 22172db9302..4ed648161fc 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -27,7 +27,7 @@ pub use io::{print, println};
 
 /* Reexported types and traits */
 
-pub use clone::Clone;
+pub use clone::{Clone, DeepClone};
 pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
 pub use container::{Container, Mutable, Map, Set};
 pub use hash::Hash;
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 77e4143d090..e116dc01943 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -176,7 +176,7 @@ pub fn ref_eq<'a,'b,T>(thing: &'a T, other: &'b T) -> bool {
 pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
     debug!("array_each_with_len: before iterate");
     if (arr as uint == 0) {
-        fail!(~"ptr::array_each_with_len failure: arr input is null pointer");
+        fail!("ptr::array_each_with_len failure: arr input is null pointer");
     }
     //let start_ptr = *arr;
     uint::iterate(0, len, |e| {
@@ -198,7 +198,7 @@ pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
 */
 pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
     if (arr as uint == 0) {
-        fail!(~"ptr::array_each_with_len failure: arr input is null pointer");
+        fail!("ptr::array_each_with_len failure: arr input is null pointer");
     }
     let len = buf_len(arr);
     debug!("array_each inferred len: %u",
@@ -353,7 +353,7 @@ pub mod ptr_tests {
             assert!((p.fst == 50));
             assert!((p.snd == 60));
 
-            let mut v0 = ~[32000u16, 32001u16, 32002u16];
+            let v0 = ~[32000u16, 32001u16, 32002u16];
             let mut v1 = ~[0u16, 0u16, 0u16];
 
             copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 1u),
@@ -441,7 +441,7 @@ pub mod ptr_tests {
             let arr_ptr = &arr[0];
             let mut ctr = 0;
             let mut iteration_count = 0;
-            array_each_with_len(arr_ptr, vec::len(arr),
+            array_each_with_len(arr_ptr, arr.len(),
                                 |e| {
                                          let actual = str::raw::from_c_str(e);
                                          let expected = copy expected_arr[ctr];
diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs
index a645a7e8680..53f51fe1da2 100644
--- a/src/libcore/repr.rs
+++ b/src/libcore/repr.rs
@@ -25,10 +25,11 @@ use managed;
 use ptr;
 use reflect;
 use reflect::{MovePtr, align};
+use str::StrSlice;
 use to_str::ToStr;
-use vec::UnboxedVecRepr;
 use vec::raw::{VecRepr, SliceRepr};
 use vec;
+use vec::{OwnedVector, UnboxedVecRepr};
 
 #[cfg(test)] use io;
 
@@ -531,7 +532,7 @@ impl TyVisitor for ReprVisitor {
                         -> bool {
         let var_stk: &mut ~[VariantState] = self.var_stk;
         match var_stk.pop() {
-            SearchingFor(*) => fail!(~"enum value matched no variant"),
+            SearchingFor(*) => fail!("enum value matched no variant"),
             _ => true
         }
     }
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 1d67e754a4f..72704a429ed 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -17,7 +17,9 @@ use either;
 use either::Either;
 use kinds::Copy;
 use option::{None, Option, Some};
+use old_iter::BaseIter;
 use vec;
+use vec::OwnedVector;
 
 /// The result type
 #[deriving(Clone, Eq)]
@@ -40,7 +42,7 @@ pub fn get<T:Copy,U>(res: &Result<T, U>) -> T {
     match *res {
       Ok(copy t) => t,
       Err(ref the_err) =>
-        fail!(fmt!("get called on error result: %?", *the_err))
+        fail!("get called on error result: %?", *the_err)
     }
 }
 
@@ -56,7 +58,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T {
     match *res {
         Ok(ref t) => t,
         Err(ref the_err) =>
-            fail!(fmt!("get_ref called on error result: %?", *the_err))
+            fail!("get_ref called on error result: %?", *the_err)
     }
 }
 
@@ -71,7 +73,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T {
 pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U {
     match *res {
       Err(copy u) => u,
-      Ok(_) => fail!(~"get_err called on ok result")
+      Ok(_) => fail!("get_err called on ok result")
     }
 }
 
@@ -376,7 +378,7 @@ pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
 pub fn unwrap<T, U>(res: Result<T, U>) -> T {
     match res {
       Ok(t) => t,
-      Err(_) => fail!(~"unwrap called on an err result")
+      Err(_) => fail!("unwrap called on an err result")
     }
 }
 
@@ -385,7 +387,7 @@ pub fn unwrap<T, U>(res: Result<T, U>) -> T {
 pub fn unwrap_err<T, U>(res: Result<T, U>) -> U {
     match res {
       Err(u) => u,
-      Ok(_) => fail!(~"unwrap called on an ok result")
+      Ok(_) => fail!("unwrap called on an ok result")
     }
 }
 
diff --git a/src/libcore/rt/local_services.rs b/src/libcore/rt/local_services.rs
index 01bef5e2458..bc945707e62 100644
--- a/src/libcore/rt/local_services.rs
+++ b/src/libcore/rt/local_services.rs
@@ -163,7 +163,7 @@ pub fn borrow_local_services(f: &fn(&mut LocalServices)) {
                 f(&mut task.local_services)
             }
             None => {
-                fail!(~"no local services for schedulers yet")
+                fail!("no local services for schedulers yet")
             }
         }
     }
@@ -177,7 +177,7 @@ pub unsafe fn unsafe_borrow_local_services() -> &mut LocalServices {
             transmute_mut_region(&mut task.local_services)
         }
         None => {
-            fail!(~"no local services for schedulers yet")
+            fail!("no local services for schedulers yet")
         }
     }
 }
diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs
index 25f6c870654..fbbc8274340 100644
--- a/src/libcore/rt/mod.rs
+++ b/src/libcore/rt/mod.rs
@@ -13,6 +13,7 @@
 #[doc(hidden)];
 
 use libc::c_char;
+use ptr::Ptr;
 
 #[path = "sched/mod.rs"]
 mod sched;
diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs
index 663fe3e62d0..dda1f27550f 100644
--- a/src/libcore/rt/sched/mod.rs
+++ b/src/libcore/rt/sched/mod.rs
@@ -118,15 +118,15 @@ pub impl Scheduler {
     fn resume_task_from_queue(~self) -> bool {
         assert!(!self.in_task_context());
 
-        let mut self = self;
-        match self.task_queue.pop_front() {
+        let mut this = self;
+        match this.task_queue.pop_front() {
             Some(task) => {
-                self.resume_task_immediately(task);
+                this.resume_task_immediately(task);
                 return true;
             }
             None => {
                 rtdebug!("no tasks in queue");
-                local_sched::put(self);
+                local_sched::put(this);
                 return false;
             }
         }
@@ -165,16 +165,16 @@ pub impl Scheduler {
     // Core scheduling ops
 
     fn resume_task_immediately(~self, task: ~Task) {
-        let mut self = self;
-        assert!(!self.in_task_context());
+        let mut this = self;
+        assert!(!this.in_task_context());
 
         rtdebug!("scheduling a task");
 
         // Store the task in the scheduler so it can be grabbed later
-        self.current_task = Some(task);
-        self.enqueue_cleanup_job(DoNothing);
+        this.current_task = Some(task);
+        this.enqueue_cleanup_job(DoNothing);
 
-        local_sched::put(self);
+        local_sched::put(this);
 
         // Take pointers to both the task and scheduler's saved registers.
         unsafe {
@@ -203,17 +203,17 @@ pub impl Scheduler {
     /// running task.  It gets transmuted to the scheduler's lifetime
     /// and called while the task is blocked.
     fn deschedule_running_task_and_then(~self, f: &fn(~Task)) {
-        let mut self = self;
-        assert!(self.in_task_context());
+        let mut this = self;
+        assert!(this.in_task_context());
 
         rtdebug!("blocking task");
 
-        let blocked_task = self.current_task.swap_unwrap();
+        let blocked_task = this.current_task.swap_unwrap();
         let f_fake_region = unsafe { transmute::<&fn(~Task), &fn(~Task)>(f) };
         let f_opaque = ClosureConverter::from_fn(f_fake_region);
-        self.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque));
+        this.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque));
 
-        local_sched::put(self);
+        local_sched::put(this);
 
         let sched = unsafe { local_sched::unsafe_borrow() };
         let (sched_context, last_task_context, _) = sched.get_contexts();
@@ -229,18 +229,18 @@ pub impl Scheduler {
     /// You would want to think hard about doing this, e.g. if there are
     /// pending I/O events it would be a bad idea.
     fn switch_running_tasks_and_then(~self, next_task: ~Task, f: &fn(~Task)) {
-        let mut self = self;
-        assert!(self.in_task_context());
+        let mut this = self;
+        assert!(this.in_task_context());
 
         rtdebug!("switching tasks");
 
-        let old_running_task = self.current_task.swap_unwrap();
+        let old_running_task = this.current_task.swap_unwrap();
         let f_fake_region = unsafe { transmute::<&fn(~Task), &fn(~Task)>(f) };
         let f_opaque = ClosureConverter::from_fn(f_fake_region);
-        self.enqueue_cleanup_job(GiveTask(old_running_task, f_opaque));
-        self.current_task = Some(next_task);
+        this.enqueue_cleanup_job(GiveTask(old_running_task, f_opaque));
+        this.current_task = Some(next_task);
 
-        local_sched::put(self);
+        local_sched::put(this);
 
         unsafe {
             let sched = local_sched::unsafe_borrow();
@@ -295,7 +295,7 @@ pub impl Scheduler {
             Some(DoNothing) => {
                 None
             }
-            None => fail!(fmt!("all context switches should have a cleanup job"))
+            None => fail!("all context switches should have a cleanup job")
         };
         // XXX: Pattern matching mutable pointers above doesn't work
         // because borrowck thinks the three patterns are conflicting
diff --git a/src/libcore/rt/stack.rs b/src/libcore/rt/stack.rs
index 9eca3bda047..061d7dab9a1 100644
--- a/src/libcore/rt/stack.rs
+++ b/src/libcore/rt/stack.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use container::Container;
+use ptr::Ptr;
 use vec;
 
 pub struct StackSegment {
@@ -29,9 +31,7 @@ pub impl StackSegment {
 
     /// Point one word beyond the high end of the allocated stack
     fn end(&self) -> *uint {
-        unsafe {
-            vec::raw::to_ptr(self.buf).offset(self.buf.len()) as *uint
-        }
+        vec::raw::to_ptr(self.buf).offset(self.buf.len()) as *uint
     }
 }
 
diff --git a/src/libcore/rt/test.rs b/src/libcore/rt/test.rs
index 63db7054088..0c6843c605d 100644
--- a/src/libcore/rt/test.rs
+++ b/src/libcore/rt/test.rs
@@ -77,7 +77,7 @@ pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
 
     // Switch to the scheduler
     let f = Cell(Cell(f));
-    let mut sched = local_sched::take();
+    let sched = local_sched::take();
     do sched.deschedule_running_task_and_then() |old_task| {
         let old_task = Cell(old_task);
         let f = f.take();
diff --git a/src/libcore/rt/uv/mod.rs b/src/libcore/rt/uv/mod.rs
index 013a28abf28..1d93b327395 100644
--- a/src/libcore/rt/uv/mod.rs
+++ b/src/libcore/rt/uv/mod.rs
@@ -34,11 +34,13 @@ via `close` and `delete` methods.
 
 */
 
+use container::Container;
 use option::*;
 use str::raw::from_c_str;
 use to_str::ToStr;
 use vec;
 use ptr;
+use ptr::Ptr;
 use libc::{c_void, c_int, size_t, malloc, free};
 use cast::transmute;
 use ptr::null;
@@ -360,7 +362,7 @@ pub type Buf = uvll::uv_buf_t;
 
 /// Borrow a slice to a Buf
 pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
-    let data = unsafe { vec::raw::to_ptr(v) };
+    let data = vec::raw::to_ptr(v);
     unsafe { uvll::buf_init(data, v.len()) }
 }
 
diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs
index 068d6db2a43..3e6aa657c57 100644
--- a/src/libcore/rt/uv/net.rs
+++ b/src/libcore/rt/uv/net.rs
@@ -141,8 +141,8 @@ pub impl StreamWatcher {
 
     fn close(self, cb: NullCallback) {
         {
-            let mut self = self;
-            let data = get_watcher_data(&mut self);
+            let mut this = self;
+            let data = get_watcher_data(&mut this);
             assert!(data.close_cb.is_none());
             data.close_cb = Some(cb);
         }
@@ -388,7 +388,7 @@ fn listen() {
             assert!(status.is_none());
             let mut server_stream_watcher = server_stream_watcher;
             let mut loop_ = loop_;
-            let mut client_tcp_watcher = TcpWatcher::new(&mut loop_);
+            let client_tcp_watcher = TcpWatcher::new(&mut loop_);
             let mut client_tcp_watcher = client_tcp_watcher.as_stream();
             server_stream_watcher.accept(client_tcp_watcher);
             let count_cell = Cell(0);
diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs
index 62a165b6d77..24bffd8d1cd 100644
--- a/src/libcore/rt/uvio.rs
+++ b/src/libcore/rt/uvio.rs
@@ -15,10 +15,12 @@ use super::io::net::ip::IpAddr;
 use super::uv::*;
 use super::rtio::*;
 use ops::Drop;
+use old_iter::CopyableIter;
 use cell::{Cell, empty_cell};
 use cast::transmute;
 use super::sched::{Scheduler, local_sched};
 
+#[cfg(test)] use container::Container;
 #[cfg(test)] use uint;
 #[cfg(test)] use unstable::run_in_bare_thread;
 #[cfg(test)] use super::test::*;
@@ -43,10 +45,10 @@ pub impl UvEventLoop {
 impl Drop for UvEventLoop {
     fn finalize(&self) {
         // XXX: Need mutable finalizer
-        let self = unsafe {
+        let this = unsafe {
             transmute::<&UvEventLoop, &mut UvEventLoop>(self)
         };
-        self.uvio.uv_loop().close();
+        this.uvio.uv_loop().close();
     }
 }
 
@@ -426,7 +428,7 @@ fn test_read_read_read() {
                 let io = local_sched::unsafe_borrow_io();
                 let mut listener = io.bind(addr).unwrap();
                 let mut stream = listener.listen().unwrap();
-                let mut buf = [1, .. 2048];
+                let buf = [1, .. 2048];
                 let mut total_bytes_written = 0;
                 while total_bytes_written < MAX {
                     stream.write(buf);
diff --git a/src/libcore/rt/uvll.rs b/src/libcore/rt/uvll.rs
index 4bff3bff7d3..0d298bde6b5 100644
--- a/src/libcore/rt/uvll.rs
+++ b/src/libcore/rt/uvll.rs
@@ -221,7 +221,7 @@ pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int {
 
 pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int {
     let buf_ptr = vec::raw::to_ptr(buf_in);
-    let buf_cnt = vec::len(buf_in) as i32;
+    let buf_cnt = buf_in.len() as i32;
     return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb);
 }
 pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, on_read: *u8) -> c_int {
diff --git a/src/libcore/rt/work_queue.rs b/src/libcore/rt/work_queue.rs
index dfa88b783c5..495cd75a0bf 100644
--- a/src/libcore/rt/work_queue.rs
+++ b/src/libcore/rt/work_queue.rs
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use container::Container;
 use option::*;
+use vec::OwnedVector;
 
 pub struct WorkQueue<T> {
     priv queue: ~[T]
diff --git a/src/libcore/run.rs b/src/libcore/run.rs
index fd168dc02f6..c84e920a172 100644
--- a/src/libcore/run.rs
+++ b/src/libcore/run.rs
@@ -205,29 +205,29 @@ fn spawn_process_internal(prog: &str, args: &[~str],
 
         let orig_std_in = get_osfhandle(if in_fd > 0 { in_fd } else { 0 }) as HANDLE;
         if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
-            fail!(fmt!("failure in get_osfhandle: %s", os::last_os_error()));
+            fail!("failure in get_osfhandle: %s", os::last_os_error());
         }
         if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
                            0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!(fmt!("failure in DuplicateHandle: %s", os::last_os_error()));
+            fail!("failure in DuplicateHandle: %s", os::last_os_error());
         }
 
         let orig_std_out = get_osfhandle(if out_fd > 0 { out_fd } else { 1 }) as HANDLE;
         if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
-            fail!(fmt!("failure in get_osfhandle: %s", os::last_os_error()));
+            fail!("failure in get_osfhandle: %s", os::last_os_error());
         }
         if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
                            0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!(fmt!("failure in DuplicateHandle: %s", os::last_os_error()));
+            fail!("failure in DuplicateHandle: %s", os::last_os_error());
         }
 
         let orig_std_err = get_osfhandle(if err_fd > 0 { err_fd } else { 2 }) as HANDLE;
         if orig_std_err as HANDLE == INVALID_HANDLE_VALUE as HANDLE {
-            fail!(fmt!("failure in get_osfhandle: %s", os::last_os_error()));
+            fail!("failure in get_osfhandle: %s", os::last_os_error());
         }
         if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
                            0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!(fmt!("failure in DuplicateHandle: %s", os::last_os_error()));
+            fail!("failure in DuplicateHandle: %s", os::last_os_error());
         }
 
         let cmd = make_command_line(prog, args);
@@ -252,7 +252,7 @@ fn spawn_process_internal(prog: &str, args: &[~str],
         CloseHandle(si.hStdError);
 
         for create_err.each |msg| {
-            fail!(fmt!("failure in CreateProcess: %s", *msg));
+            fail!("failure in CreateProcess: %s", *msg);
         }
 
         // We close the thread handle because we don't care about keeping the thread id valid,
@@ -379,7 +379,7 @@ fn spawn_process_internal(prog: &str, args: &[~str],
 
         let pid = fork();
         if pid < 0 {
-            fail!(fmt!("failure in fork: %s", os::last_os_error()));
+            fail!("failure in fork: %s", os::last_os_error());
         } else if pid > 0 {
             return RunProgramResult {pid: pid, handle: ptr::null()};
         }
@@ -387,13 +387,13 @@ fn spawn_process_internal(prog: &str, args: &[~str],
         rustrt::rust_unset_sigprocmask();
 
         if in_fd > 0 && dup2(in_fd, 0) == -1 {
-            fail!(fmt!("failure in dup2(in_fd, 0): %s", os::last_os_error()));
+            fail!("failure in dup2(in_fd, 0): %s", os::last_os_error());
         }
         if out_fd > 0 && dup2(out_fd, 1) == -1 {
-            fail!(fmt!("failure in dup2(out_fd, 1): %s", os::last_os_error()));
+            fail!("failure in dup2(out_fd, 1): %s", os::last_os_error());
         }
         if err_fd > 0 && dup2(err_fd, 2) == -1 {
-            fail!(fmt!("failure in dup3(err_fd, 2): %s", os::last_os_error()));
+            fail!("failure in dup3(err_fd, 2): %s", os::last_os_error());
         }
         // close all other fds
         for int::range_rev(getdtablesize() as int - 1, 2) |fd| {
@@ -403,7 +403,7 @@ fn spawn_process_internal(prog: &str, args: &[~str],
         for dir.each |dir| {
             do str::as_c_str(*dir) |dirp| {
                 if chdir(dirp) == -1 {
-                    fail!(fmt!("failure in chdir: %s", os::last_os_error()));
+                    fail!("failure in chdir: %s", os::last_os_error());
                 }
             }
         }
@@ -415,7 +415,7 @@ fn spawn_process_internal(prog: &str, args: &[~str],
             do with_argv(prog, args) |argv| {
                 execvp(*argv, argv);
                 // execvp only returns if an error occurred
-                fail!(fmt!("failure in execvp: %s", os::last_os_error()));
+                fail!("failure in execvp: %s", os::last_os_error());
             }
         }
     }
@@ -646,8 +646,7 @@ pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput {
                 errs = s;
             }
             (n, _) => {
-                fail!(fmt!("program_output received an unexpected file \
-                           number: %u", n));
+                fail!("program_output received an unexpected file number: %u", n);
             }
         };
         count -= 1;
@@ -713,14 +712,14 @@ pub fn waitpid(pid: pid_t) -> int {
 
             let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
             if proc.is_null() {
-                fail!(fmt!("failure in OpenProcess: %s", os::last_os_error()));
+                fail!("failure in OpenProcess: %s", os::last_os_error());
             }
 
             loop {
                 let mut status = 0;
                 if GetExitCodeProcess(proc, &mut status) == FALSE {
                     CloseHandle(proc);
-                    fail!(fmt!("failure in GetExitCodeProcess: %s", os::last_os_error()));
+                    fail!("failure in GetExitCodeProcess: %s", os::last_os_error());
                 }
                 if status != STILL_ACTIVE {
                     CloseHandle(proc);
@@ -728,7 +727,7 @@ pub fn waitpid(pid: pid_t) -> int {
                 }
                 if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED {
                     CloseHandle(proc);
-                    fail!(fmt!("failure in WaitForSingleObject: %s", os::last_os_error()));
+                    fail!("failure in WaitForSingleObject: %s", os::last_os_error());
                 }
             }
         }
@@ -765,7 +764,7 @@ pub fn waitpid(pid: pid_t) -> int {
 
         let mut status = 0 as c_int;
         if unsafe { waitpid(pid, &mut status, 0) } == -1 {
-            fail!(fmt!("failure in waitpid: %s", os::last_os_error()));
+            fail!("failure in waitpid: %s", os::last_os_error());
         }
 
         return if WIFEXITED(status) {
@@ -778,7 +777,6 @@ pub fn waitpid(pid: pid_t) -> int {
 
 #[cfg(test)]
 mod tests {
-    use libc;
     use option::None;
     use os;
     use run::{readclose, writeclose};
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 3e2116dda0d..ec7177e5211 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -23,14 +23,19 @@ use cast;
 use char;
 use clone::Clone;
 use cmp::{TotalOrd, Ordering, Less, Equal, Greater};
+use container::Container;
+use iter::Times;
+use iterator::Iterator;
 use libc;
 use option::{None, Option, Some};
-use iterator::Iterator;
+use old_iter::{BaseIter, EqIter};
 use ptr;
+use ptr::Ptr;
 use str;
+use to_str::ToStr;
 use uint;
 use vec;
-use to_str::ToStr;
+use vec::{OwnedVector, OwnedCopyableVector};
 
 #[cfg(not(test))] use cmp::{Eq, Ord, Equiv, TotalEq};
 
@@ -1046,8 +1051,8 @@ pub fn _each_split_within<'a>(ss: &'a str,
 
             (B, Cr, UnderLim) => { B }
             (B, Cr, OverLim)  if (i - last_start + 1) > lim
-                              => fail!(fmt!("word starting with %? longer than limit!",
-                                            self::slice(ss, last_start, i + 1))),
+                              => fail!("word starting with %? longer than limit!",
+                                       self::slice(ss, last_start, i + 1)),
             (B, Cr, OverLim)  => { slice(); slice_start = last_start; B }
             (B, Ws, UnderLim) => { last_end = i; C }
             (B, Ws, OverLim)  => { last_end = i; slice(); A }
@@ -2054,7 +2059,7 @@ pub fn is_utf8(v: &const [u8]) -> bool {
 
 /// Determines if a vector of `u16` contains valid UTF-16
 pub fn is_utf16(v: &[u16]) -> bool {
-    let len = vec::len(v);
+    let len = v.len();
     let mut i = 0u;
     while (i < len) {
         let u = v[i];
@@ -2098,7 +2103,7 @@ pub fn to_utf16(s: &str) -> ~[u16] {
 }
 
 pub fn utf16_chars(v: &[u16], f: &fn(char)) {
-    let len = vec::len(v);
+    let len = v.len();
     let mut i = 0u;
     while (i < len && v[i] != 0u16) {
         let u = v[i];
@@ -2123,7 +2128,7 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) {
 
 pub fn from_utf16(v: &[u16]) -> ~str {
     let mut buf = ~"";
-    reserve(&mut buf, vec::len(v));
+    reserve(&mut buf, v.len());
     utf16_chars(v, |ch| push_char(&mut buf, ch));
     buf
 }
@@ -2393,7 +2398,7 @@ static tag_six_b: uint = 252u;
  * # Example
  *
  * ~~~
- * let i = str::as_bytes("Hello World") { |bytes| vec::len(bytes) };
+ * let i = str::as_bytes("Hello World") { |bytes| bytes.len() };
  * ~~~
  */
 #[inline]
@@ -3133,13 +3138,16 @@ impl<'self> Iterator<char> for StrCharIterator<'self> {
 
 #[cfg(test)]
 mod tests {
+    use container::Container;
     use char;
     use option::Some;
     use libc::c_char;
     use libc;
+    use old_iter::BaseIter;
     use ptr;
     use str::*;
     use vec;
+    use vec::ImmutableVector;
     use cmp::{TotalOrd, Less, Equal, Greater};
 
     #[test]
diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs
index 73f556518fa..4e239c4c82c 100644
--- a/src/libcore/str/ascii.rs
+++ b/src/libcore/str/ascii.rs
@@ -12,7 +12,10 @@
 
 use to_str::{ToStr,ToStrConsume};
 use str;
+use str::StrSlice;
 use cast;
+use old_iter::BaseIter;
+use vec::{CopyableVector, ImmutableVector, OwnedVector};
 
 /// Datatype to hold one ascii character. It is 8 bit long.
 #[deriving(Clone, Eq)]
diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs
index a30db039f30..766815a5e90 100644
--- a/src/libcore/task/local_data_priv.rs
+++ b/src/libcore/task/local_data_priv.rs
@@ -94,12 +94,10 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
     let map_ptr = rt::rust_get_task_local_data(task);
     if map_ptr.is_null() {
         let map: TaskLocalMap = @mut ~[];
+        // NB: This bumps the ref count before converting to an unsafe pointer,
+        // keeping the map alive until TLS is destroyed
         rt::rust_set_task_local_data(task, cast::transmute(map));
         rt::rust_task_local_data_atexit(task, cleanup_task_local_map_extern_cb);
-        // Also need to reference it an extra time to keep it for now.
-        let nonmut = cast::transmute::<TaskLocalMap,
-                                       @~[Option<TaskLocalElement>]>(map);
-        cast::bump_box_refcount(nonmut);
         map
     } else {
         let map = cast::transmute(map_ptr);
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index 2484d8c5fed..d57bd5528bc 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -198,7 +198,7 @@ pub fn task() -> TaskBuilder {
 priv impl TaskBuilder {
     fn consume(&mut self) -> TaskBuilder {
         if self.consumed {
-            fail!(~"Cannot copy a task_builder"); // Fake move mode on self
+            fail!("Cannot copy a task_builder"); // Fake move mode on self
         }
         self.consumed = true;
         let gen_body = replace(&mut self.gen_body, None);
@@ -263,7 +263,7 @@ pub impl TaskBuilder {
         // sending out messages.
 
         if self.opts.notify_chan.is_some() {
-            fail!(~"Can't set multiple future_results for one task!");
+            fail!("Can't set multiple future_results for one task!");
         }
 
         // Construct the future and give it to the caller.
@@ -494,7 +494,7 @@ pub fn yield() {
         let task_ = rt::rust_get_task();
         let killed = rt::rust_task_yield(task_);
         if killed && !failing() {
-            fail!(~"killed");
+            fail!("killed");
         }
     }
 }
@@ -772,7 +772,7 @@ fn test_add_wrapper() {
     do b0.add_wrapper |body| {
         let ch = Cell(ch.take());
         let result: ~fn() = || {
-            let mut ch = ch.take();
+            let ch = ch.take();
             body();
             ch.send(());
         };
diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs
index 327b7a988aa..fc38702bc16 100644
--- a/src/libcore/task/spawn.rs
+++ b/src/libcore/task/spawn.rs
@@ -78,7 +78,6 @@ use cell::Cell;
 use container::Map;
 use comm::{Chan, GenericChan};
 use prelude::*;
-use unstable;
 use ptr;
 use hashmap::HashSet;
 use task::local_data_priv::{local_get, local_set, OldHandle};
@@ -90,6 +89,7 @@ use task::{ExistingScheduler, SchedulerHandle};
 use task::unkillable;
 use uint;
 use util;
+use unstable::sync::{Exclusive, exclusive};
 
 #[cfg(test)] use task::default_task_opts;
 
@@ -128,7 +128,7 @@ struct TaskGroupData {
     // tasks in this group.
     descendants: TaskSet,
 }
-type TaskGroupArc = unstable::Exclusive<Option<TaskGroupData>>;
+type TaskGroupArc = Exclusive<Option<TaskGroupData>>;
 
 type TaskGroupInner<'self> = &'self mut Option<TaskGroupData>;
 
@@ -158,7 +158,7 @@ struct AncestorNode {
     ancestors:      AncestorList,
 }
 
-struct AncestorList(Option<unstable::Exclusive<AncestorNode>>);
+struct AncestorList(Option<Exclusive<AncestorNode>>);
 
 // Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
 #[inline(always)]
@@ -167,7 +167,7 @@ fn access_group<U>(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U {
 }
 
 #[inline(always)]
-fn access_ancestors<U>(x: &unstable::Exclusive<AncestorNode>,
+fn access_ancestors<U>(x: &Exclusive<AncestorNode>,
                        blk: &fn(x: &mut AncestorNode) -> U) -> U {
     x.with(blk)
 }
@@ -479,7 +479,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
                     // here.
                     let mut members = new_taskset();
                     taskset_insert(&mut members, spawner);
-                    let tasks = unstable::exclusive(Some(TaskGroupData {
+                    let tasks = exclusive(Some(TaskGroupData {
                         members: members,
                         descendants: new_taskset(),
                     }));
@@ -508,7 +508,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
             (g, a, spawner_group.is_main)
         } else {
             // Child is in a separate group from spawner.
-            let g = unstable::exclusive(Some(TaskGroupData {
+            let g = exclusive(Some(TaskGroupData {
                 members:     new_taskset(),
                 descendants: new_taskset(),
             }));
@@ -528,7 +528,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
                     };
                 assert!(new_generation < uint::max_value);
                 // Build a new node in the ancestor list.
-                AncestorList(Some(unstable::exclusive(AncestorNode {
+                AncestorList(Some(exclusive(AncestorNode {
                     generation: new_generation,
                     parent_group: Some(spawner_group.tasks.clone()),
                     ancestors: old_ancestors,
@@ -569,10 +569,10 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
             spawn_raw_newsched(opts, f)
         }
         SchedulerContext => {
-            fail!(~"can't spawn from scheduler context")
+            fail!("can't spawn from scheduler context")
         }
         GlobalContext => {
-            fail!(~"can't spawn from global context")
+            fail!("can't spawn from global context")
         }
     }
 }
@@ -708,7 +708,7 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
 
     fn new_task_in_sched(opts: SchedOpts) -> *rust_task {
         if opts.foreign_stack_size != None {
-            fail!(~"foreign_stack_size scheduler option unimplemented");
+            fail!("foreign_stack_size scheduler option unimplemented");
         }
 
         let num_threads = match opts.mode {
@@ -719,11 +719,11 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
             SingleThreaded => 1u,
             ThreadPerCore => unsafe { rt::rust_num_threads() },
             ThreadPerTask => {
-                fail!(~"ThreadPerTask scheduling mode unimplemented")
+                fail!("ThreadPerTask scheduling mode unimplemented")
             }
             ManualThreads(threads) => {
                 if threads == 0u {
-                    fail!(~"can not create a scheduler with no threads");
+                    fail!("can not create a scheduler with no threads");
                 }
                 threads
             }
diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs
index 182a03da4b1..ad42881ffa0 100644
--- a/src/libcore/to_bytes.rs
+++ b/src/libcore/to_bytes.rs
@@ -17,6 +17,7 @@ The `ToBytes` and `IterBytes` traits
 use io;
 use io::Writer;
 use option::{None, Option, Some};
+use old_iter::BaseIter;
 use str;
 
 pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool;
@@ -457,6 +458,7 @@ pub fn iter_bytes_2<A:IterBytes,B:IterBytes>(a: &A, b: &B,
     b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
 }
 #[cfg(not(stage0))]
+#[inline(always)]
 pub fn iter_bytes_2<A:IterBytes,B:IterBytes>(a: &A, b: &B,
                                              lsb0: bool, z: Cb) -> bool {
     a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z)
diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs
index 58a9f768644..365cb847740 100644
--- a/src/libcore/to_str.rs
+++ b/src/libcore/to_str.rs
@@ -20,6 +20,7 @@ use hashmap::HashSet;
 use container::Map;
 use hash::Hash;
 use cmp::Eq;
+use old_iter::BaseIter;
 
 pub trait ToStr {
     fn to_str(&self) -> ~str;
@@ -236,4 +237,4 @@ mod tests {
         assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}");
         assert!(empty_set.to_str() == ~"{}");
     }
-}
\ No newline at end of file
+}
diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs
deleted file mode 100644
index 25e4d07b01d..00000000000
--- a/src/libcore/unstable.rs
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[doc(hidden)];
-
-use cast;
-use libc;
-use comm::{GenericChan, GenericPort};
-use prelude::*;
-use task;
-use task::atomically;
-use self::finally::Finally;
-
-#[path = "unstable/at_exit.rs"]
-pub mod at_exit;
-#[path = "unstable/global.rs"]
-pub mod global;
-#[path = "unstable/finally.rs"]
-pub mod finally;
-#[path = "unstable/weak_task.rs"]
-pub mod weak_task;
-#[path = "unstable/exchange_alloc.rs"]
-pub mod exchange_alloc;
-#[path = "unstable/intrinsics.rs"]
-pub mod intrinsics;
-#[path = "unstable/simd.rs"]
-pub mod simd;
-#[path = "unstable/extfmt.rs"]
-pub mod extfmt;
-#[path = "unstable/lang.rs"]
-#[cfg(not(test))]
-pub mod lang;
-
-mod rustrt {
-    use unstable::{raw_thread, rust_little_lock};
-
-    pub extern {
-        pub unsafe fn rust_create_little_lock() -> rust_little_lock;
-        pub unsafe fn rust_destroy_little_lock(lock: rust_little_lock);
-        pub unsafe fn rust_lock_little_lock(lock: rust_little_lock);
-        pub unsafe fn rust_unlock_little_lock(lock: rust_little_lock);
-
-        pub unsafe fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
-        pub unsafe fn rust_raw_thread_join_delete(thread: *raw_thread);
-    }
-}
-
-#[allow(non_camel_case_types)] // runtime type
-pub type raw_thread = libc::c_void;
-
-/**
-
-Start a new thread outside of the current runtime context and wait
-for it to terminate.
-
-The executing thread has no access to a task pointer and will be using
-a normal large stack.
-*/
-pub fn run_in_bare_thread(f: ~fn()) {
-    let (port, chan) = comm::stream();
-    // FIXME #4525: Unfortunate that this creates an extra scheduler but it's
-    // necessary since rust_raw_thread_join_delete is blocking
-    do task::spawn_sched(task::SingleThreaded) {
-        unsafe {
-            let closure: &fn() = || {
-                f()
-            };
-            let thread = rustrt::rust_raw_thread_start(&closure);
-            rustrt::rust_raw_thread_join_delete(thread);
-            chan.send(());
-        }
-    }
-    port.recv();
-}
-
-#[test]
-fn test_run_in_bare_thread() {
-    let i = 100;
-    do run_in_bare_thread {
-        assert!(i == 100);
-    }
-}
-
-#[test]
-fn test_run_in_bare_thread_exchange() {
-    // Does the exchange heap work without the runtime?
-    let i = ~100;
-    do run_in_bare_thread {
-        assert!(i == ~100);
-    }
-}
-
-fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool {
-    unsafe {
-        let old = intrinsics::atomic_cxchg(address, oldval, newval);
-        old == oldval
-    }
-}
-
-/****************************************************************************
- * Shared state & exclusive ARC
- ****************************************************************************/
-
-struct ArcData<T> {
-    count:     libc::intptr_t,
-    // FIXME(#3224) should be able to make this non-option to save memory
-    data:      Option<T>,
-}
-
-struct ArcDestruct<T> {
-    data: *libc::c_void,
-}
-
-#[unsafe_destructor]
-impl<T> Drop for ArcDestruct<T>{
-    fn finalize(&self) {
-        unsafe {
-            do task::unkillable {
-                let mut data: ~ArcData<T> = cast::transmute(self.data);
-                let new_count =
-                    intrinsics::atomic_xsub(&mut data.count, 1) - 1;
-                assert!(new_count >= 0);
-                if new_count == 0 {
-                    // drop glue takes over.
-                } else {
-                    cast::forget(data);
-                }
-            }
-        }
-    }
-}
-
-fn ArcDestruct<T>(data: *libc::c_void) -> ArcDestruct<T> {
-    ArcDestruct {
-        data: data
-    }
-}
-
-/**
- * COMPLETELY UNSAFE. Used as a primitive for the safe versions in std::arc.
- *
- * Data races between tasks can result in crashes and, with sufficient
- * cleverness, arbitrary type coercion.
- */
-pub type SharedMutableState<T> = ArcDestruct<T>;
-
-pub unsafe fn shared_mutable_state<T:Owned>(data: T) ->
-        SharedMutableState<T> {
-    let data = ~ArcData { count: 1, data: Some(data) };
-    let ptr = cast::transmute(data);
-    ArcDestruct(ptr)
-}
-
-#[inline(always)]
-pub unsafe fn get_shared_mutable_state<T:Owned>(
-    rc: *SharedMutableState<T>) -> *mut T
-{
-    let ptr: ~ArcData<T> = cast::transmute((*rc).data);
-    assert!(ptr.count > 0);
-    let r = cast::transmute(ptr.data.get_ref());
-    cast::forget(ptr);
-    return r;
-}
-#[inline(always)]
-pub unsafe fn get_shared_immutable_state<'a,T:Owned>(
-        rc: &'a SharedMutableState<T>) -> &'a T {
-    let ptr: ~ArcData<T> = cast::transmute((*rc).data);
-    assert!(ptr.count > 0);
-    // Cast us back into the correct region
-    let r = cast::transmute_region(ptr.data.get_ref());
-    cast::forget(ptr);
-    return r;
-}
-
-pub unsafe fn clone_shared_mutable_state<T:Owned>(rc: &SharedMutableState<T>)
-        -> SharedMutableState<T> {
-    let mut ptr: ~ArcData<T> = cast::transmute((*rc).data);
-    let new_count = intrinsics::atomic_xadd(&mut ptr.count, 1) + 1;
-    assert!(new_count >= 2);
-    cast::forget(ptr);
-    ArcDestruct((*rc).data)
-}
-
-impl<T:Owned> Clone for SharedMutableState<T> {
-    fn clone(&self) -> SharedMutableState<T> {
-        unsafe {
-            clone_shared_mutable_state(self)
-        }
-    }
-}
-
-/****************************************************************************/
-
-#[allow(non_camel_case_types)] // runtime type
-pub type rust_little_lock = *libc::c_void;
-
-struct LittleLock {
-    l: rust_little_lock,
-}
-
-impl Drop for LittleLock {
-    fn finalize(&self) {
-        unsafe {
-            rustrt::rust_destroy_little_lock(self.l);
-        }
-    }
-}
-
-fn LittleLock() -> LittleLock {
-    unsafe {
-        LittleLock {
-            l: rustrt::rust_create_little_lock()
-        }
-    }
-}
-
-pub impl LittleLock {
-    #[inline(always)]
-    unsafe fn lock<T>(&self, f: &fn() -> T) -> T {
-        do atomically {
-            rustrt::rust_lock_little_lock(self.l);
-            do (|| {
-                f()
-            }).finally {
-                rustrt::rust_unlock_little_lock(self.l);
-            }
-        }
-    }
-}
-
-struct ExData<T> {
-    lock: LittleLock,
-    failed: bool,
-    data: T,
-}
-
-/**
- * An arc over mutable data that is protected by a lock. For library use only.
- */
-pub struct Exclusive<T> {
-    x: SharedMutableState<ExData<T>>
-}
-
-pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
-    let data = ExData {
-        lock: LittleLock(),
-        failed: false,
-        data: user_data
-    };
-    Exclusive {
-        x: unsafe {
-            shared_mutable_state(data)
-        }
-    }
-}
-
-impl<T:Owned> Clone for Exclusive<T> {
-    // Duplicate an exclusive ARC, as std::arc::clone.
-    fn clone(&self) -> Exclusive<T> {
-        Exclusive { x: unsafe { clone_shared_mutable_state(&self.x) } }
-    }
-}
-
-pub impl<T:Owned> Exclusive<T> {
-    // Exactly like std::arc::mutex_arc,access(), but with the little_lock
-    // instead of a proper mutex. Same reason for being unsafe.
-    //
-    // Currently, scheduling operations (i.e., yielding, receiving on a pipe,
-    // accessing the provided condition variable) are prohibited while inside
-    // the exclusive. Supporting that is a work in progress.
-    #[inline(always)]
-    unsafe fn with<U>(&self, f: &fn(x: &mut T) -> U) -> U {
-        let rec = get_shared_mutable_state(&self.x);
-        do (*rec).lock.lock {
-            if (*rec).failed {
-                fail!(
-                    ~"Poisoned exclusive - another task failed inside!");
-            }
-            (*rec).failed = true;
-            let result = f(&mut (*rec).data);
-            (*rec).failed = false;
-            result
-        }
-    }
-
-    #[inline(always)]
-    unsafe fn with_imm<U>(&self, f: &fn(x: &T) -> U) -> U {
-        do self.with |x| {
-            f(cast::transmute_immut(x))
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use comm;
-    use super::exclusive;
-    use task;
-    use uint;
-
-    #[test]
-    fn exclusive_arc() {
-        let mut futures = ~[];
-
-        let num_tasks = 10;
-        let count = 10;
-
-        let total = exclusive(~0);
-
-        for uint::range(0, num_tasks) |_i| {
-            let total = total.clone();
-            let (port, chan) = comm::stream();
-            futures.push(port);
-
-            do task::spawn || {
-                for uint::range(0, count) |_i| {
-                    do total.with |count| {
-                        **count += 1;
-                    }
-                }
-                chan.send(());
-            }
-        };
-
-        for futures.each |f| { f.recv() }
-
-        do total.with |total| {
-            assert!(**total == num_tasks * count)
-        };
-    }
-
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn exclusive_poison() {
-        // Tests that if one task fails inside of an exclusive, subsequent
-        // accesses will also fail.
-        let x = exclusive(1);
-        let x2 = x.clone();
-        do task::try || {
-            do x2.with |one| {
-                assert!(*one == 2);
-            }
-        };
-        do x.with |one| {
-            assert!(*one == 1);
-        }
-    }
-}
diff --git a/src/libcore/unstable/exchange_alloc.rs b/src/libcore/unstable/exchange_alloc.rs
index 57ed579e88d..3b35c2fb804 100644
--- a/src/libcore/unstable/exchange_alloc.rs
+++ b/src/libcore/unstable/exchange_alloc.rs
@@ -46,7 +46,7 @@ stuff in exchange_alloc::malloc
 pub unsafe fn malloc_raw(size: uint) -> *c_void {
     let p = c_malloc(size as size_t);
     if p.is_null() {
-        fail!(~"Failure in malloc_raw: result ptr is null");
+        fail!("Failure in malloc_raw: result ptr is null");
     }
     p
 }
diff --git a/src/libcore/unstable/extfmt.rs b/src/libcore/unstable/extfmt.rs
index 258da9ff383..11ac8c14fe4 100644
--- a/src/libcore/unstable/extfmt.rs
+++ b/src/libcore/unstable/extfmt.rs
@@ -257,12 +257,12 @@ pub mod ct {
         let mut flags = ~[];
 
         while i < lim {
-            let f = match s[i] {
-                '-' as u8 => FlagLeftJustify,
-                '0' as u8 => FlagLeftZeroPad,
-                ' ' as u8 => FlagSpaceForSign,
-                '+' as u8 => FlagSignAlways,
-                '#' as u8 => FlagAlternate,
+            let f = match s[i] as char {
+                '-' => FlagLeftJustify,
+                '0' => FlagLeftZeroPad,
+                ' ' => FlagSpaceForSign,
+                '+' => FlagSignAlways,
+                '#' => FlagAlternate,
                 _ => break
             };
 
@@ -313,18 +313,18 @@ pub mod ct {
 
         // FIXME (#2249): Do we really want two signed types here?
         // How important is it to be printf compatible?
-        let t = match s[i] {
-            'b' as u8 => TyBool,
-            's' as u8 => TyStr,
-            'c' as u8 => TyChar,
-            'd' as u8 | 'i' as u8 => TyInt(Signed),
-            'u' as u8 => TyInt(Unsigned),
-            'x' as u8 => TyHex(CaseLower),
-            'X' as u8 => TyHex(CaseUpper),
-            't' as u8 => TyBits,
-            'o' as u8 => TyOctal,
-            'f' as u8 => TyFloat,
-            '?' as u8 => TyPoly,
+        let t = match s[i] as char {
+            'b' => TyBool,
+            's' => TyStr,
+            'c' => TyChar,
+            'd' | 'i' => TyInt(Signed),
+            'u' => TyInt(Unsigned),
+            'x' => TyHex(CaseLower),
+            'X' => TyHex(CaseUpper),
+            't' => TyBits,
+            'o' => TyOctal,
+            'f' => TyFloat,
+            '?' => TyPoly,
             _ => err(~"unknown type in conversion: " + s.substr(i, 1))
         };
 
diff --git a/src/libcore/unstable/global.rs b/src/libcore/unstable/global.rs
index eac686e28d1..88433f9cefe 100644
--- a/src/libcore/unstable/global.rs
+++ b/src/libcore/unstable/global.rs
@@ -31,14 +31,13 @@ use kinds::Owned;
 use libc::{c_void};
 use option::{Option, Some, None};
 use ops::Drop;
-use unstable::{Exclusive, exclusive};
+use unstable::sync::{Exclusive, exclusive};
 use unstable::at_exit::at_exit;
 use unstable::intrinsics::atomic_cxchg;
 use hashmap::HashMap;
 use sys::Closure;
 
-#[cfg(test)] use unstable::{SharedMutableState, shared_mutable_state};
-#[cfg(test)] use unstable::get_shared_immutable_state;
+#[cfg(test)] use unstable::sync::{UnsafeAtomicRcBox};
 #[cfg(test)] use task::spawn;
 #[cfg(test)] use uint;
 
@@ -234,18 +233,16 @@ extern {
 
 #[test]
 fn test_clone_rc() {
-    type MyType = SharedMutableState<int>;
-
-    fn key(_v: SharedMutableState<int>) { }
+    fn key(_v: UnsafeAtomicRcBox<int>) { }
 
     for uint::range(0, 100) |_| {
         do spawn {
             unsafe {
                 let val = do global_data_clone_create(key) {
-                    ~shared_mutable_state(10)
+                    ~UnsafeAtomicRcBox::new(10)
                 };
 
-                assert!(get_shared_immutable_state(&val) == &10);
+                assert!(val.get() == &10);
             }
         }
     }
@@ -253,18 +250,12 @@ fn test_clone_rc() {
 
 #[test]
 fn test_modify() {
-    type MyType = SharedMutableState<int>;
-
-    fn key(_v: SharedMutableState<int>) { }
+    fn key(_v: UnsafeAtomicRcBox<int>) { }
 
     unsafe {
         do global_data_modify(key) |v| {
             match v {
-                None => {
-                    unsafe {
-                        Some(~shared_mutable_state(10))
-                    }
-                }
+                None => { Some(~UnsafeAtomicRcBox::new(10)) }
                 _ => fail!()
             }
         }
@@ -272,7 +263,7 @@ fn test_modify() {
         do global_data_modify(key) |v| {
             match v {
                 Some(sms) => {
-                    let v = get_shared_immutable_state(sms);
+                    let v = sms.get();
                     assert!(*v == 10);
                     None
                 },
@@ -282,11 +273,7 @@ fn test_modify() {
 
         do global_data_modify(key) |v| {
             match v {
-                None => {
-                    unsafe {
-                        Some(~shared_mutable_state(10))
-                    }
-                }
+                None => { Some(~UnsafeAtomicRcBox::new(10)) }
                 _ => fail!()
             }
         }
diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs
index b8c0c4e4a92..1636abedf7a 100644
--- a/src/libcore/unstable/intrinsics.rs
+++ b/src/libcore/unstable/intrinsics.rs
@@ -8,62 +8,119 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-An attempt to move all intrinsic declarations to a single place,
-as mentioned in #3369
-The intrinsics are defined in librustc/middle/trans/foreign.rs.
+/*! rustc compiler intrinsics.
+
+The corresponding definitions are in librustc/middle/trans/foreign.rs.
+
+# Atomics
+
+The atomic intrinsics provide common atomic operations on machine
+words, with multiple possible memory orderings. They obey the same
+semantics as C++0x. See the LLVM documentation on [[atomics]].
+
+[atomics]: http://llvm.org/docs/Atomics.html
+
+A quick refresher on memory ordering:
+
+* Acquire - a barrier for aquiring a lock. Subsequent reads and writes
+  take place after the barrier.
+* Release - a barrier for releasing a lock. Preceding reads and writes
+  take place before the barrier.
+* Sequentially consistent - sequentially consistent operations are
+  guaranteed to happen in order. This is the standard mode for working
+  with atomic types and is equivalent to Java's `volatile`.
+
 */
 
 #[abi = "rust-intrinsic"]
 pub extern "rust-intrinsic" {
+
+    /// Atomic compare and exchange, sequentially consistent.
     pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
+    /// Atomic compare and exchange, acquire ordering.
     pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
+    /// Atomic compare and exchange, release ordering.
     pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
 
+    /// Atomic load, sequentially consistent.
     #[cfg(not(stage0))]
     pub fn atomic_load(src: &int) -> int;
+    /// Atomic load, acquire ordering.
     #[cfg(not(stage0))]
     pub fn atomic_load_acq(src: &int) -> int;
 
+    /// Atomic store, sequentially consistent.
     #[cfg(not(stage0))]
     pub fn atomic_store(dst: &mut int, val: int);
+    /// Atomic store, release ordering.
     #[cfg(not(stage0))]
     pub fn atomic_store_rel(dst: &mut int, val: int);
 
+    /// Atomic exchange, sequentially consistent.
     pub fn atomic_xchg(dst: &mut int, src: int) -> int;
+    /// Atomic exchange, acquire ordering.
     pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
+    /// Atomic exchange, release ordering.
     pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
 
+    /// Atomic addition, sequentially consistent.
     pub fn atomic_xadd(dst: &mut int, src: int) -> int;
+    /// Atomic addition, acquire ordering.
     pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
+    /// Atomic addition, release ordering.
     pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;
 
+    /// Atomic subtraction, sequentially consistent.
     pub fn atomic_xsub(dst: &mut int, src: int) -> int;
+    /// Atomic subtraction, acquire ordering.
     pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
+    /// Atomic subtraction, release ordering.
     pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
 
+    /// The size of a type in bytes.
+    ///
+    /// This is the exact number of bytes in memory taken up by a
+    /// value of the given type. In other words, a memset of this size
+    /// would *exactly* overwrite a value. When laid out in vectors
+    /// and structures there may be additional padding between
+    /// elements.
     pub fn size_of<T>() -> uint;
 
+    /// Move a value to a memory location containing a value.
+    ///
+    /// Drop glue is run on the destination, which must contain a
+    /// valid Rust value.
     pub fn move_val<T>(dst: &mut T, src: T);
+
+    /// Move a value to an uninitialized memory location.
+    ///
+    /// Drop glue is not run on the destination.
     pub fn move_val_init<T>(dst: &mut T, src: T);
 
     pub fn min_align_of<T>() -> uint;
     pub fn pref_align_of<T>() -> uint;
 
+    /// Get a static pointer to a type descriptor.
     pub fn get_tydesc<T>() -> *();
 
-    /// init is unsafe because it returns a zeroed-out datum,
+    /// Create a value initialized to zero.
+    ///
+    /// `init` is unsafe because it returns a zeroed-out datum,
     /// which is unsafe unless T is POD. We don't have a POD
-    /// kind yet. (See #4074)
+    /// kind yet. (See #4074).
     pub unsafe fn init<T>() -> T;
 
+    /// Create an uninitialized value.
     #[cfg(not(stage0))]
     pub unsafe fn uninit<T>() -> T;
 
-    /// forget is unsafe because the caller is responsible for
-    /// ensuring the argument is deallocated already
+    /// Move a value out of scope without running drop glue.
+    ///
+    /// `forget` is unsafe because the caller is responsible for
+    /// ensuring the argument is deallocated already.
     pub unsafe fn forget<T>(_: T) -> ();
 
+    /// Returns `true` if a type requires drop glue.
     pub fn needs_drop<T>() -> bool;
 
     // XXX: intrinsic uses legacy modes and has reference to TyDesc
@@ -72,9 +129,12 @@ pub extern "rust-intrinsic" {
     // XXX: intrinsic uses legacy modes
     //fn frame_address(f: &once fn(*u8));
 
+    /// Get the address of the `__morestack` stack growth function.
     pub fn morestack_addr() -> *();
 
+    /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic.
     pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
+    /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic.
     pub fn memmove64(dst: *mut u8, src: *u8, size: u64);
 
     pub fn sqrtf32(x: f32) -> f32;
diff --git a/src/libcore/unstable/mod.rs b/src/libcore/unstable/mod.rs
new file mode 100644
index 00000000000..bef7a7f87d3
--- /dev/null
+++ b/src/libcore/unstable/mod.rs
@@ -0,0 +1,78 @@
+// 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.
+
+#[doc(hidden)];
+
+use libc;
+use comm::{GenericChan, GenericPort};
+use prelude::*;
+use task;
+
+pub mod at_exit;
+pub mod global;
+pub mod finally;
+pub mod weak_task;
+pub mod exchange_alloc;
+pub mod intrinsics;
+pub mod simd;
+pub mod extfmt;
+#[cfg(not(test))]
+pub mod lang;
+pub mod sync;
+
+/**
+
+Start a new thread outside of the current runtime context and wait
+for it to terminate.
+
+The executing thread has no access to a task pointer and will be using
+a normal large stack.
+*/
+pub fn run_in_bare_thread(f: ~fn()) {
+    let (port, chan) = comm::stream();
+    // FIXME #4525: Unfortunate that this creates an extra scheduler but it's
+    // necessary since rust_raw_thread_join_delete is blocking
+    do task::spawn_sched(task::SingleThreaded) {
+        unsafe {
+            let closure: &fn() = || {
+                f()
+            };
+            let thread = rust_raw_thread_start(&closure);
+            rust_raw_thread_join_delete(thread);
+            chan.send(());
+        }
+    }
+    port.recv();
+}
+
+#[test]
+fn test_run_in_bare_thread() {
+    let i = 100;
+    do run_in_bare_thread {
+        assert!(i == 100);
+    }
+}
+
+#[test]
+fn test_run_in_bare_thread_exchange() {
+    // Does the exchange heap work without the runtime?
+    let i = ~100;
+    do run_in_bare_thread {
+        assert!(i == ~100);
+    }
+}
+
+#[allow(non_camel_case_types)] // runtime type
+pub type raw_thread = libc::c_void;
+
+extern {
+    fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
+    fn rust_raw_thread_join_delete(thread: *raw_thread);
+}
diff --git a/src/libcore/unstable/sync.rs b/src/libcore/unstable/sync.rs
new file mode 100644
index 00000000000..4d5c3bf7a78
--- /dev/null
+++ b/src/libcore/unstable/sync.rs
@@ -0,0 +1,285 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cast;
+use libc;
+use option::*;
+use task;
+use task::atomically;
+use unstable::finally::Finally;
+use unstable::intrinsics;
+use ops::Drop;
+use clone::Clone;
+use kinds::Owned;
+
+/// An atomically reference counted pointer.
+///
+/// Enforces no shared-memory safety.
+pub struct UnsafeAtomicRcBox<T> {
+    data: *mut libc::c_void,
+}
+
+struct AtomicRcBoxData<T> {
+    count: int,
+    data: Option<T>,
+}
+
+impl<T: Owned> UnsafeAtomicRcBox<T> {
+    pub fn new(data: T) -> UnsafeAtomicRcBox<T> {
+        unsafe {
+            let data = ~AtomicRcBoxData { count: 1, data: Some(data) };
+            let ptr = cast::transmute(data);
+            return UnsafeAtomicRcBox { data: ptr };
+        }
+    }
+
+    #[inline(always)]
+    #[cfg(stage0)]
+    pub unsafe fn get(&self) -> *mut T
+    {
+        let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+        assert!(data.count > 0);
+        let r: *mut T = cast::transmute(data.data.get_mut_ref());
+        cast::forget(data);
+        return r;
+    }
+
+    #[inline(always)]
+    #[cfg(not(stage0))]
+    pub unsafe fn get(&self) -> *mut T
+    {
+        let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+        assert!(data.count > 0);
+        let r: *mut T = data.data.get_mut_ref();
+        cast::forget(data);
+        return r;
+    }
+
+    #[inline(always)]
+    #[cfg(stage0)]
+    pub unsafe fn get_immut(&self) -> *T
+    {
+        let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+        assert!(data.count > 0);
+        let r: *T = cast::transmute(data.data.get_mut_ref());
+        cast::forget(data);
+        return r;
+    }
+
+    #[inline(always)]
+    #[cfg(not(stage0))]
+    pub unsafe fn get_immut(&self) -> *T
+    {
+        let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+        assert!(data.count > 0);
+        let r: *T = cast::transmute_immut(data.data.get_mut_ref());
+        cast::forget(data);
+        return r;
+    }
+}
+
+impl<T: Owned> Clone for UnsafeAtomicRcBox<T> {
+    fn clone(&self) -> UnsafeAtomicRcBox<T> {
+        unsafe {
+            let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+            let new_count = intrinsics::atomic_xadd(&mut data.count, 1) + 1;
+            assert!(new_count >= 2);
+            cast::forget(data);
+            return UnsafeAtomicRcBox { data: self.data };
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for UnsafeAtomicRcBox<T>{
+    fn finalize(&self) {
+        unsafe {
+            do task::unkillable {
+                let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+                let new_count = intrinsics::atomic_xsub(&mut data.count, 1) - 1;
+                assert!(new_count >= 0);
+                if new_count == 0 {
+                    // drop glue takes over.
+                } else {
+                    cast::forget(data);
+                }
+            }
+        }
+    }
+}
+
+
+/****************************************************************************/
+
+#[allow(non_camel_case_types)] // runtime type
+pub type rust_little_lock = *libc::c_void;
+
+struct LittleLock {
+    l: rust_little_lock,
+}
+
+impl Drop for LittleLock {
+    fn finalize(&self) {
+        unsafe {
+            rust_destroy_little_lock(self.l);
+        }
+    }
+}
+
+fn LittleLock() -> LittleLock {
+    unsafe {
+        LittleLock {
+            l: rust_create_little_lock()
+        }
+    }
+}
+
+pub impl LittleLock {
+    #[inline(always)]
+    unsafe fn lock<T>(&self, f: &fn() -> T) -> T {
+        do atomically {
+            rust_lock_little_lock(self.l);
+            do (|| {
+                f()
+            }).finally {
+                rust_unlock_little_lock(self.l);
+            }
+        }
+    }
+}
+
+struct ExData<T> {
+    lock: LittleLock,
+    failed: bool,
+    data: T,
+}
+
+/**
+ * An arc over mutable data that is protected by a lock. For library use only.
+ */
+pub struct Exclusive<T> {
+    x: UnsafeAtomicRcBox<ExData<T>>
+}
+
+pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
+    let data = ExData {
+        lock: LittleLock(),
+        failed: false,
+        data: user_data
+    };
+    Exclusive {
+        x: UnsafeAtomicRcBox::new(data)
+    }
+}
+
+impl<T:Owned> Clone for Exclusive<T> {
+    // Duplicate an exclusive ARC, as std::arc::clone.
+    fn clone(&self) -> Exclusive<T> {
+        Exclusive { x: self.x.clone() }
+    }
+}
+
+pub impl<T:Owned> Exclusive<T> {
+    // Exactly like std::arc::mutex_arc,access(), but with the little_lock
+    // instead of a proper mutex. Same reason for being unsafe.
+    //
+    // Currently, scheduling operations (i.e., yielding, receiving on a pipe,
+    // accessing the provided condition variable) are prohibited while inside
+    // the exclusive. Supporting that is a work in progress.
+    #[inline(always)]
+    unsafe fn with<U>(&self, f: &fn(x: &mut T) -> U) -> U {
+        let rec = self.x.get();
+        do (*rec).lock.lock {
+            if (*rec).failed {
+                fail!("Poisoned exclusive - another task failed inside!");
+            }
+            (*rec).failed = true;
+            let result = f(&mut (*rec).data);
+            (*rec).failed = false;
+            result
+        }
+    }
+
+    #[inline(always)]
+    unsafe fn with_imm<U>(&self, f: &fn(x: &T) -> U) -> U {
+        do self.with |x| {
+            f(cast::transmute_immut(x))
+        }
+    }
+}
+
+fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool {
+    unsafe {
+        let old = intrinsics::atomic_cxchg(address, oldval, newval);
+        old == oldval
+    }
+}
+
+extern {
+    fn rust_create_little_lock() -> rust_little_lock;
+    fn rust_destroy_little_lock(lock: rust_little_lock);
+    fn rust_lock_little_lock(lock: rust_little_lock);
+    fn rust_unlock_little_lock(lock: rust_little_lock);
+}
+
+#[cfg(test)]
+mod tests {
+    use comm;
+    use super::exclusive;
+    use task;
+    use uint;
+
+    #[test]
+    fn exclusive_arc() {
+        let mut futures = ~[];
+
+        let num_tasks = 10;
+        let count = 10;
+
+        let total = exclusive(~0);
+
+        for uint::range(0, num_tasks) |_i| {
+            let total = total.clone();
+            let (port, chan) = comm::stream();
+            futures.push(port);
+
+            do task::spawn || {
+                for uint::range(0, count) |_i| {
+                    do total.with |count| {
+                        **count += 1;
+                    }
+                }
+                chan.send(());
+            }
+        };
+
+        for futures.each |f| { f.recv() }
+
+        do total.with |total| {
+            assert!(**total == num_tasks * count)
+        };
+    }
+
+    #[test] #[should_fail] #[ignore(cfg(windows))]
+    fn exclusive_poison() {
+        // Tests that if one task fails inside of an exclusive, subsequent
+        // accesses will also fail.
+        let x = exclusive(1);
+        let x2 = x.clone();
+        do task::try || {
+            do x2.with |one| {
+                assert!(*one == 2);
+            }
+        };
+        do x.with |one| {
+            assert!(*one == 1);
+        }
+    }
+}
diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs
index 8670bcfcd9a..d5c5230cef8 100644
--- a/src/libcore/unstable/weak_task.rs
+++ b/src/libcore/unstable/weak_task.rs
@@ -191,7 +191,7 @@ fn test_select_stream_and_oneshot() {
     use comm::select2i;
     use either::{Left, Right};
 
-    let mut (port, chan) = stream();
+    let (port, chan) = stream();
     let port = Cell(port);
     let (waitport, waitchan) = stream();
     do spawn {
diff --git a/src/libcore/util.rs b/src/libcore/util.rs
index c6add76f944..e5067fb90bc 100644
--- a/src/libcore/util.rs
+++ b/src/libcore/util.rs
@@ -171,7 +171,7 @@ fn choose_weighted_item(v: &[Item]) -> Item {
 
 */
 pub fn unreachable() -> ! {
-    fail!(~"internal error: entered unreachable code");
+    fail!("internal error: entered unreachable code");
 }
 
 #[cfg(test)]
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 604f0297b64..4c6e0791ba2 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -22,9 +22,11 @@ use old_iter;
 use iterator::Iterator;
 use kinds::Copy;
 use libc;
+use old_iter::{BaseIter, CopyableIter};
 use option::{None, Option, Some};
 use ptr::to_unsafe_ptr;
 use ptr;
+use ptr::Ptr;
 use sys;
 use uint;
 use unstable::intrinsics;
@@ -235,7 +237,7 @@ pub fn build_sized_opt<A>(size: Option<uint>,
 
 /// Returns the first element of a vector
 pub fn head<'r,T>(v: &'r [T]) -> &'r T {
-    if v.len() == 0 { fail!(~"head: empty vector") }
+    if v.len() == 0 { fail!("head: empty vector") }
     &v[0]
 }
 
@@ -261,7 +263,7 @@ pub fn initn<'r,T>(v: &'r [T], n: uint) -> &'r [T] {
 
 /// Returns the last element of the slice `v`, failing if the slice is empty.
 pub fn last<'r,T>(v: &'r [T]) -> &'r T {
-    if v.len() == 0 { fail!(~"last: empty vector") }
+    if v.len() == 0 { fail!("last: empty vector") }
     &v[v.len() - 1]
 }
 
@@ -585,7 +587,7 @@ pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) {
 pub fn pop<T>(v: &mut ~[T]) -> T {
     let ln = v.len();
     if ln == 0 {
-        fail!(~"sorry, cannot vec::pop an empty vector")
+        fail!("sorry, cannot vec::pop an empty vector")
     }
     let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
     unsafe {
@@ -599,7 +601,7 @@ pub fn pop<T>(v: &mut ~[T]) -> T {
 pub fn pop<T>(v: &mut ~[T]) -> T {
     let ln = v.len();
     if ln == 0 {
-        fail!(~"sorry, cannot vec::pop an empty vector")
+        fail!("sorry, cannot vec::pop an empty vector")
     }
     let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
     unsafe {
@@ -618,7 +620,7 @@ pub fn pop<T>(v: &mut ~[T]) -> T {
 pub fn swap_remove<T>(v: &mut ~[T], index: uint) -> T {
     let ln = v.len();
     if index >= ln {
-        fail!(fmt!("vec::swap_remove - index %u >= length %u", index, ln));
+        fail!("vec::swap_remove - index %u >= length %u", index, ln);
     }
     if index < ln - 1 {
         swap(*v, index, ln - 1);
@@ -1443,6 +1445,46 @@ pub fn reverse<T>(v: &mut [T]) {
     }
 }
 
+/**
+ * Reverse part of a vector in place.
+ *
+ * Reverse the elements in the vector between `start` and `end - 1`.
+ *
+ * If either start or end do not represent valid positions in the vector, the
+ * vector is returned unchanged.
+ *
+ * # Arguments
+ *
+ * * `v` - The mutable vector to be modified
+ *
+ * * `start` - Index of the first element of the slice
+ *
+ * * `end` - Index one past the final element to be reversed.
+ *
+ * # Example
+ *
+ * Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call:
+ *
+ * ~~~
+ *
+ * reverse_part(v, 1, 4);
+ *
+ * ~~~
+ *
+ * `v` now contains `[1,4,3,2,5]`.
+ */
+pub fn reverse_part<T>(v: &mut [T], start: uint, end : uint) {
+    let sz = v.len();
+    if start >= sz || end > sz { return; }
+    let mut i = start;
+    let mut j = end - 1;
+    while i < j {
+        vec::swap(v, i, j);
+        i += 1;
+        j -= 1;
+    }
+}
+
 /// Returns a vector with the order of elements reversed
 pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] {
     let mut rs: ~[T] = ~[];
@@ -1681,8 +1723,8 @@ pub fn eachi_reverse<'r,T>(v: &'r [T],
  */
 #[inline]
 pub fn _each2<U, T>(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool {
-    assert!(len(v1) == len(v2));
-    for uint::range(0u, len(v1)) |i| {
+    assert!(v1.len() == v2.len());
+    for uint::range(0u, v1.len()) |i| {
         if !f(&v1[i], &v2[i]) {
             return false;
         }
@@ -1700,6 +1742,35 @@ pub fn each2<U, T>(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool {
 }
 
 /**
+ *
+ * Iterates over two vector with mutable.
+ *
+ * # Failure
+ *
+ * Both vectors must have the same length
+ */
+#[inline]
+pub fn _each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) -> bool {
+    assert!(v1.len() == v2.len());
+    for uint::range(0u, v1.len()) |i| {
+        if !f(&mut v1[i], &mut v2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+#[cfg(stage0)]
+pub fn each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) {
+    _each2_mut(v1, v2, f);
+}
+
+#[cfg(not(stage0))]
+pub fn each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) -> bool {
+    _each2_mut(v1, v2, f)
+}
+
+/**
  * Iterate over all permutations of vector `v`.
  *
  * Permutations are produced in lexicographic order with respect to the order
@@ -1708,29 +1779,49 @@ pub fn each2<U, T>(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool {
  *
  * The total number of permutations produced is `len(v)!`.  If `v` contains
  * repeated elements, then some permutations are repeated.
+ *
+ * See [Algorithms to generate
+ * permutations](http://en.wikipedia.org/wiki/Permutation).
+ *
+ *  # Arguments
+ *
+ *  * `values` - A vector of values from which the permutations are
+ *  chosen
+ *
+ *  * `fun` - The function to iterate over the combinations
  */
-#[cfg(not(stage0))]
-pub fn each_permutation<T:Copy>(v: &[T], put: &fn(ts: &[T]) -> bool) -> bool {
-    let ln = len(v);
-    if ln <= 1 {
-        put(v);
-    } else {
-        // This does not seem like the most efficient implementation.  You
-        // could make far fewer copies if you put your mind to it.
-        let mut i = 0u;
-        while i < ln {
-            let elt = v[i];
-            let mut rest = slice(v, 0u, i).to_vec();
-            rest.push_all(const_slice(v, i+1u, ln));
-            for each_permutation(rest) |permutation| {
-                if !put(append(~[elt], permutation)) {
-                    return false;
-                }
-            }
-            i += 1u;
+pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
+    let length = values.len();
+    let mut permutation = vec::from_fn(length, |i| values[i]);
+    if length <= 1 {
+        fun(permutation);
+        return true;
+    }
+    let mut indices = vec::from_fn(length, |i| i);
+    loop {
+        if !fun(permutation) { return true; }
+        // find largest k such that indices[k] < indices[k+1]
+        // if no such k exists, all permutations have been generated
+        let mut k = length - 2;
+        while k > 0 && indices[k] >= indices[k+1] {
+            k -= 1;
+        }
+        if k == 0 && indices[0] > indices[1] { return true; }
+        // find largest l such that indices[k] < indices[l]
+        // k+1 is guaranteed to be such
+        let mut l = length - 1;
+        while indices[k] >= indices[l] {
+            l -= 1;
+        }
+        // swap indices[k] and indices[l]; sort indices[k+1..]
+        // (they're just reversed)
+        vec::swap(indices, k, l);
+        reverse_part(indices, k+1, length);
+        // fixup permutation based on indices
+        for uint::range(k, length) |i| {
+            permutation[i] = values[indices[i]];
         }
     }
-    return true;
 }
 
 /**
@@ -2040,6 +2131,8 @@ pub trait ImmutableVector<'self, T> {
     fn initn(&self, n: uint) -> &'self [T];
     fn last(&self) -> &'self T;
     fn last_opt(&self) -> Option<&'self T>;
+    fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
+    fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
     #[cfg(stage0)]
     fn each_reverse(&self, blk: &fn(&T) -> bool);
     #[cfg(not(stage0))]
@@ -2107,6 +2200,30 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
     #[inline]
     fn last_opt(&self) -> Option<&'self T> { last_opt(*self) }
 
+    /**
+     * Find the first index matching some predicate
+     *
+     * Apply function `f` to each element of `v`.  When function `f` returns
+     * true then an option containing the index is returned. If `f` matches no
+     * elements then none is returned.
+     */
+    #[inline]
+    fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
+        position(*self, f)
+    }
+
+    /**
+     * Find the last index matching some predicate
+     *
+     * Apply function `f` to each element of `v` in reverse order.  When
+     * function `f` returns true then an option containing the index is
+     * returned. If `f` matches no elements then none is returned.
+     */
+    #[inline]
+    fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
+        rposition(*self, f)
+    }
+
     /// Iterates over a vector's elements in reverse.
     #[inline]
     #[cfg(stage0)]
@@ -2199,43 +2316,17 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
 }
 
 pub trait ImmutableEqVector<T:Eq> {
-    fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
     fn position_elem(&self, t: &T) -> Option<uint>;
-    fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
     fn rposition_elem(&self, t: &T) -> Option<uint>;
 }
 
 impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] {
-    /**
-     * Find the first index matching some predicate
-     *
-     * Apply function `f` to each element of `v`.  When function `f` returns
-     * true then an option containing the index is returned. If `f` matches no
-     * elements then none is returned.
-     */
-    #[inline]
-    fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
-        position(*self, f)
-    }
-
     /// Find the first index containing a matching value
     #[inline]
     fn position_elem(&self, x: &T) -> Option<uint> {
         position_elem(*self, x)
     }
 
-    /**
-     * Find the last index matching some predicate
-     *
-     * Apply function `f` to each element of `v` in reverse order.  When
-     * function `f` returns true then an option containing the index is
-     * returned. If `f` matches no elements then none is returned.
-     */
-    #[inline]
-    fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
-        rposition(*self, f)
-    }
-
     /// Find the last index containing a matching value
     #[inline]
     fn rposition_elem(&self, t: &T) -> Option<uint> {
@@ -2515,23 +2606,29 @@ pub mod raw {
      * would also make any pointers to it invalid.
      */
     #[inline(always)]
-    pub unsafe fn to_ptr<T>(v: &[T]) -> *T {
-        let repr: **SliceRepr = transmute(&v);
-        transmute(&((**repr).data))
+    pub fn to_ptr<T>(v: &[T]) -> *T {
+        unsafe {
+            let repr: **SliceRepr = transmute(&v);
+            transmute(&((**repr).data))
+        }
     }
 
     /** see `to_ptr()` */
     #[inline(always)]
-    pub unsafe fn to_const_ptr<T>(v: &const [T]) -> *const T {
-        let repr: **SliceRepr = transmute(&v);
-        transmute(&((**repr).data))
+    pub fn to_const_ptr<T>(v: &const [T]) -> *const T {
+        unsafe {
+            let repr: **SliceRepr = transmute(&v);
+            transmute(&((**repr).data))
+        }
     }
 
     /** see `to_ptr()` */
     #[inline(always)]
-    pub unsafe fn to_mut_ptr<T>(v: &mut [T]) -> *mut T {
-        let repr: **SliceRepr = transmute(&v);
-        transmute(&((**repr).data))
+    pub fn to_mut_ptr<T>(v: &mut [T]) -> *mut T {
+        unsafe {
+            let repr: **SliceRepr = transmute(&v);
+            transmute(&((**repr).data))
+        }
     }
 
     /**
@@ -3298,8 +3395,9 @@ mod tests {
     #[test]
     fn test_swap_remove_noncopyable() {
         // Tests that we don't accidentally run destructors twice.
-        let mut v = ~[::unstable::exclusive(()), ::unstable::exclusive(()),
-                      ::unstable::exclusive(())];
+        let mut v = ~[::unstable::sync::exclusive(()),
+                      ::unstable::sync::exclusive(()),
+                      ::unstable::sync::exclusive(())];
         let mut _e = v.swap_remove(0);
         assert!(v.len() == 2);
         _e = v.swap_remove(1);
@@ -3564,7 +3662,7 @@ mod tests {
         fn sub(a: int, b: &int) -> int {
             a - *b
         }
-        let mut v = ~[1, 2, 3, 4];
+        let v = ~[1, 2, 3, 4];
         let sum = foldl(0, v, sub);
         assert!(sum == -10);
     }
@@ -3574,7 +3672,7 @@ mod tests {
         fn sub(a: &int, b: int) -> int {
             *a - b
         }
-        let mut v = ~[1, 2, 3, 4];
+        let v = ~[1, 2, 3, 4];
         let sum = foldr(v, 0, sub);
         assert!(sum == -2);
     }
@@ -3738,7 +3836,7 @@ mod tests {
         assert!(position_between(~[], 0u, 0u, f).is_none());
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(position_between(v, 0u, 0u, f).is_none());
         assert!(position_between(v, 0u, 1u, f).is_none());
@@ -3767,7 +3865,7 @@ mod tests {
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
         fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(find(v, f) == Some((1, 'b')));
         assert!(find(v, g).is_none());
@@ -3778,7 +3876,7 @@ mod tests {
         assert!(find_between(~[], 0u, 0u, f).is_none());
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(find_between(v, 0u, 0u, f).is_none());
         assert!(find_between(v, 0u, 1u, f).is_none());
@@ -3807,7 +3905,7 @@ mod tests {
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
         fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(position(v, f) == Some(1u));
         assert!(position(v, g).is_none());
@@ -3818,7 +3916,7 @@ mod tests {
         assert!(rposition_between(~[], 0u, 0u, f).is_none());
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(rposition_between(v, 0u, 0u, f).is_none());
         assert!(rposition_between(v, 0u, 1u, f).is_none());
@@ -3847,7 +3945,7 @@ mod tests {
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
         fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(rfind(v, f) == Some((3, 'b')));
         assert!(rfind(v, g).is_none());
@@ -3858,7 +3956,7 @@ mod tests {
         assert!(rfind_between(~[], 0u, 0u, f).is_none());
 
         fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
-        let mut v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
 
         assert!(rfind_between(v, 0u, 0u, f).is_none());
         assert!(rfind_between(v, 0u, 1u, f).is_none());
@@ -4327,7 +4425,7 @@ mod tests {
     #[ignore(windows)]
     #[should_fail]
     fn test_map_fail() {
-        let mut v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
         let mut i = 0;
         do map(v) |_elt| {
             if i == 2 {
@@ -4693,6 +4791,53 @@ mod tests {
     }
 
     #[test]
+    fn test_reverse_part() {
+        let mut values = [1,2,3,4,5];
+        reverse_part(values,1,4);
+        assert_eq!(values, [1,4,3,2,5]);
+    }
+
+    #[test]
+    fn test_permutations0() {
+        let values = [];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[]]);
+    }
+
+    #[test]
+    fn test_permutations1() {
+        let values = [1];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[1]]);
+    }
+
+    #[test]
+    fn test_permutations2() {
+        let values = [1,2];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[1,2],~[2,1]]);
+    }
+
+    #[test]
+    fn test_permutations3() {
+        let values = [1,2,3];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]);
+    }
+
+    #[test]
     fn test_each_val() {
         use old_iter::CopyableNonstrictIter;
         let mut i = 0;
diff --git a/src/libfuzzer/ast_match.rs b/src/libfuzzer/ast_match.rs
index 806a7aedd31..2502830250d 100644
--- a/src/libfuzzer/ast_match.rs
+++ b/src/libfuzzer/ast_match.rs
@@ -15,8 +15,8 @@ fn vec_equal<T>(v: ~[T],
                 u: ~[T],
                 element_equality_test: @fn(&&T, &&T) -> bool) ->
    bool {
-    let Lv = vec::len(v);
-    if Lv != vec::len(u) { return false; }
+    let Lv = v.len();
+    if Lv != u.len() { return false; }
     let i = 0u;
     while i < Lv {
         if !element_equality_test(v[i], u[i]) { return false; }
diff --git a/src/libfuzzer/cycles.rs b/src/libfuzzer/cycles.rs
index c18d1f43b56..a6434d64cdc 100644
--- a/src/libfuzzer/cycles.rs
+++ b/src/libfuzzer/cycles.rs
@@ -19,7 +19,7 @@ fn under(r : rand::rng, n : uint) -> uint {
 
 // random choice from a vec
 fn choice<T:copy>(r : rand::rng, v : ~[const T]) -> T {
-    assert!(vec::len(v) != 0u); v[under(r, vec::len(v))]
+    assert!(v.len() != 0u); v[under(r, v.len())]
 }
 
 // k in n chance of being true
diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc
index c75dc2979f1..59a715e7f90 100644
--- a/src/libfuzzer/fuzzer.rc
+++ b/src/libfuzzer/fuzzer.rc
@@ -134,7 +134,7 @@ pub fn stash_expr_if(c: @fn(@ast::expr, test_mode)->bool,
                      e: @ast::expr,
                      tm: test_mode) {
     if c(e, tm) {
-        *es += ~[e];
+        *es = *es + ~[e];
     } else {
         /* now my indices are wrong :( */
     }
@@ -606,7 +606,7 @@ pub fn check_roundtrip_convergence(code: @~str, maxIters: uint) {
         run::run_program(~"diff",
                          ~[~"-w", ~"-u", ~"round-trip-a.rs",
                           ~"round-trip-b.rs"]);
-        fail!(~"Mismatch");
+        fail!("Mismatch");
     }
 }
 
diff --git a/src/libfuzzer/rand_util.rs b/src/libfuzzer/rand_util.rs
index 2422c146e24..c239e8ab933 100644
--- a/src/libfuzzer/rand_util.rs
+++ b/src/libfuzzer/rand_util.rs
@@ -18,7 +18,7 @@ fn under(r : rand::rng, n : uint) -> uint {
 
 // random choice from a vec
 fn choice<T:copy>(r : rand::rng, v : ~[T]) -> T {
-    assert!(vec::len(v) != 0u); v[under(r, vec::len(v))]
+    assert!(v.len() != 0u); v[under(r, v.len())]
 }
 
 // 1 in n chance of being true
@@ -26,7 +26,7 @@ fn unlikely(r : rand::rng, n : uint) -> bool { under(r, n) == 0u }
 
 // shuffle a vec in place
 fn shuffle<T>(r : rand::rng, &v : ~[T]) {
-    let i = vec::len(v);
+    let i = v.len();
     while i >= 2u {
         // Loop invariant: elements with index >= i have been locked in place.
         i -= 1u;
@@ -49,7 +49,7 @@ fn shuffled<T:copy>(r : rand::rng, v : ~[T]) -> ~[T] {
 // * weighted_vec is O(total weight) space
 type weighted<T> = { weight: uint, item: T };
 fn weighted_choice<T:copy>(r : rand::rng, v : ~[weighted<T>]) -> T {
-    assert!(vec::len(v) != 0u);
+    assert!(v.len() != 0u);
     let total = 0u;
     for {weight: weight, item: _} in v {
         total += weight;
diff --git a/src/librustc/README.txt b/src/librustc/README.txt
index 487a7927d27..6d4a8157f11 100644
--- a/src/librustc/README.txt
+++ b/src/librustc/README.txt
@@ -35,19 +35,19 @@ ASTs -- are in a separate crate called "syntax", whose files are in
 ./../libsyntax, where . is the current directory (that is, the parent
 directory of front/, middle/, back/, and so on).
 
-The entry-point for the compiler is main() in driver/rustc.rs, and
+The entry-point for the compiler is main() in rustc.rc, and
 this file sequences the various parts together.
 
 
 The 3 central data structures:
 ------------------------------
 
-#1: ../libsyntax/ast.rs defines the AST. The AST is treated as immutable
+#1: ./../libsyntax/ast.rs defines the AST. The AST is treated as immutable
     after parsing, but it depends on mutable context data structures
     (mainly hash maps) to give it meaning.
 
       - Many -- though not all -- nodes within this data structure are
-        wrapped in the type spanned<T>, meaning that the front-end has
+        wrapped in the type `spanned<T>`, meaning that the front-end has
         marked the input coordinates of that node. The member .node is
         the data itself, the member .span is the input location (file,
         line, column; both low and high).
@@ -78,7 +78,7 @@ Control and information flow within the compiler:
 - main() in rustc.rc assumes control on startup. Options are
   parsed, platform is detected, etc.
 
-- libsyntax/parse/parser.rs parses the input files and produces an AST
+- ./../libsyntax/parse/parser.rs parses the input files and produces an AST
   that represents the input crate.
 
 - Multiple middle-end passes (middle/resolve.rs, middle/typeck.rs)
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 0e2739e40a9..92d3a451559 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -171,7 +171,6 @@ pub mod write {
     use back::link::{output_type_assembly, output_type_bitcode};
     use back::link::{output_type_exe, output_type_llvm_assembly};
     use back::link::{output_type_object};
-    use back::link::output_type;
     use driver::session::Session;
     use driver::session;
     use lib::llvm::llvm;
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index fceff55abf8..37a025cd820 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -137,8 +137,8 @@ pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
            abs1.to_str(), abs2.to_str());
     let split1: &[~str] = abs1.components;
     let split2: &[~str] = abs2.components;
-    let len1 = vec::len(split1);
-    let len2 = vec::len(split2);
+    let len1 = split1.len();
+    let len2 = split2.len();
     assert!(len1 > 0);
     assert!(len2 > 0);
 
@@ -173,7 +173,7 @@ pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
     let install_prefix = env!("CFG_PREFIX");
 
     if install_prefix == ~"" {
-        fail!(~"rustc compiled without CFG_PREFIX environment variable");
+        fail!("rustc compiled without CFG_PREFIX environment variable");
     }
 
     let tlib = filesearch::relative_target_lib_path(target_triple);
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 904a7ccb13f..99ffa8cc94a 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -22,6 +22,7 @@ use middle;
 use util::common::time;
 use util::ppaux;
 
+use core::hashmap::HashMap;
 use core::int;
 use core::io;
 use core::os;
@@ -200,9 +201,6 @@ pub fn compile_rest(sess: Session,
     crate = time(time_passes, ~"core injection", ||
         front::core_inject::maybe_inject_libcore_ref(sess, crate));
 
-    time(time_passes, ~"building lint settings table", ||
-        lint::build_settings_crate(sess, crate));
-
     let ast_map = time(time_passes, ~"ast indexing", ||
             syntax::ast_map::map_crate(sess.diagnostic(), crate));
 
@@ -523,7 +521,7 @@ pub fn host_triple() -> ~str {
     return if ht != ~"" {
             ht
         } else {
-            fail!(~"rustc built without CFG_BUILD_TRIPLE")
+            fail!("rustc built without CFG_BUILD_TRIPLE")
         };
 }
 
@@ -632,7 +630,7 @@ pub fn build_session_options(binary: @~str,
     let extra_debuginfo = debugging_opts & session::extra_debug_info != 0;
     let debuginfo = debugging_opts & session::debug_info != 0 ||
         extra_debuginfo;
-    let static = debugging_opts & session::static != 0;
+    let statik = debugging_opts & session::statik != 0;
     let target =
         match target_opt {
             None => host_triple(),
@@ -660,7 +658,7 @@ pub fn build_session_options(binary: @~str,
 
     let sopts = @session::options {
         crate_type: crate_type,
-        is_static: static,
+        is_static: statik,
         gc: gc,
         optimize: opt_level,
         debuginfo: debuginfo,
@@ -709,7 +707,6 @@ pub fn build_session_(sopts: @session::options,
         &sopts.maybe_sysroot,
         sopts.target_triple,
         /*bad*/copy sopts.addl_lib_search_paths);
-    let lint_settings = lint::mk_lint_settings();
     @Session_ {
         targ_cfg: target_cfg,
         opts: sopts,
@@ -723,7 +720,7 @@ pub fn build_session_(sopts: @session::options,
         filesearch: filesearch,
         building_library: @mut false,
         working_dir: os::getcwd(),
-        lint_settings: lint_settings
+        lints: @mut HashMap::new(),
     }
 }
 
@@ -905,7 +902,6 @@ mod test {
     use driver::driver::{build_configuration, build_session};
     use driver::driver::{build_session_options, optgroups, str_input};
 
-    use core::vec;
     use std::getopts::groups::getopts;
     use std::getopts;
     use syntax::attr;
@@ -917,8 +913,7 @@ mod test {
         let matches =
             &match getopts(~[~"--test"], optgroups()) {
               Ok(copy m) => m,
-              Err(copy f) => fail!(~"test_switch_implies_cfg_test: " +
-                             getopts::fail_str(f))
+              Err(copy f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f))
             };
         let sessopts = build_session_options(
             @~"rustc", matches, diagnostic::emit);
@@ -935,8 +930,7 @@ mod test {
             &match getopts(~[~"--test", ~"--cfg=test"], optgroups()) {
               Ok(copy m) => m,
               Err(copy f) => {
-                fail!(~"test_switch_implies_cfg_test_unless_cfg_test: " +
-                    getopts::fail_str(f));
+                fail!("test_switch_implies_cfg_test_unless_cfg_test: %s", getopts::fail_str(f));
               }
             };
         let sessopts = build_session_options(
@@ -944,6 +938,6 @@ mod test {
         let sess = build_session(sessopts, diagnostic::emit);
         let cfg = build_configuration(sess, @~"whatever", &str_input(~""));
         let test_items = attr::find_meta_items_by_name(cfg, ~"test");
-        assert!((vec::len(test_items) == 1u));
+        assert!(test_items.len() == 1u);
     }
 }
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 92cdcff65d5..6fba5ec8d3a 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -26,6 +26,8 @@ use syntax::{ast, codemap};
 use syntax::abi;
 use syntax;
 
+use core::hashmap::HashMap;
+
 #[deriving(Eq)]
 pub enum os { os_win32, os_macos, os_linux, os_android, os_freebsd, }
 
@@ -62,7 +64,7 @@ pub static gc: uint = 1 << 18;
 pub static jit: uint = 1 << 19;
 pub static debug_info: uint = 1 << 20;
 pub static extra_debug_info: uint = 1 << 21;
-pub static static: uint = 1 << 22;
+pub static statik: uint = 1 << 22;
 pub static print_link_args: uint = 1 << 23;
 
 pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
@@ -98,7 +100,7 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
       extra_debug_info),
      (~"debug-info", ~"Produce debug info (experimental)", debug_info),
      (~"static", ~"Use or produce static libraries or binaries " +
-      "(experimental)", static)
+      "(experimental)", statik)
     ]
 }
 
@@ -170,7 +172,7 @@ pub struct Session_ {
     filesearch: @filesearch::FileSearch,
     building_library: @mut bool,
     working_dir: Path,
-    lint_settings: lint::LintSettings
+    lints: @mut HashMap<ast::node_id, ~[(lint::lint, codemap::span, ~str)]>,
 }
 
 pub type Session = @Session_;
@@ -221,24 +223,12 @@ pub impl Session_ {
     fn unimpl(@self, msg: &str) -> ! {
         self.span_diagnostic.handler().unimpl(msg)
     }
-    fn span_lint_level(@self, level: lint::level, sp: span, msg: &str) {
-        match level {
-          lint::allow => { },
-          lint::warn => self.span_warn(sp, msg),
-          lint::deny | lint::forbid => {
-            self.span_err(sp, msg);
-          }
+    fn add_lint(@self, lint: lint::lint, id: ast::node_id, sp: span, msg: ~str) {
+        match self.lints.find_mut(&id) {
+            Some(arr) => { arr.push((lint, sp, msg)); return; }
+            None => {}
         }
-    }
-    fn span_lint(@self, lint_mode: lint::lint,
-                 expr_id: ast::node_id,
-                 item_id: ast::node_id,
-                 span: span,
-                 msg: &str) {
-        let level = lint::get_lint_settings_level(
-            self.lint_settings, lint_mode, expr_id, item_id);
-        let msg = fmt!("%s [-W %s]", msg, lint::get_lint_name(lint_mode));
-        self.span_lint_level(level, span, msg);
+        self.lints.insert(id, ~[(lint, sp, msg)]);
     }
     fn next_node_id(@self) -> ast::node_id {
         return syntax::parse::next_node_id(self.parse_sess);
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index f556baee918..be03ed99ad7 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -206,7 +206,7 @@ fn is_bench_fn(i: @ast::item) -> bool {
     fn has_test_signature(i: @ast::item) -> bool {
         match i.node {
             ast::item_fn(ref decl, _, _, ref generics, _) => {
-                let input_cnt = vec::len(decl.inputs);
+                let input_cnt = decl.inputs.len();
                 let no_output = match decl.output.node {
                     ast::ty_nil => true,
                     _ => false
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 4c61c42a339..d06bf1480c9 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1566,6 +1566,7 @@ pub mod llvm {
         /* Atomic Operations */
         pub unsafe fn LLVMBuildAtomicLoad(B: BuilderRef,
                                           PointerVal: ValueRef,
+                                          Name: *c_char,
                                           Order: AtomicOrdering)
                                        -> ValueRef;
 
@@ -2044,7 +2045,7 @@ pub fn float_width(llt: TypeRef) -> uint {
               2 => 64u,
               3 => 80u,
               4 | 5 => 128u,
-              _ => fail!(~"llvm_float_width called on a non-float type")
+              _ => fail!("llvm_float_width called on a non-float type")
             };
     }
 }
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index d2b71447f47..9426cd6041d 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -100,7 +100,7 @@ pub static tag_mod_impl_trait: uint = 0x47u;
   different tags.
  */
 pub static tag_item_impl_method: uint = 0x48u;
-pub static tag_item_trait_method_self_ty: uint = 0x4b;
+pub static tag_item_trait_method_explicit_self: uint = 0x4b;
 pub static tag_item_trait_method_self_ty_region: uint = 0x4c;
 
 
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index d8117a87480..5a0820202a9 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -22,7 +22,7 @@ use syntax::ast_map;
 use syntax::diagnostic::expect;
 
 pub struct ProvidedTraitMethodInfo {
-    ty: ty::method,
+    ty: ty::Method,
     def_id: ast::def_id
 }
 
@@ -129,17 +129,18 @@ pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id,
 }
 
 pub fn get_method(tcx: ty::ctxt,
-                  def: ast::def_id) -> ty::method
+                  def: ast::def_id) -> ty::Method
 {
     let cdata = cstore::get_crate_data(tcx.cstore, def.crate);
     decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx)
 }
 
-pub fn get_method_name_and_self_ty(cstore: @mut cstore::CStore,
-                                   def: ast::def_id) -> (ast::ident, ast::self_ty_)
+pub fn get_method_name_and_explicit_self(cstore: @mut cstore::CStore,
+                                         def: ast::def_id)
+                                     -> (ast::ident, ast::explicit_self_)
 {
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_method_name_and_self_ty(cstore.intr, cdata, def.node)
+    decoder::get_method_name_and_explicit_self(cstore.intr, cdata, def.node)
 }
 
 pub fn get_trait_method_def_ids(cstore: @mut cstore::CStore,
@@ -233,14 +234,13 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
     }
 }
 
-// Given a def_id for an impl or class, return the traits it implements,
-// or the empty vector if it's not for an impl or for a class that implements
-// traits
-pub fn get_impl_traits(tcx: ty::ctxt,
-                       def: ast::def_id) -> ~[@ty::TraitRef] {
+// Given a def_id for an impl, return the trait it implements,
+// if there is one.
+pub fn get_impl_trait(tcx: ty::ctxt,
+                      def: ast::def_id) -> Option<@ty::TraitRef> {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_impl_traits(cdata, def.node, tcx)
+    decoder::get_impl_trait(cdata, def.node, tcx)
 }
 
 pub fn get_impl_method(cstore: @mut cstore::CStore,
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index b8218bc4d46..43073728e83 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -87,7 +87,7 @@ fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc {
 fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc {
     let items = reader::get_doc(reader::Doc(data), tag_items);
     match maybe_find_item(item_id, items) {
-       None => fail!(fmt!("lookup_item: id not found: %d", item_id)),
+       None => fail!("lookup_item: id not found: %d", item_id),
        Some(d) => d
     }
 }
@@ -139,7 +139,7 @@ fn item_family(item: ebml::Doc) -> Family {
       'g' => PublicField,
       'j' => PrivateField,
       'N' => InheritedField,
-       c => fail!(fmt!("unexpected family char: %c", c))
+       c => fail!("unexpected family char: %c", c)
     }
 }
 
@@ -151,7 +151,7 @@ fn item_visibility(item: ebml::Doc) -> ast::visibility {
                 'y' => ast::public,
                 'n' => ast::private,
                 'i' => ast::inherited,
-                _ => fail!(~"unknown visibility character")
+                _ => fail!("unknown visibility character")
             }
         }
     }
@@ -415,19 +415,20 @@ pub fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
     item_ty_param_count(lookup_item(id, data))
 }
 
-pub fn get_impl_traits(cdata: cmd,
+pub fn get_impl_trait(cdata: cmd,
                        id: ast::node_id,
-                       tcx: ty::ctxt) -> ~[@ty::TraitRef]
+                       tcx: ty::ctxt) -> Option<@ty::TraitRef>
 {
     let item_doc = lookup_item(id, cdata.data);
-    let mut results = ~[];
+    let mut result = None;
     for reader::tagged_docs(item_doc, tag_item_trait_ref) |tp| {
         let trait_ref =
             @parse_trait_ref_data(tp.data, cdata.cnum, tp.start, tcx,
                                   |_, did| translate_def_id(cdata, did));
-        results.push(trait_ref);
+        result = Some(trait_ref);
+        break;
     };
-    results
+    result
 }
 
 pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
@@ -458,8 +459,8 @@ pub enum def_like {
 fn def_like_to_def(def_like: def_like) -> ast::def {
     match def_like {
         dl_def(def) => return def,
-        dl_impl(*) => fail!(~"found impl in def_like_to_def"),
-        dl_field => fail!(~"found field in def_like_to_def")
+        dl_impl(*) => fail!("found impl in def_like_to_def"),
+        dl_field => fail!("found field in def_like_to_def")
     }
 }
 
@@ -653,7 +654,7 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
                                 item, tcx, cdata);
         let name = item_name(intr, item);
         let arg_tys = match ty::get(ctor_ty).sty {
-          ty::ty_bare_fn(ref f) => f.sig.inputs.map(|a| a.ty),
+          ty::ty_bare_fn(ref f) => copy f.sig.inputs,
           _ => ~[], // Nullary enum variant.
         };
         match variant_disr_val(item) {
@@ -670,23 +671,23 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
     return infos;
 }
 
-fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ {
+fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
     fn get_mutability(ch: u8) -> ast::mutability {
         match ch as char {
             'i' => { ast::m_imm }
             'm' => { ast::m_mutbl }
             'c' => { ast::m_const }
             _ => {
-                fail!(fmt!("unknown mutability character: `%c`", ch as char))
+                fail!("unknown mutability character: `%c`", ch as char)
             }
         }
     }
 
-    let self_type_doc = reader::get_doc(item, tag_item_trait_method_self_ty);
-    let string = reader::doc_as_str(self_type_doc);
+    let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
+    let string = reader::doc_as_str(explicit_self_doc);
 
-    let self_ty_kind = string[0];
-    match self_ty_kind as char {
+    let explicit_self_kind = string[0];
+    match explicit_self_kind as char {
         's' => { return ast::sty_static; }
         'v' => { return ast::sty_value; }
         '@' => { return ast::sty_box(get_mutability(string[1])); }
@@ -696,7 +697,7 @@ fn get_self_ty(item: ebml::Doc) -> ast::self_ty_ {
             return ast::sty_region(None, get_mutability(string[1]));
         }
         _ => {
-            fail!(fmt!("unknown self type code: `%c`", self_ty_kind as char));
+            fail!("unknown self type code: `%c`", explicit_self_kind as char);
         }
     }
 }
@@ -707,12 +708,12 @@ fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
     for reader::tagged_docs(item, tag_item_impl_method) |doc| {
         let m_did = reader::with_doc_data(doc, |d| parse_def_id(d));
         let mth_item = lookup_item(m_did.node, cdata.data);
-        let self_ty = get_self_ty(mth_item);
+        let explicit_self = get_explicit_self(mth_item);
         rslt.push(@resolve::MethodInfo {
                     did: translate_def_id(cdata, m_did),
                     n_tps: item_ty_param_count(mth_item) - base_tps,
                     ident: item_name(intr, mth_item),
-                    self_type: self_ty});
+                    explicit_self: explicit_self});
     }
     rslt
 }
@@ -748,19 +749,19 @@ pub fn get_impls_for_mod(intr: @ident_interner,
     @result
 }
 
-pub fn get_method_name_and_self_ty(
+pub fn get_method_name_and_explicit_self(
     intr: @ident_interner,
     cdata: cmd,
-    id: ast::node_id) -> (ast::ident, ast::self_ty_)
+    id: ast::node_id) -> (ast::ident, ast::explicit_self_)
 {
     let method_doc = lookup_item(id, cdata.data);
     let name = item_name(intr, method_doc);
-    let self_ty = get_self_ty(method_doc);
-    (name, self_ty)
+    let explicit_self = get_explicit_self(method_doc);
+    (name, explicit_self)
 }
 
 pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
-                  tcx: ty::ctxt) -> ty::method
+                  tcx: ty::ctxt) -> ty::Method
 {
     let method_doc = lookup_item(id, cdata.data);
     let def_id = item_def_id(method_doc, cdata);
@@ -770,19 +771,20 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
     let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata);
     let fty = doc_method_fty(method_doc, tcx, cdata);
     let vis = item_visibility(method_doc);
-    let self_ty = get_self_ty(method_doc);
-    ty::method {
-        ident: name,
-        generics: ty::Generics {
+    let explicit_self = get_explicit_self(method_doc);
+
+    ty::Method::new(
+        name,
+        ty::Generics {
             type_param_defs: type_param_defs,
             region_param: None
         },
-        transformed_self_ty: transformed_self_ty,
-        fty: fty,
-        self_ty: self_ty,
-        vis: vis,
-        def_id: def_id
-    }
+        transformed_self_ty,
+        fty,
+        explicit_self,
+        vis,
+        def_id
+    )
 }
 
 pub fn get_trait_method_def_ids(cdata: cmd,
@@ -823,19 +825,20 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
         };
 
         let transformed_self_ty = doc_transformed_self_ty(mth, tcx, cdata);
-        let self_ty = get_self_ty(mth);
-        let ty_method = ty::method {
-            ident: name,
-            generics: ty::Generics {
+        let explicit_self = get_explicit_self(mth);
+
+        let ty_method = ty::Method::new(
+            name,
+            ty::Generics {
                 type_param_defs: type_param_defs,
                 region_param: None
             },
-            transformed_self_ty: transformed_self_ty,
-            fty: fty,
-            self_ty: self_ty,
-            vis: ast::public,
-            def_id: did
-        };
+            transformed_self_ty,
+            fty,
+            explicit_self,
+            ast::public,
+            did
+        );
         let provided_trait_method_info = ProvidedTraitMethodInfo {
             ty: ty_method,
             def_id: did
@@ -998,7 +1001,7 @@ fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str {
     if id.crate != ast::local_crate { return ~"external"; }
     let it = match maybe_find_item(id.node, items) {
         Some(it) => it,
-        None => fail!(fmt!("describe_def: item not found %?", id))
+        None => fail!("describe_def: item not found %?", id)
     };
     return item_family_to_str(item_family(it));
 }
@@ -1061,7 +1064,7 @@ fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] {
             let meta_items = get_meta_items(attr_doc);
             // Currently it's only possible to have a single meta item on
             // an attribute
-            assert!((vec::len(meta_items) == 1u));
+            assert!(meta_items.len() == 1u);
             let meta_item = meta_items[0];
             attrs.push(
                 codemap::spanned {
@@ -1189,7 +1192,7 @@ pub fn translate_def_id(cdata: cmd, did: ast::def_id) -> ast::def_id {
 
     match cdata.cnum_map.find(&did.crate) {
       option::Some(&n) => ast::def_id { crate: n, node: did.node },
-      option::None => fail!(~"didn't find a crate in the cnum_map")
+      option::None => fail!("didn't find a crate in the cnum_map")
     }
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 02f0cc6e42d..d27bfd081bc 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -366,7 +366,7 @@ fn encode_path(ecx: @EncodeContext,
 fn encode_reexported_static_method(ecx: @EncodeContext,
                                    ebml_w: &mut writer::Encoder,
                                    exp: &middle::resolve::Export2,
-                                   m: @ty::method) {
+                                   m: @ty::Method) {
     debug!("(encode static trait method) reexport '%s::%s'",
             *exp.name, *ecx.tcx.sess.str_of(m.ident));
     ebml_w.start_tag(tag_items_data_item_reexport);
@@ -389,7 +389,7 @@ fn encode_reexported_static_methods(ecx: @EncodeContext,
                 Some(&ast_map::node_item(_, path)) => {
                     if mod_path != *path {
                         for methods.each |&m| {
-                            if m.self_ty  == ast::sty_static {
+                            if m.explicit_self == ast::sty_static {
                                 encode_reexported_static_method(ecx,
                                                                 ebml_w,
                                                                 exp, m);
@@ -486,11 +486,11 @@ fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: visibility) {
     ebml_w.end_tag();
 }
 
-fn encode_self_type(ebml_w: &mut writer::Encoder, self_type: ast::self_ty_) {
-    ebml_w.start_tag(tag_item_trait_method_self_ty);
+fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explicit_self_) {
+    ebml_w.start_tag(tag_item_trait_method_explicit_self);
 
     // Encode the base self type.
-    match self_type {
+    match explicit_self {
         sty_static => {
             ebml_w.writer.write(&[ 's' as u8 ]);
         }
@@ -625,7 +625,7 @@ fn encode_info_for_struct_ctor(ecx: @EncodeContext,
 
 fn encode_method_ty_fields(ecx: @EncodeContext,
                            ebml_w: &mut writer::Encoder,
-                           method_ty: &ty::method) {
+                           method_ty: &ty::Method) {
     encode_def_id(ebml_w, method_ty.def_id);
     encode_name(ecx, ebml_w, method_ty.ident);
     encode_ty_type_param_defs(ebml_w, ecx,
@@ -634,7 +634,7 @@ fn encode_method_ty_fields(ecx: @EncodeContext,
     encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
     encode_method_fty(ecx, ebml_w, &method_ty.fty);
     encode_visibility(ebml_w, method_ty.vis);
-    encode_self_type(ebml_w, method_ty.self_ty);
+    encode_explicit_self(ebml_w, method_ty.explicit_self);
 }
 
 fn encode_info_for_method(ecx: @EncodeContext,
@@ -652,10 +652,10 @@ fn encode_info_for_method(ecx: @EncodeContext,
     ebml_w.start_tag(tag_items_data_item);
 
     let method_def_id = local_def(m.id);
-    let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id);
+    let method_ty = ty::method(ecx.tcx, method_def_id);
     encode_method_ty_fields(ecx, ebml_w, method_ty);
 
-    match m.self_ty.node {
+    match m.explicit_self.node {
         ast::sty_static => {
             encode_family(ebml_w, purity_static_method_family(m.purity));
         }
@@ -696,7 +696,7 @@ fn purity_static_method_family(p: purity) -> char {
       unsafe_fn => 'U',
       pure_fn => 'P',
       impure_fn => 'F',
-      _ => fail!(~"extern fn can't be static")
+      _ => fail!("extern fn can't be static")
     }
 }
 
@@ -948,7 +948,7 @@ fn encode_info_for_item(ecx: @EncodeContext,
         for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
             assert!(method_def_id.crate == ast::local_crate);
 
-            let method_ty: @ty::method = ty::method(tcx, method_def_id);
+            let method_ty = ty::method(tcx, method_def_id);
 
             index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
 
@@ -962,7 +962,7 @@ fn encode_info_for_item(ecx: @EncodeContext,
             trait_path.push(ast_map::path_name(item.ident));
             encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
 
-            match method_ty.self_ty {
+            match method_ty.explicit_self {
                 sty_static => {
                     encode_family(ebml_w,
                                   purity_static_method_family(
@@ -991,7 +991,7 @@ fn encode_info_for_item(ecx: @EncodeContext,
                     // This is obviously a bogus assert but I don't think this
                     // ever worked before anyhow...near as I can tell, before
                     // we would emit two items.
-                    if method_ty.self_ty == sty_static {
+                    if method_ty.explicit_self == sty_static {
                         tcx.sess.span_unimpl(
                             item.span,
                             fmt!("Method %s is both provided and static",
@@ -1009,7 +1009,7 @@ fn encode_info_for_item(ecx: @EncodeContext,
             ebml_w.end_tag();
         }
       }
-      item_mac(*) => fail!(~"item macros unimplemented")
+      item_mac(*) => fail!("item macros unimplemented")
     }
 }
 
@@ -1068,7 +1068,7 @@ fn encode_info_for_items(ecx: @EncodeContext,
                         let mut ebml_w = copy ebml_w;
                         encode_info_for_item(ecx, &mut ebml_w, i, index, *pt);
                     }
-                    _ => fail!(~"bad item")
+                    _ => fail!("bad item")
                 }
             }
         },
@@ -1087,7 +1087,7 @@ fn encode_info_for_items(ecx: @EncodeContext,
                                                      abi);
                     }
                     // case for separate item and foreign-item tables
-                    _ => fail!(~"bad foreign item")
+                    _ => fail!("bad foreign item")
                 }
             }
         },
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 9ef1f3e7b41..82d46c03101 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -139,7 +139,7 @@ fn make_target_lib_path(sysroot: &Path,
 fn get_or_default_sysroot() -> Path {
     match os::self_exe_path() {
       option::Some(ref p) => (*p).pop(),
-      option::None => fail!(~"can't determine value for sysroot")
+      option::None => fail!("can't determine value for sysroot")
     }
 }
 
@@ -207,7 +207,7 @@ fn get_rustpkg_lib_path_nearest() -> Result<Path, ~str> {
 pub fn libdir() -> ~str {
    let libdir = env!("CFG_LIBDIR");
    if str::is_empty(libdir) {
-      fail!(~"rustc compiled without CFG_LIBDIR environment variable");
+      fail!("rustc compiled without CFG_LIBDIR environment variable");
    }
    libdir
 }
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index d1510f31a9e..cfb2bd4b837 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -142,7 +142,7 @@ pub fn crate_name_from_metas(metas: &[@ast::meta_item]) -> @~str {
                 _ => fail!()
             }
         }
-        None => fail!(~"expected to find the crate name")
+        None => fail!("expected to find the crate name")
     }
 }
 
@@ -171,7 +171,7 @@ pub fn metadata_matches(extern_metas: &[@ast::meta_item],
                         local_metas: &[@ast::meta_item]) -> bool {
 
     debug!("matching %u metadata requirements against %u items",
-           vec::len(local_metas), vec::len(extern_metas));
+           local_metas.len(), extern_metas.len());
 
     for local_metas.each |needed| {
         if !attr::contains(extern_metas, *needed) {
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index c220ae45b1a..55a0755f5e3 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -126,12 +126,6 @@ pub fn parse_trait_ref_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ct
     parse_trait_ref(st, conv)
 }
 
-pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
-                      conv: conv_did) -> ty::arg {
-    let st = parse_state_from_data(data, crate_num, pos, tcx);
-    parse_arg(st, conv)
-}
-
 fn parse_path(st: @mut PState) -> @ast::Path {
     let mut idents: ~[ast::ident] = ~[];
     fn is_last(c: char) -> bool { return c == '(' || c == ':'; }
@@ -219,7 +213,7 @@ fn parse_bound_region(st: @mut PState) -> ty::bound_region {
         assert!(next(st) == '|');
         ty::br_cap_avoid(id, @parse_bound_region(st))
       },
-      _ => fail!(~"parse_bound_region: bad input")
+      _ => fail!("parse_bound_region: bad input")
     }
 }
 
@@ -248,7 +242,7 @@ fn parse_region(st: @mut PState) -> ty::Region {
       'e' => {
         ty::re_static
       }
-      _ => fail!(~"parse_region: bad input")
+      _ => fail!("parse_region: bad input")
     }
 }
 
@@ -256,7 +250,7 @@ fn parse_opt<T>(st: @mut PState, f: &fn() -> T) -> Option<T> {
     match next(st) {
       'n' => None,
       's' => Some(f()),
-      _ => fail!(~"parse_opt: bad input")
+      _ => fail!("parse_opt: bad input")
     }
 }
 
@@ -295,7 +289,7 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t {
           'D' => return ty::mk_mach_int(ast::ty_i64),
           'f' => return ty::mk_mach_float(ast::ty_f32),
           'F' => return ty::mk_mach_float(ast::ty_f64),
-          _ => fail!(~"parse_ty: bad numeric type")
+          _ => fail!("parse_ty: bad numeric type")
         }
       }
       'c' => return ty::mk_char(),
@@ -446,7 +440,7 @@ fn parse_purity(c: char) -> purity {
       'p' => pure_fn,
       'i' => impure_fn,
       'c' => extern_fn,
-      _ => fail!(~"parse_purity: bad purity")
+      _ => fail!("parse_purity: bad purity")
     }
 }
 
@@ -467,13 +461,7 @@ fn parse_onceness(c: char) -> ast::Onceness {
     match c {
         'o' => ast::Once,
         'm' => ast::Many,
-        _ => fail!(~"parse_onceness: bad onceness")
-    }
-}
-
-fn parse_arg(st: @mut PState, conv: conv_did) -> ty::arg {
-    ty::arg {
-        ty: parse_ty(st, conv)
+        _ => fail!("parse_onceness: bad onceness")
     }
 }
 
@@ -482,12 +470,14 @@ fn parse_closure_ty(st: @mut PState, conv: conv_did) -> ty::ClosureTy {
     let purity = parse_purity(next(st));
     let onceness = parse_onceness(next(st));
     let region = parse_region(st);
+    let bounds = parse_bounds(st, conv);
     let sig = parse_sig(st, conv);
     ty::ClosureTy {
         purity: purity,
         sigil: sigil,
         onceness: onceness,
         region: region,
+        bounds: bounds.builtin_bounds,
         sig: sig
     }
 }
@@ -505,9 +495,9 @@ fn parse_bare_fn_ty(st: @mut PState, conv: conv_did) -> ty::BareFnTy {
 
 fn parse_sig(st: @mut PState, conv: conv_did) -> ty::FnSig {
     assert!((next(st) == '['));
-    let mut inputs: ~[ty::arg] = ~[];
+    let mut inputs = ~[];
     while peek(st) != ']' {
-        inputs.push(ty::arg { ty: parse_ty(st, conv) });
+        inputs.push(parse_ty(st, conv));
     }
     st.pos += 1u; // eat the ']'
     let ret_ty = parse_ty(st, conv);
@@ -519,7 +509,7 @@ fn parse_sig(st: @mut PState, conv: conv_did) -> ty::FnSig {
 // Rust metadata parsing
 pub fn parse_def_id(buf: &[u8]) -> ast::def_id {
     let mut colon_idx = 0u;
-    let len = vec::len(buf);
+    let len = buf.len();
     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
     if colon_idx == len {
         error!("didn't find ':' when parsing def id");
@@ -531,13 +521,13 @@ pub fn parse_def_id(buf: &[u8]) -> ast::def_id {
 
     let crate_num = match uint::parse_bytes(crate_part, 10u) {
        Some(cn) => cn as int,
-       None => fail!(fmt!("internal error: parse_def_id: crate number \
-                               expected, but found %?", crate_part))
+       None => fail!("internal error: parse_def_id: crate number expected, but found %?",
+                     crate_part)
     };
     let def_num = match uint::parse_bytes(def_part, 10u) {
        Some(dn) => dn as int,
-       None => fail!(fmt!("internal error: parse_def_id: id expected, but \
-                               found %?", def_part))
+       None => fail!("internal error: parse_def_id: id expected, but found %?",
+                     def_part)
     };
     ast::def_id { crate: crate_num, node: def_num }
 }
@@ -552,10 +542,10 @@ pub fn parse_type_param_def_data(data: @~[u8], start: uint,
 
 fn parse_type_param_def(st: @mut PState, conv: conv_did) -> ty::TypeParameterDef {
     ty::TypeParameterDef {def_id: parse_def(st, NominalType, conv),
-                          bounds: parse_bounds(st, conv)}
+                          bounds: @parse_bounds(st, conv)}
 }
 
-fn parse_bounds(st: @mut PState, conv: conv_did) -> @ty::ParamBounds {
+fn parse_bounds(st: @mut PState, conv: conv_did) -> ty::ParamBounds {
     let mut param_bounds = ty::ParamBounds {
         builtin_bounds: ty::EmptyBuiltinBounds(),
         trait_bounds: ~[]
@@ -578,10 +568,10 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> @ty::ParamBounds {
                 param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
             }
             '.' => {
-                return @param_bounds;
+                return param_bounds;
             }
             _ => {
-                fail!(~"parse_bounds: bad bounds")
+                fail!("parse_bounds: bad bounds")
             }
         }
     }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 86088646bca..5f799f49946 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -332,7 +332,7 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) {
           debug!("~~~~ %s", ~"]");
           w.write_char(']');
       }
-      ty::ty_err => fail!(~"Shouldn't encode error type")
+      ty::ty_err => fail!("Shouldn't encode error type")
     }
 }
 
@@ -344,10 +344,6 @@ fn enc_sigil(w: @io::Writer, sigil: Sigil) {
     }
 }
 
-pub fn enc_arg(w: @io::Writer, cx: @ctxt, arg: ty::arg) {
-    enc_ty(w, cx, arg.ty);
-}
-
 fn enc_purity(w: @io::Writer, p: purity) {
     match p {
       pure_fn => w.write_char('p'),
@@ -384,19 +380,22 @@ fn enc_closure_ty(w: @io::Writer, cx: @ctxt, ft: &ty::ClosureTy) {
     enc_purity(w, ft.purity);
     enc_onceness(w, ft.onceness);
     enc_region(w, cx, ft.region);
+    let bounds = ty::ParamBounds {builtin_bounds: ft.bounds,
+                                  trait_bounds: ~[]};
+    enc_bounds(w, cx, &bounds);
     enc_fn_sig(w, cx, &ft.sig);
 }
 
 fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
     w.write_char('[');
-    for fsig.inputs.each |arg| {
-        enc_arg(w, cx, *arg);
+    for fsig.inputs.each |ty| {
+        enc_ty(w, cx, *ty);
     }
     w.write_char(']');
     enc_ty(w, cx, fsig.output);
 }
 
-fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @ty::ParamBounds) {
+fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) {
     for bs.builtin_bounds.each |bound| {
         match bound {
             ty::BoundOwned => w.write_char('S'),
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 0afabd53ba9..209a14942e9 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -293,7 +293,7 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
                                              span: _}, _) => true,
               ast::stmt_decl(@codemap::spanned { node: ast::decl_item(_),
                                              span: _}, _) => false,
-              ast::stmt_mac(*) => fail!(~"unexpanded macro in astencode")
+              ast::stmt_mac(*) => fail!("unexpanded macro in astencode")
             }
         };
         let blk_sans_items = ast::blk_ {
@@ -526,8 +526,8 @@ fn encode_method_map_entry(ecx: @e::EncodeContext,
                            ebml_w: &mut writer::Encoder,
                            mme: method_map_entry) {
     do ebml_w.emit_struct("method_map_entry", 3) |ebml_w| {
-        do ebml_w.emit_struct_field("self_arg", 0u) |ebml_w| {
-            ebml_w.emit_arg(ecx, mme.self_arg);
+        do ebml_w.emit_struct_field("self_ty", 0u) |ebml_w| {
+            ebml_w.emit_ty(ecx, mme.self_ty);
         }
         do ebml_w.emit_struct_field("explicit_self", 2u) |ebml_w| {
             mme.explicit_self.encode(ebml_w);
@@ -546,14 +546,14 @@ impl read_method_map_entry_helper for reader::Decoder {
                              -> method_map_entry {
         do self.read_struct("method_map_entry", 3) |this| {
             method_map_entry {
-                self_arg: this.read_struct_field("self_arg", 0, |this| {
-                    this.read_arg(xcx)
+                self_ty: this.read_struct_field("self_ty", 0u, |this| {
+                    this.read_ty(xcx)
                 }),
                 explicit_self: this.read_struct_field("explicit_self",
                                                       2,
                                                       |this| {
-                    let self_type: ast::self_ty_ = Decodable::decode(this);
-                    self_type
+                    let explicit_self: ast::explicit_self_ = Decodable::decode(this);
+                    explicit_self
                 }),
                 origin: this.read_struct_field("origin", 1, |this| {
                     let method_origin: method_origin =
@@ -686,7 +686,7 @@ impl vtable_decoder_helpers for reader::Decoder {
                     )
                   }
                   // hard to avoid - user input
-                  _ => fail!(~"bad enum variant")
+                  _ => fail!("bad enum variant")
                 }
             }
         }
@@ -712,7 +712,6 @@ impl get_ty_str_ctxt for e::EncodeContext {
 }
 
 trait ebml_writer_helpers {
-    fn emit_arg(&mut self, ecx: @e::EncodeContext, arg: ty::arg);
     fn emit_ty(&mut self, ecx: @e::EncodeContext, ty: ty::t);
     fn emit_vstore(&mut self, ecx: @e::EncodeContext, vstore: ty::vstore);
     fn emit_tys(&mut self, ecx: @e::EncodeContext, tys: &[ty::t]);
@@ -737,12 +736,6 @@ impl ebml_writer_helpers for writer::Encoder {
         }
     }
 
-    fn emit_arg(&mut self, ecx: @e::EncodeContext, arg: ty::arg) {
-        do self.emit_opaque |this| {
-            tyencode::enc_arg(this.writer, ecx.ty_str_ctxt(), arg);
-        }
-    }
-
     fn emit_tys(&mut self, ecx: @e::EncodeContext, tys: &[ty::t]) {
         do self.emit_from_vec(tys) |this, ty| {
             this.emit_ty(ecx, *ty)
@@ -943,7 +936,6 @@ impl doc_decoder_helpers for ebml::Doc {
 }
 
 trait ebml_decoder_decoder_helpers {
-    fn read_arg(&mut self, xcx: @ExtendedDecodeContext) -> ty::arg;
     fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t;
     fn read_tys(&mut self, xcx: @ExtendedDecodeContext) -> ~[ty::t];
     fn read_type_param_def(&mut self, xcx: @ExtendedDecodeContext)
@@ -958,17 +950,6 @@ trait ebml_decoder_decoder_helpers {
 }
 
 impl ebml_decoder_decoder_helpers for reader::Decoder {
-    fn read_arg(&mut self, xcx: @ExtendedDecodeContext) -> ty::arg {
-        do self.read_opaque |this, doc| {
-            tydecode::parse_arg_data(
-                doc.data,
-                xcx.dcx.cdata.cnum,
-                doc.start,
-                xcx.dcx.tcx,
-                |s, a| this.convert_def_id(xcx, s, a))
-        }
-    }
-
     fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t {
         // Note: regions types embed local node ids.  In principle, we
         // should translate these node ids into the new decode
@@ -1127,7 +1108,7 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
                 dcx.tcx.adjustments.insert(id, adj);
             } else if tag == (c::tag_table_capture_map as uint) {
                 let cvars =
-                    at_vec::from_owned(
+                    at_vec::to_managed_consume(
                         val_dsr.read_to_vec(
                             |val_dsr| val_dsr.read_capture_var(xcx)));
                 dcx.maps.capture_map.insert(id, cvars);
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 2f116cb1b28..2f24a8ceb24 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -359,7 +359,7 @@ pub impl<'self> CheckLoanCtxt<'self> {
                 self, expr, cmt);
         }
 
-        fn mark_variable_as_used_mut(self: &CheckLoanCtxt,
+        fn mark_variable_as_used_mut(this: &CheckLoanCtxt,
                                      cmt: mc::cmt) {
             //! If the mutability of the `cmt` being written is inherited
             //! from a local variable, liveness will
@@ -370,12 +370,12 @@ pub impl<'self> CheckLoanCtxt<'self> {
             let mut cmt = cmt;
             loop {
                 debug!("mark_writes_through_upvars_as_used_mut(cmt=%s)",
-                       cmt.repr(self.tcx()));
+                       cmt.repr(this.tcx()));
                 match cmt.cat {
                     mc::cat_local(id) |
                     mc::cat_arg(id) |
                     mc::cat_self(id) => {
-                        self.tcx().used_mut_nodes.insert(id);
+                        this.tcx().used_mut_nodes.insert(id);
                         return;
                     }
 
@@ -411,14 +411,14 @@ pub impl<'self> CheckLoanCtxt<'self> {
             }
         }
 
-        fn check_for_aliasable_mutable_writes(self: &CheckLoanCtxt,
+        fn check_for_aliasable_mutable_writes(this: &CheckLoanCtxt,
                                               expr: @ast::expr,
                                               cmt: mc::cmt) -> bool {
             //! Safety checks related to writes to aliasable, mutable locations
 
             let guarantor = cmt.guarantor();
             debug!("check_for_aliasable_mutable_writes(cmt=%s, guarantor=%s)",
-                   cmt.repr(self.tcx()), guarantor.repr(self.tcx()));
+                   cmt.repr(this.tcx()), guarantor.repr(this.tcx()));
             match guarantor.cat {
                 mc::cat_deref(b, _, mc::region_ptr(m_mutbl, _)) => {
                     // Statically prohibit writes to `&mut` when aliasable
@@ -426,7 +426,7 @@ pub impl<'self> CheckLoanCtxt<'self> {
                     match b.freely_aliasable() {
                         None => {}
                         Some(cause) => {
-                            self.bccx.report_aliasability_violation(
+                            this.bccx.report_aliasability_violation(
                                 expr.span,
                                 MutabilityViolation,
                                 cause);
@@ -442,7 +442,7 @@ pub impl<'self> CheckLoanCtxt<'self> {
                         derefs: deref_count
                     };
                     debug!("Inserting write guard at %?", key);
-                    self.bccx.write_guard_map.insert(key);
+                    this.bccx.write_guard_map.insert(key);
                 }
 
                 _ => {}
@@ -452,7 +452,7 @@ pub impl<'self> CheckLoanCtxt<'self> {
         }
 
         fn check_for_assignment_to_restricted_or_frozen_location(
-            self: &CheckLoanCtxt,
+            this: &CheckLoanCtxt,
             expr: @ast::expr,
             cmt: mc::cmt) -> bool
         {
@@ -494,11 +494,11 @@ pub impl<'self> CheckLoanCtxt<'self> {
             // `RESTR_MUTATE` restriction whenever the contents of an
             // owned pointer are borrowed, and hence while `v[*]` is not
             // restricted from being written, `v` is.
-            for self.each_in_scope_restriction(expr.id, loan_path)
+            for this.each_in_scope_restriction(expr.id, loan_path)
                 |loan, restr|
             {
                 if restr.set.intersects(RESTR_MUTATE) {
-                    self.report_illegal_mutation(expr, loan_path, loan);
+                    this.report_illegal_mutation(expr, loan_path, loan);
                     return false;
                 }
             }
@@ -557,9 +557,9 @@ pub impl<'self> CheckLoanCtxt<'self> {
                 }
 
                 // Check for a non-const loan of `loan_path`
-                for self.each_in_scope_loan(expr.id) |loan| {
+                for this.each_in_scope_loan(expr.id) |loan| {
                     if loan.loan_path == loan_path && loan.mutbl != m_const {
-                        self.report_illegal_mutation(expr, full_loan_path, loan);
+                        this.report_illegal_mutation(expr, full_loan_path, loan);
                         return false;
                     }
                 }
@@ -674,7 +674,7 @@ fn check_loans_in_fn<'a>(fk: &visit::fn_kind,
                          body: &ast::blk,
                          sp: span,
                          id: ast::node_id,
-                         self: @mut CheckLoanCtxt<'a>,
+                         this: @mut CheckLoanCtxt<'a>,
                          visitor: visit::vt<@mut CheckLoanCtxt<'a>>) {
     match *fk {
         visit::fk_item_fn(*) |
@@ -685,48 +685,48 @@ fn check_loans_in_fn<'a>(fk: &visit::fn_kind,
 
         visit::fk_anon(*) |
         visit::fk_fn_block(*) => {
-            let fty = ty::node_id_to_type(self.tcx(), id);
+            let fty = ty::node_id_to_type(this.tcx(), id);
             let fty_sigil = ty::ty_closure_sigil(fty);
-            check_moves_from_captured_variables(self, id, fty_sigil);
+            check_moves_from_captured_variables(this, id, fty_sigil);
         }
     }
 
-    visit::visit_fn(fk, decl, body, sp, id, self, visitor);
+    visit::visit_fn(fk, decl, body, sp, id, this, visitor);
 
-    fn check_moves_from_captured_variables(self: @mut CheckLoanCtxt,
+    fn check_moves_from_captured_variables(this: @mut CheckLoanCtxt,
                                            id: ast::node_id,
                                            fty_sigil: ast::Sigil) {
         match fty_sigil {
             ast::ManagedSigil | ast::OwnedSigil => {
-                let cap_vars = self.bccx.capture_map.get(&id);
+                let cap_vars = this.bccx.capture_map.get(&id);
                 for cap_vars.each |cap_var| {
                     match cap_var.mode {
                         moves::CapRef | moves::CapCopy => { loop; }
                         moves::CapMove => { }
                     }
                     let def_id = ast_util::def_id_of_def(cap_var.def).node;
-                    let ty = ty::node_id_to_type(self.tcx(), def_id);
-                    let cmt = self.bccx.cat_def(id, cap_var.span,
+                    let ty = ty::node_id_to_type(this.tcx(), def_id);
+                    let cmt = this.bccx.cat_def(id, cap_var.span,
                                                 ty, cap_var.def);
-                    let move_err = self.analyze_move_out_from_cmt(cmt);
+                    let move_err = this.analyze_move_out_from_cmt(cmt);
                     match move_err {
                         MoveOk => {}
                         MoveFromIllegalCmt(move_cmt) => {
-                            self.bccx.span_err(
+                            this.bccx.span_err(
                                 cap_var.span,
                                 fmt!("illegal by-move capture of %s",
-                                     self.bccx.cmt_to_str(move_cmt)));
+                                     this.bccx.cmt_to_str(move_cmt)));
                         }
                         MoveWhileBorrowed(loan_path, loan_span) => {
-                            self.bccx.span_err(
+                            this.bccx.span_err(
                                 cap_var.span,
                                 fmt!("cannot move `%s` into closure \
                                       because it is borrowed",
-                                     self.bccx.loan_path_to_str(loan_path)));
-                            self.bccx.span_note(
+                                     this.bccx.loan_path_to_str(loan_path)));
+                            this.bccx.span_note(
                                 loan_span,
                                 fmt!("borrow of `%s` occurs here",
-                                     self.bccx.loan_path_to_str(loan_path)));
+                                     this.bccx.loan_path_to_str(loan_path)));
                         }
                     }
                 }
@@ -738,48 +738,48 @@ fn check_loans_in_fn<'a>(fk: &visit::fn_kind,
 }
 
 fn check_loans_in_local<'a>(local: @ast::local,
-                            self: @mut CheckLoanCtxt<'a>,
+                            this: @mut CheckLoanCtxt<'a>,
                             vt: visit::vt<@mut CheckLoanCtxt<'a>>) {
-    visit::visit_local(local, self, vt);
+    visit::visit_local(local, this, vt);
 }
 
 fn check_loans_in_expr<'a>(expr: @ast::expr,
-                           self: @mut CheckLoanCtxt<'a>,
+                           this: @mut CheckLoanCtxt<'a>,
                            vt: visit::vt<@mut CheckLoanCtxt<'a>>) {
     debug!("check_loans_in_expr(expr=%s)",
-           expr.repr(self.tcx()));
+           expr.repr(this.tcx()));
 
-    visit::visit_expr(expr, self, vt);
+    visit::visit_expr(expr, this, vt);
 
-    self.check_for_conflicting_loans(expr.id);
+    this.check_for_conflicting_loans(expr.id);
 
-    if self.bccx.moves_map.contains(&expr.id) {
-        self.check_move_out_from_expr(expr);
+    if this.bccx.moves_map.contains(&expr.id) {
+        this.check_move_out_from_expr(expr);
     }
 
     match expr.node {
       ast::expr_assign(dest, _) |
       ast::expr_assign_op(_, dest, _) => {
-        self.check_assignment(dest);
+        this.check_assignment(dest);
       }
       ast::expr_call(f, ref args, _) => {
-        self.check_call(expr, Some(f), f.id, f.span, *args);
+        this.check_call(expr, Some(f), f.id, f.span, *args);
       }
       ast::expr_method_call(_, _, _, ref args, _) => {
-        self.check_call(expr, None, expr.callee_id, expr.span, *args);
+        this.check_call(expr, None, expr.callee_id, expr.span, *args);
       }
       ast::expr_index(_, rval) |
       ast::expr_binary(_, _, rval)
-      if self.bccx.method_map.contains_key(&expr.id) => {
-        self.check_call(expr,
+      if this.bccx.method_map.contains_key(&expr.id) => {
+        this.check_call(expr,
                         None,
                         expr.callee_id,
                         expr.span,
                         ~[rval]);
       }
       ast::expr_unary(*) | ast::expr_index(*)
-      if self.bccx.method_map.contains_key(&expr.id) => {
-        self.check_call(expr,
+      if this.bccx.method_map.contains_key(&expr.id) => {
+        this.check_call(expr,
                         None,
                         expr.callee_id,
                         expr.span,
@@ -790,10 +790,10 @@ fn check_loans_in_expr<'a>(expr: @ast::expr,
 }
 
 fn check_loans_in_pat<'a>(pat: @ast::pat,
-                          self: @mut CheckLoanCtxt<'a>,
+                          this: @mut CheckLoanCtxt<'a>,
                           vt: visit::vt<@mut CheckLoanCtxt<'a>>)
 {
-    self.check_for_conflicting_loans(pat.id);
+    this.check_for_conflicting_loans(pat.id);
 
     // Note: moves out of pattern bindings are not checked by
     // the borrow checker, at least not directly.  What happens
@@ -806,13 +806,14 @@ fn check_loans_in_pat<'a>(pat: @ast::pat,
     // rewalk the patterns and rebuild the pattern
     // categorizations.
 
-    visit::visit_pat(pat, self, vt);
+    visit::visit_pat(pat, this, vt);
 }
 
 fn check_loans_in_block<'a>(blk: &ast::blk,
-                            self: @mut CheckLoanCtxt<'a>,
+                            this: @mut CheckLoanCtxt<'a>,
                             vt: visit::vt<@mut CheckLoanCtxt<'a>>)
 {
-    visit::visit_block(blk, self, vt);
-    self.check_for_conflicting_loans(blk.node.id);
+    visit::visit_block(blk, this, vt);
+    this.check_for_conflicting_loans(blk.node.id);
 }
+
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index 330d60a59d3..e377bebcc26 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -93,7 +93,7 @@ impl GuaranteeLifetimeContext {
                 let omit_root = (
                     ptr_mutbl == m_imm &&
                     self.bccx.is_subregion_of(self.loan_region, base_scope) &&
-                    base.mutbl.is_immutable() &&
+                    self.is_rvalue_or_immutable(base) &&
                     !self.is_moved(base)
                 );
 
@@ -168,6 +168,19 @@ impl GuaranteeLifetimeContext {
         }
     }
 
+    fn is_rvalue_or_immutable(&self,
+                              cmt: mc::cmt) -> bool {
+        //! We can omit the root on an `@T` value if the location
+        //! that holds the box is either (1) an rvalue, in which case
+        //! it is in a non-user-accessible temporary, or (2) an immutable
+        //! lvalue.
+
+        cmt.mutbl.is_immutable() || match cmt.guarantor().cat {
+            mc::cat_rvalue => true,
+            _ => false
+        }
+    }
+
     fn check_root(&self,
                   cmt_deref: mc::cmt,
                   cmt_base: mc::cmt,
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index 94a029911a8..64d32d713d0 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -90,14 +90,14 @@ pub fn gather_loans(bccx: @BorrowckCtxt,
 }
 
 fn add_pat_to_id_range(p: @ast::pat,
-                       self: @mut GatherLoanCtxt,
+                       this: @mut GatherLoanCtxt,
                        v: visit::vt<@mut GatherLoanCtxt>) {
     // NB: This visitor function just adds the pat ids into the id
     // range. We gather loans that occur in patterns using the
     // `gather_pat()` method below. Eventually these two should be
     // brought together.
-    self.id_range.add(p.id);
-    visit::visit_pat(p, self, v);
+    this.id_range.add(p.id);
+    visit::visit_pat(p, this, v);
 }
 
 fn gather_loans_in_fn(fk: &visit::fn_kind,
@@ -105,7 +105,7 @@ fn gather_loans_in_fn(fk: &visit::fn_kind,
                       body: &ast::blk,
                       sp: span,
                       id: ast::node_id,
-                      self: @mut GatherLoanCtxt,
+                      this: @mut GatherLoanCtxt,
                       v: visit::vt<@mut GatherLoanCtxt>) {
     match fk {
         // Do not visit items here, the outer loop in borrowck/mod
@@ -116,95 +116,95 @@ fn gather_loans_in_fn(fk: &visit::fn_kind,
 
         // Visit closures as part of the containing item.
         &visit::fk_anon(*) | &visit::fk_fn_block(*) => {
-            self.push_repeating_id(body.node.id);
-            visit::visit_fn(fk, decl, body, sp, id, self, v);
-            self.pop_repeating_id(body.node.id);
+            this.push_repeating_id(body.node.id);
+            visit::visit_fn(fk, decl, body, sp, id, this, v);
+            this.pop_repeating_id(body.node.id);
         }
     }
 }
 
 fn gather_loans_in_block(blk: &ast::blk,
-                         self: @mut GatherLoanCtxt,
+                         this: @mut GatherLoanCtxt,
                          vt: visit::vt<@mut GatherLoanCtxt>) {
-    self.id_range.add(blk.node.id);
-    visit::visit_block(blk, self, vt);
+    this.id_range.add(blk.node.id);
+    visit::visit_block(blk, this, vt);
 }
 
 fn gather_loans_in_expr(ex: @ast::expr,
-                        self: @mut GatherLoanCtxt,
+                        this: @mut GatherLoanCtxt,
                         vt: visit::vt<@mut GatherLoanCtxt>) {
-    let bccx = self.bccx;
+    let bccx = this.bccx;
     let tcx = bccx.tcx;
 
     debug!("gather_loans_in_expr(expr=%?/%s)",
            ex.id, pprust::expr_to_str(ex, tcx.sess.intr()));
 
-    self.id_range.add(ex.id);
-    self.id_range.add(ex.callee_id);
+    this.id_range.add(ex.id);
+    this.id_range.add(ex.callee_id);
 
     // If this expression is borrowed, have to ensure it remains valid:
     for tcx.adjustments.find(&ex.id).each |&adjustments| {
-        self.guarantee_adjustments(ex, *adjustments);
+        this.guarantee_adjustments(ex, *adjustments);
     }
 
     // Special checks for various kinds of expressions:
     match ex.node {
       ast::expr_addr_of(mutbl, base) => {
-        let base_cmt = self.bccx.cat_expr(base);
+        let base_cmt = this.bccx.cat_expr(base);
 
         // make sure that the thing we are pointing out stays valid
         // for the lifetime `scope_r` of the resulting ptr:
         let scope_r = ty_region(tcx, ex.span, ty::expr_ty(tcx, ex));
-        self.guarantee_valid(ex.id, ex.span, base_cmt, mutbl, scope_r);
-        visit::visit_expr(ex, self, vt);
+        this.guarantee_valid(ex.id, ex.span, base_cmt, mutbl, scope_r);
+        visit::visit_expr(ex, this, vt);
       }
 
       ast::expr_match(ex_v, ref arms) => {
-        let cmt = self.bccx.cat_expr(ex_v);
+        let cmt = this.bccx.cat_expr(ex_v);
         for arms.each |arm| {
             for arm.pats.each |pat| {
-                self.gather_pat(cmt, *pat, arm.body.node.id, ex.id);
+                this.gather_pat(cmt, *pat, arm.body.node.id, ex.id);
             }
         }
-        visit::visit_expr(ex, self, vt);
+        visit::visit_expr(ex, this, vt);
       }
 
       ast::expr_index(_, arg) |
       ast::expr_binary(_, _, arg)
-      if self.bccx.method_map.contains_key(&ex.id) => {
+      if this.bccx.method_map.contains_key(&ex.id) => {
           // Arguments in method calls are always passed by ref.
           //
           // Currently these do not use adjustments, so we have to
           // hardcode this check here (note that the receiver DOES use
           // adjustments).
           let scope_r = ty::re_scope(ex.id);
-          let arg_cmt = self.bccx.cat_expr(arg);
-          self.guarantee_valid(arg.id, arg.span, arg_cmt, m_imm, scope_r);
-          visit::visit_expr(ex, self, vt);
+          let arg_cmt = this.bccx.cat_expr(arg);
+          this.guarantee_valid(arg.id, arg.span, arg_cmt, m_imm, scope_r);
+          visit::visit_expr(ex, this, vt);
       }
 
       // see explanation attached to the `root_ub` field:
       ast::expr_while(cond, ref body) => {
           // during the condition, can only root for the condition
-          self.push_repeating_id(cond.id);
-          (vt.visit_expr)(cond, self, vt);
-          self.pop_repeating_id(cond.id);
+          this.push_repeating_id(cond.id);
+          (vt.visit_expr)(cond, this, vt);
+          this.pop_repeating_id(cond.id);
 
           // during body, can only root for the body
-          self.push_repeating_id(body.node.id);
-          (vt.visit_block)(body, self, vt);
-          self.pop_repeating_id(body.node.id);
+          this.push_repeating_id(body.node.id);
+          (vt.visit_block)(body, this, vt);
+          this.pop_repeating_id(body.node.id);
       }
 
       // see explanation attached to the `root_ub` field:
       ast::expr_loop(ref body, _) => {
-          self.push_repeating_id(body.node.id);
-          visit::visit_expr(ex, self, vt);
-          self.pop_repeating_id(body.node.id);
+          this.push_repeating_id(body.node.id);
+          visit::visit_expr(ex, this, vt);
+          this.pop_repeating_id(body.node.id);
       }
 
       _ => {
-        visit::visit_expr(ex, self, vt);
+        visit::visit_expr(ex, this, vt);
       }
     }
 }
@@ -624,13 +624,14 @@ pub impl GatherLoanCtxt {
 // Setting up info that preserve needs.
 // This is just the most convenient place to do it.
 fn add_stmt_to_map(stmt: @ast::stmt,
-                   self: @mut GatherLoanCtxt,
+                   this: @mut GatherLoanCtxt,
                    vt: visit::vt<@mut GatherLoanCtxt>) {
     match stmt.node {
         ast::stmt_expr(_, id) | ast::stmt_semi(_, id) => {
-            self.bccx.stmt_map.insert(id);
+            this.bccx.stmt_map.insert(id);
         }
         _ => ()
     }
-    visit::visit_stmt(stmt, self, vt);
+    visit::visit_stmt(stmt, this, vt);
 }
+
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index fbc186a6fd4..0f01b2b1e41 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -110,7 +110,7 @@ fn borrowck_fn(fk: &visit::fn_kind,
                body: &ast::blk,
                sp: span,
                id: ast::node_id,
-               self: @BorrowckCtxt,
+               this: @BorrowckCtxt,
                v: visit::vt<@BorrowckCtxt>) {
     match fk {
         &visit::fk_anon(*) |
@@ -124,11 +124,11 @@ fn borrowck_fn(fk: &visit::fn_kind,
 
             // Check the body of fn items.
             let (id_range, all_loans) =
-                gather_loans::gather_loans(self, body);
+                gather_loans::gather_loans(this, body);
             let all_loans: &~[Loan] = &*all_loans; // FIXME(#5074)
             let mut dfcx =
-                DataFlowContext::new(self.tcx,
-                                     self.method_map,
+                DataFlowContext::new(this.tcx,
+                                     this.method_map,
                                      LoanDataFlowOperator,
                                      id_range,
                                      all_loans.len());
@@ -137,11 +137,11 @@ fn borrowck_fn(fk: &visit::fn_kind,
                 dfcx.add_kill(loan.kill_scope, loan_idx);
             }
             dfcx.propagate(body);
-            check_loans::check_loans(self, &dfcx, *all_loans, body);
+            check_loans::check_loans(this, &dfcx, *all_loans, body);
         }
     }
 
-    visit::visit_fn(fk, decl, body, sp, id, self, v);
+    visit::visit_fn(fk, decl, body, sp, id, this, v);
 }
 
 // ----------------------------------------------------------------------
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 9e6d9053237..faa489e5763 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -241,7 +241,7 @@ pub fn check_item_recursion(sess: Session,
                     ast_map::node_item(it, _) => {
                       (v.visit_item)(it, env, v);
                     }
-                    _ => fail!(~"const not bound to an item")
+                    _ => fail!("const not bound to an item")
                   }
                 }
               }
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 330d30c17a8..d859e03811f 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -147,14 +147,14 @@ pub fn check_exhaustive(cx: @MatchCheckCtxt, sp: span, pats: ~[@pat]) {
                 ty::ty_enum(id, _) => {
                     let vid = match *ctor {
                         variant(id) => id,
-                        _ => fail!(~"check_exhaustive: non-variant ctor"),
+                        _ => fail!("check_exhaustive: non-variant ctor"),
                     };
                     let variants = ty::enum_variants(cx.tcx, id);
 
                     match variants.find(|v| v.id == vid) {
                         Some(v) => Some(cx.tcx.sess.str_of(v.name)),
                         None => {
-                            fail!(~"check_exhaustive: bad variant in ctor")
+                            fail!("check_exhaustive: bad variant in ctor")
                         }
                     }
                 }
@@ -382,7 +382,7 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
               None => (),
               Some(val(const_bool(true))) => true_found = true,
               Some(val(const_bool(false))) => false_found = true,
-              _ => fail!(~"impossible case")
+              _ => fail!("impossible case")
             }
         }
         if true_found && false_found { None }
@@ -449,10 +449,10 @@ pub fn ctor_arity(cx: @MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
       ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u,
       ty::ty_enum(eid, _) => {
           let id = match *ctor { variant(id) => id,
-          _ => fail!(~"impossible case") };
+          _ => fail!("impossible case") };
         match vec::find(*ty::enum_variants(cx.tcx, eid), |v| v.id == id ) {
             Some(v) => v.args.len(),
-            None => fail!(~"impossible case")
+            None => fail!("impossible case")
         }
       }
       ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
@@ -504,7 +504,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
                                     compare_const_vals(c_hi, &e_v) <= 0
                             }
                             single => true,
-                            _ => fail!(~"type error")
+                            _ => fail!("type error")
                         };
                         if match_ {
                             Some(vec::to_owned(r.tail()))
@@ -535,7 +535,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
                                     compare_const_vals(c_hi, &e_v) <= 0
                             }
                             single => true,
-                            _ => fail!(~"type error")
+                            _ => fail!("type error")
                         };
                         if match_ {
                             Some(vec::to_owned(r.tail()))
@@ -625,7 +625,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
                             compare_const_vals(c_hi, &e_v) <= 0
                     }
                     single => true,
-                    _ => fail!(~"type error")
+                    _ => fail!("type error")
                 };
                 if match_ { Some(vec::to_owned(r.tail())) } else { None }
             }
@@ -635,7 +635,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
                     range(ref lo, ref hi) =>
                         ((/*bad*/copy *lo), (/*bad*/copy *hi)),
                     single => return Some(vec::to_owned(r.tail())),
-                    _ => fail!(~"type error")
+                    _ => fail!("type error")
                 };
                 let v_lo = eval_const_expr(cx.tcx, lo),
                 v_hi = eval_const_expr(cx.tcx, hi);
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 7c1933d6785..6cc4409aee6 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -467,7 +467,7 @@ pub fn compare_const_vals(a: &const_val, b: &const_val) -> int {
             1
         }
     }
-    _ => fail!(~"compare_const_vals: ill-typed comparison")
+    _ => fail!("compare_const_vals: ill-typed comparison")
   }
 }
 
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index dc08fb39ad9..31d22b76800 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -753,7 +753,8 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
             }
 
             ast::expr_lit(*) |
-            ast::expr_path(*) => {
+            ast::expr_path(*) |
+            ast::expr_self => {
             }
 
             ast::expr_addr_of(_, e) |
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index 419b75a2ad9..872ad83b739 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -20,8 +20,7 @@ use syntax::{ast, ast_util, visit};
 
 // A vector of defs representing the free variables referred to in a function.
 // (The def_upvar will already have been stripped).
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub struct freevar_entry {
     def: ast::def, //< The variable being accessed free.
     span: span     //< First span where it is accessed (there can be multiple)
@@ -45,10 +44,10 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::blk)
         |expr, depth, v| {
             match expr.node {
               ast::expr_fn_block(*) => visit::visit_expr(expr, depth + 1, v),
-              ast::expr_path(*) => {
+              ast::expr_path(*) | ast::expr_self => {
                   let mut i = 0;
                   match def_map.find(&expr.id) {
-                    None => fail!(~"path not found"),
+                    None => fail!("path not found"),
                     Some(&df) => {
                       let mut def = df;
                       while i < depth {
@@ -111,7 +110,7 @@ pub fn annotate_freevars(def_map: resolve::DefMap, crate: @ast::crate) ->
 
 pub fn get_freevars(tcx: ty::ctxt, fid: ast::node_id) -> freevar_info {
     match tcx.freevars.find(&fid) {
-      None => fail!(~"get_freevars: "+int::to_str(fid)+~" has no freevars"),
+      None => fail!("get_freevars: %d has no freevars", fid),
       Some(&d) => return d
     }
 }
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index f8f6dbd8259..a891e8d3b7f 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -275,11 +275,11 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
         };
         if ts.len() != type_param_defs.len() {
             // Fail earlier to make debugging easier
-            fail!(fmt!("internal error: in kind::check_expr, length \
-                       mismatch between actual and declared bounds: actual = \
-                        %s, declared = %s",
-                       ts.repr(cx.tcx),
-                       type_param_defs.repr(cx.tcx)));
+            fail!("internal error: in kind::check_expr, length \
+                  mismatch between actual and declared bounds: actual = \
+                  %s, declared = %s",
+                  ts.repr(cx.tcx),
+                  type_param_defs.repr(cx.tcx));
         }
         for vec::each2(**ts, *type_param_defs) |&ty, type_param_def| {
             check_bounds(cx, type_parameter_id, e.span, ty, type_param_def)
@@ -360,7 +360,7 @@ fn is_nullary_variant(cx: Context, ex: @expr) -> bool {
       expr_path(_) => {
         match cx.tcx.def_map.get_copy(&ex.id) {
           def_variant(edid, vdid) => {
-            vec::len(ty::enum_variant_with_id(cx.tcx, edid, vdid).args) == 0u
+              vec::len(ty::enum_variant_with_id(cx.tcx, edid, vdid).args) == 0u
           }
           _ => false
         }
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index f7f5f0fe29c..aecbcb626e9 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use driver::session::Session;
 use driver::session;
 use middle::ty;
 use middle::pat_util;
@@ -19,7 +18,7 @@ use std::smallintmap::SmallIntMap;
 use syntax::attr;
 use syntax::codemap::span;
 use syntax::codemap;
-use syntax::{ast, visit};
+use syntax::{ast, visit, ast_util};
 
 /**
  * A 'lint' check is a kind of miscellaneous constraint that a user _might_
@@ -28,18 +27,34 @@ use syntax::{ast, visit};
  * other phases of the compiler, which are generally required to hold in order
  * to compile the program at all.
  *
- * We also build up a table containing information about lint settings, in
- * order to allow other passes to take advantage of the lint attribute
- * infrastructure. To save space, the table is keyed by the id of /items/, not
- * of every expression. When an item has the default settings, the entry will
- * be omitted. If we start allowing lint attributes on expressions, we will
- * start having entries for expressions that do not share their enclosing
- * items settings.
+ * The lint checking is all consolidated into one pass which runs just before
+ * translation to LLVM bytecode. Throughout compilation, lint warnings can be
+ * added via the `add_lint` method on the Session structure. This requires a
+ * span and an id of the node that the lint is being added to. The lint isn't
+ * actually emitted at that time because it is unknown what the actual lint
+ * level at that location is.
  *
- * This module then, exports two passes: one that populates the lint
- * settings table in the session and is run early in the compile process, and
- * one that does a variety of lint checks, and is run late in the compile
- * process.
+ * To actually emit lint warnings/errors, a separate pass is used just before
+ * translation. A context keeps track of the current state of all lint levels.
+ * Upon entering a node of the ast which can modify the lint settings, the
+ * previous lint state is pushed onto a stack and the ast is then recursed upon.
+ * As the ast is traversed, this keeps track of the current lint level for all
+ * lint attributes.
+ *
+ * At each node of the ast which can modify lint attributes, all known lint
+ * passes are also applied.  Each lint pass is a visit::vt<()> structure. These
+ * visitors are constructed via the lint_*() functions below. There are also
+ * some lint checks which operate directly on ast nodes (such as @ast::item),
+ * and those are organized as check_item_*(). Each visitor added to the lint
+ * context is modified to stop once it reaches a node which could alter the lint
+ * levels. This means that everything is looked at once and only once by every
+ * lint pass.
+ *
+ * With this all in place, to add a new lint warning, all you need to do is to
+ * either invoke `add_lint` on the session at the appropriate time, or write a
+ * lint pass in this module which is just an ast visitor. The context used when
+ * traversing the ast has a `span_lint` method which only needs the span of the
+ * item that's being warned about.
  */
 
 #[deriving(Eq)]
@@ -51,7 +66,6 @@ pub enum lint {
     implicit_copies,
     unrecognized_lint,
     non_implicitly_copyable_typarams,
-    vecs_implicitly_copyable,
     deprecated_pattern,
     non_camel_case_types,
     type_limits,
@@ -87,7 +101,20 @@ struct LintSpec {
     default: level
 }
 
-pub type LintDict = @HashMap<~str, LintSpec>;
+pub type LintDict = HashMap<~str, LintSpec>;
+
+enum AttributedNode<'self> {
+    Item(@ast::item),
+    Method(&'self ast::method),
+    Crate(@ast::crate),
+}
+
+#[deriving(Eq)]
+enum LintSource {
+    Node(span),
+    Default,
+    CommandLine
+}
 
 static lint_table: &'static [(&'static str, LintSpec)] = &[
     ("ctypes",
@@ -132,14 +159,6 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
         default: warn
      }),
 
-    ("vecs_implicitly_copyable",
-     LintSpec {
-        lint: vecs_implicitly_copyable,
-        desc: "make vecs and strs not implicitly copyable \
-              (only checked at top level)",
-        default: warn
-     }),
-
     ("implicit_copies",
      LintSpec {
         lint: implicit_copies,
@@ -234,82 +253,90 @@ pub fn get_lint_dict() -> LintDict {
     for lint_table.each|&(k, v)| {
         map.insert(k.to_str(), v);
     }
-    return @map;
-}
-
-pub fn get_lint_name(lint_mode: lint) -> ~str {
-    for lint_table.each |&(name, spec)| {
-        if spec.lint == lint_mode {
-            return name.to_str();
-        }
-    }
-    fail!();
-}
-// This is a highly not-optimal set of data structure decisions.
-type LintModes = @mut SmallIntMap<level>;
-type LintModeMap = @mut HashMap<ast::node_id, LintModes>;
-
-// settings_map maps node ids of items with non-default lint settings
-// to their settings; default_settings contains the settings for everything
-// not in the map.
-pub struct LintSettings {
-    default_settings: LintModes,
-    settings_map: LintModeMap
-}
-
-pub fn mk_lint_settings() -> LintSettings {
-    LintSettings {
-        default_settings: @mut SmallIntMap::new(),
-        settings_map: @mut HashMap::new()
-    }
-}
-
-pub fn get_lint_level(modes: LintModes, lint: lint) -> level {
-    match modes.find(&(lint as uint)) {
-      Some(&c) => c,
-      None => allow
-    }
-}
-
-pub fn get_lint_settings_level(settings: LintSettings,
-                               lint_mode: lint,
-                               _expr_id: ast::node_id,
-                               item_id: ast::node_id)
-                            -> level {
-    match settings.settings_map.find(&item_id) {
-      Some(&modes) => get_lint_level(modes, lint_mode),
-      None => get_lint_level(settings.default_settings, lint_mode)
-    }
-}
-
-// This is kind of unfortunate. It should be somewhere else, or we should use
-// a persistent data structure...
-fn clone_lint_modes(modes: LintModes) -> LintModes {
-    @mut (copy *modes)
+    return map;
 }
 
 struct Context {
-    dict: LintDict,
-    curr: LintModes,
-    is_default: bool,
-    sess: Session
+    // All known lint modes (string versions)
+    dict: @LintDict,
+    // Current levels of each lint warning
+    curr: SmallIntMap<(level, LintSource)>,
+    // context we're checking in (used to access fields like sess)
+    tcx: ty::ctxt,
+    // When recursing into an attributed node of the ast which modifies lint
+    // levels, this stack keeps track of the previous lint levels of whatever
+    // was modified.
+    lint_stack: ~[(lint, level, LintSource)],
+    // Each of these visitors represents a lint pass. A number of the lint
+    // attributes are registered by adding a visitor to iterate over the ast.
+    // Others operate directly on @ast::item structures (or similar). Finally,
+    // others still are added to the Session object via `add_lint`, and these
+    // are all passed with the lint_session visitor.
+    visitors: ~[visit::vt<()>],
 }
 
-pub impl Context {
+impl Context {
     fn get_level(&self, lint: lint) -> level {
-        get_lint_level(self.curr, lint)
+        match self.curr.find(&(lint as uint)) {
+          Some(&(lvl, _)) => lvl,
+          None => allow
+        }
     }
 
-    fn set_level(&self, lint: lint, level: level) {
+    fn get_source(&self, lint: lint) -> LintSource {
+        match self.curr.find(&(lint as uint)) {
+          Some(&(_, src)) => src,
+          None => Default
+        }
+    }
+
+    fn set_level(&mut self, lint: lint, level: level, src: LintSource) {
         if level == allow {
             self.curr.remove(&(lint as uint));
         } else {
-            self.curr.insert(lint as uint, level);
+            self.curr.insert(lint as uint, (level, src));
         }
     }
 
-    fn span_lint(&self, level: level, span: span, msg: ~str) {
-        self.sess.span_lint_level(level, span, msg);
+    fn lint_to_str(&self, lint: lint) -> ~str {
+        for self.dict.each |k, v| {
+            if v.lint == lint {
+                return copy *k;
+            }
+        }
+        fail!("unregistered lint %?", lint);
+    }
+
+    fn span_lint(&self, lint: lint, span: span, msg: &str) {
+        let (level, src) = match self.curr.find(&(lint as uint)) {
+            Some(&pair) => pair,
+            None => { return; }
+        };
+        if level == allow { return; }
+
+        let mut note = None;
+        let msg = match src {
+            Default | CommandLine => {
+                fmt!("%s [-%c %s%s]", msg, match level {
+                        warn => 'W', deny => 'D', forbid => 'F',
+                        allow => fail!()
+                    }, str::replace(self.lint_to_str(lint), "_", "-"),
+                    if src == Default { " (default)" } else { "" })
+            },
+            Node(src) => {
+                note = Some(src);
+                msg.to_str()
+            }
+        };
+        match level {
+            warn =>          { self.tcx.sess.span_warn(span, msg); }
+            deny | forbid => { self.tcx.sess.span_err(span, msg);  }
+            allow => fail!(),
+        }
+
+        for note.each |&span| {
+            self.tcx.sess.span_note(span, "lint level defined here");
+        }
     }
 
     /**
@@ -317,189 +344,191 @@ pub impl Context {
      * current lint context, call the provided function, then reset the
      * lints in effect to their previous state.
      */
-    fn with_lint_attrs(&self, attrs: ~[ast::attribute], f: &fn(Context)) {
-
-        let mut new_ctxt = *self;
-        let mut triples = ~[];
-
-        for [allow, warn, deny, forbid].each |level| {
-            let level_name = level_to_str(*level);
-            let metas =
-                attr::attr_metas(attr::find_attrs_by_name(attrs, level_name));
-            for metas.each |meta| {
-                match meta.node {
-                  ast::meta_list(_, ref metas) => {
-                    for metas.each |meta| {
-                        match meta.node {
-                          ast::meta_word(ref lintname) => {
-                            triples.push((*meta,
-                                          *level,
-                                          /*bad*/copy *lintname));
-                          }
-                          _ => {
-                            self.sess.span_err(
-                                meta.span,
-                                "malformed lint attribute");
-                          }
-                        }
-                    }
-                  }
-                  _  => {
-                    self.sess.span_err(meta.span,
-                                       "malformed lint attribute");
-                  }
-                }
-            }
-        }
-
-        for triples.each |triple| {
-            // FIXME(#3874): it would be nicer to write this...
-            // let (meta, level, lintname) = /*bad*/copy *pair;
-            let (meta, level, lintname) = match *triple {
-                (ref meta, level, lintname) => (meta, level, lintname)
-            };
-
-            match self.dict.find(lintname) {
+    fn with_lint_attrs(@mut self, attrs: &[ast::attribute], f: &fn()) {
+        // Parse all of the lint attributes, and then add them all to the
+        // current dictionary of lint information. Along the way, keep a history
+        // of what we changed so we can roll everything back after invoking the
+        // specified closure
+        let mut pushed = 0u;
+        for each_lint(self.tcx.sess, attrs) |meta, level, lintname| {
+            let lint = match self.dict.find(lintname) {
               None => {
                 self.span_lint(
-                    new_ctxt.get_level(unrecognized_lint),
+                    unrecognized_lint,
                     meta.span,
                     fmt!("unknown `%s` attribute: `%s`",
                          level_to_str(level), *lintname));
+                loop
               }
-              Some(lint) => {
-
-                if new_ctxt.get_level(lint.lint) == forbid &&
-                    level != forbid {
-                    self.span_lint(
-                        forbid,
-                        meta.span,
-                        fmt!("%s(%s) overruled by outer forbid(%s)",
-                             level_to_str(level),
-                             *lintname, *lintname));
-                }
+              Some(lint) => { lint.lint }
+            };
 
-                // we do multiple unneeded copies of the
-                // map if many attributes are set, but
-                // this shouldn't actually be a problem...
+            let now = self.get_level(lint);
+            if now == forbid && level != forbid {
+                self.tcx.sess.span_err(meta.span,
+                    fmt!("%s(%s) overruled by outer forbid(%s)",
+                         level_to_str(level),
+                         *lintname, *lintname));
+                loop;
+            }
 
-                let c = clone_lint_modes(new_ctxt.curr);
-                new_ctxt = Context {
-                    is_default: false,
-                    curr: c,
-                    .. new_ctxt
-                };
-                new_ctxt.set_level(lint.lint, level);
-              }
+            if now != level {
+                let src = self.get_source(lint);
+                self.lint_stack.push((lint, now, src));
+                pushed += 1;
+                self.set_level(lint, level, Node(meta.span));
             }
         }
-        f(new_ctxt);
-    }
-}
 
+        f();
 
-fn build_settings_item(i: @ast::item, cx: Context, v: visit::vt<Context>) {
-    do cx.with_lint_attrs(/*bad*/copy i.attrs) |cx| {
-        if !cx.is_default {
-            cx.sess.lint_settings.settings_map.insert(i.id, cx.curr);
+        // rollback
+        for pushed.times {
+            let (lint, lvl, src) = self.lint_stack.pop();
+            self.set_level(lint, lvl, src);
         }
-        visit::visit_item(i, cx, v);
     }
-}
-
-pub fn build_settings_crate(sess: session::Session, crate: @ast::crate) {
-    let cx = Context {
-        dict: get_lint_dict(),
-        curr: @mut SmallIntMap::new(),
-        is_default: true,
-        sess: sess
-    };
 
-    // Install defaults.
-    for cx.dict.each_value |&spec| {
-        cx.set_level(spec.lint, spec.default);
+    fn add_lint(&mut self, v: visit::vt<()>) {
+        self.visitors.push(item_stopping_visitor(v));
     }
 
-    // Install command-line options, overriding defaults.
-    for sess.opts.lint_opts.each |pair| {
-        let (lint,level) = *pair;
-        cx.set_level(lint, level);
+    fn process(&self, n: AttributedNode) {
+        match n {
+            Item(it) => {
+                for self.visitors.each |v| {
+                    visit::visit_item(it, (), *v);
+                }
+            }
+            Crate(c) => {
+                for self.visitors.each |v| {
+                    visit::visit_crate(c, (), *v);
+                }
+            }
+            // Can't use visit::visit_method_helper because the
+            // item_stopping_visitor has overridden visit_fn(&fk_method(... ))
+            // to be a no-op, so manually invoke visit_fn.
+            Method(m) => {
+                let fk = visit::fk_method(copy m.ident, &m.generics, m);
+                for self.visitors.each |v| {
+                    visit::visit_fn(&fk, &m.decl, &m.body, m.span, m.id,
+                                    (), *v);
+                }
+            }
+        }
     }
+}
 
-    do cx.with_lint_attrs(/*bad*/copy crate.node.attrs) |cx| {
-        // Copy out the default settings
-        for cx.curr.each |&k, &v| {
-            sess.lint_settings.default_settings.insert(k, v);
+#[cfg(stage0)]
+pub fn each_lint(sess: session::Session,
+                 attrs: &[ast::attribute],
+                 f: &fn(@ast::meta_item, level, &~str) -> bool)
+{
+    for [allow, warn, deny, forbid].each |&level| {
+        let level_name = level_to_str(level);
+        let attrs = attr::find_attrs_by_name(attrs, level_name);
+        for attrs.each |attr| {
+            let meta = attr.node.value;
+            let metas = match meta.node {
+                ast::meta_list(_, ref metas) => metas,
+                _ => {
+                    sess.span_err(meta.span, ~"malformed lint attribute");
+                    loop;
+                }
+            };
+            for metas.each |meta| {
+                match meta.node {
+                    ast::meta_word(lintname) => {
+                        if !f(*meta, level, lintname) {
+                            return;
+                        }
+                    }
+                    _ => {
+                        sess.span_err(meta.span, ~"malformed lint attribute");
+                    }
+                }
+            }
         }
-
-        let cx = Context {
-            is_default: true,
-            .. cx
-        };
-
-        let visit = visit::mk_vt(@visit::Visitor {
-            visit_item: build_settings_item,
-            .. *visit::default_visitor()
-        });
-        visit::visit_crate(crate, cx, visit);
     }
-
-    sess.abort_if_errors();
 }
-
-fn check_item(i: @ast::item, cx: ty::ctxt) {
-    check_item_ctypes(cx, i);
-    check_item_while_true(cx, i);
-    check_item_path_statement(cx, i);
-    check_item_non_camel_case_types(cx, i);
-    check_item_heap(cx, i);
-    check_item_type_limits(cx, i);
-    check_item_default_methods(cx, i);
-    check_item_unused_unsafe(cx, i);
-    check_item_unused_mut(cx, i);
+#[cfg(not(stage0))]
+pub fn each_lint(sess: session::Session,
+                 attrs: &[ast::attribute],
+                 f: &fn(@ast::meta_item, level, &~str) -> bool) -> bool
+{
+    for [allow, warn, deny, forbid].each |&level| {
+        let level_name = level_to_str(level);
+        let attrs = attr::find_attrs_by_name(attrs, level_name);
+        for attrs.each |attr| {
+            let meta = attr.node.value;
+            let metas = match meta.node {
+                ast::meta_list(_, ref metas) => metas,
+                _ => {
+                    sess.span_err(meta.span, ~"malformed lint attribute");
+                    loop;
+                }
+            };
+            for metas.each |meta| {
+                match meta.node {
+                    ast::meta_word(lintname) => {
+                        if !f(*meta, level, lintname) {
+                            return false;
+                        }
+                    }
+                    _ => {
+                        sess.span_err(meta.span, ~"malformed lint attribute");
+                    }
+                }
+            }
+        }
+    }
+    return true;
 }
 
 // Take a visitor, and modify it so that it will not proceed past subitems.
 // This is used to make the simple visitors used for the lint passes
 // not traverse into subitems, since that is handled by the outer
 // lint visitor.
-fn item_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
-    visit::mk_vt(@visit::Visitor {visit_item: |_i, _e, _v| { },
-        .. **(ty_stopping_visitor(v))})
+fn item_stopping_visitor<E: Copy>(v: visit::vt<E>) -> visit::vt<E> {
+    visit::mk_vt(@visit::Visitor {
+        visit_item: |_i, _e, _v| { },
+        visit_fn: |fk, fd, b, s, id, e, v| {
+            match *fk {
+                visit::fk_method(*) => {}
+                _ => visit::visit_fn(fk, fd, b, s, id, e, v)
+            }
+        },
+    .. **(ty_stopping_visitor(v))})
 }
 
 fn ty_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
     visit::mk_vt(@visit::Visitor {visit_ty: |_t, _e, _v| { },.. **v})
 }
 
-fn check_item_while_true(cx: ty::ctxt, it: @ast::item) {
-    let visit = item_stopping_visitor(
-        visit::mk_simple_visitor(@visit::SimpleVisitor {
-            visit_expr: |e: @ast::expr| {
-                match e.node {
-                    ast::expr_while(cond, _) => {
-                        match cond.node {
-                            ast::expr_lit(@codemap::spanned {
-                                node: ast::lit_bool(true), _}) =>
-                            {
-                                cx.sess.span_lint(
-                                    while_true, e.id, it.id,
-                                    e.span,
-                                    "denote infinite loops \
-                                     with loop { ... }");
-                            }
-                            _ => ()
+fn lint_while_true(cx: @mut Context) -> visit::vt<()> {
+    visit::mk_simple_visitor(@visit::SimpleVisitor {
+        visit_expr: |e: @ast::expr| {
+            match e.node {
+                ast::expr_while(cond, _) => {
+                    match cond.node {
+                        ast::expr_lit(@codemap::spanned {
+                            node: ast::lit_bool(true), _}) =>
+                        {
+                            cx.span_lint(while_true, e.span,
+                                         "denote infinite loops with \
+                                          loop { ... }");
                         }
+                        _ => ()
                     }
-                    _ => ()
                 }
-            },
-            .. *visit::default_simple_visitor()
-        }));
-    visit::visit_item(it, (), visit);
+                _ => ()
+            }
+        },
+        .. *visit::default_simple_visitor()
+    })
 }
 
-fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
+fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
     fn is_valid<T:cmp::Ord>(binop: ast::binop, v: T,
             min: T, max: T) -> bool {
         match binop {
@@ -543,7 +572,7 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
         }
     }
 
-    fn check_limits(cx: ty::ctxt, binop: ast::binop, l: &ast::expr,
+    fn check_limits(cx: @mut Context, binop: ast::binop, l: &ast::expr,
                     r: &ast::expr) -> bool {
         let (lit, expr, swap) = match (&l.node, &r.node) {
             (&ast::expr_lit(_), _) => (l, r, true),
@@ -552,12 +581,12 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
         };
         // Normalize the binop so that the literal is always on the RHS in
         // the comparison
-        let norm_binop = if (swap) {
+        let norm_binop = if swap {
             rev_binop(binop)
         } else {
             binop
         };
-        match ty::get(ty::expr_ty(cx, @/*bad*/copy *expr)).sty {
+        match ty::get(ty::expr_ty(cx.tcx, @/*bad*/copy *expr)).sty {
             ty::ty_int(int_ty) => {
                 let (min, max) = int_ty_range(int_ty);
                 let lit_val: i64 = match lit.node {
@@ -601,36 +630,29 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
             ast::expr_binary(ref binop, @ref l, @ref r) => {
                 if is_comparison(*binop)
                     && !check_limits(cx, *binop, l, r) {
-                    cx.sess.span_lint(
-                        type_limits, e.id, it.id, e.span,
-                        "comparison is useless due to type limits");
+                    cx.span_lint(type_limits, e.span,
+                                 "comparison is useless due to type limits");
                 }
             }
             _ => ()
         }
     };
 
-    let visit = item_stopping_visitor(
-        visit::mk_simple_visitor(@visit::SimpleVisitor {
-            visit_expr: visit_expr,
-            .. *visit::default_simple_visitor()
-        }));
-    visit::visit_item(it, (), visit);
+    visit::mk_simple_visitor(@visit::SimpleVisitor {
+        visit_expr: visit_expr,
+        .. *visit::default_simple_visitor()
+    })
 }
 
-fn check_item_default_methods(cx: ty::ctxt, item: @ast::item) {
+fn check_item_default_methods(cx: @mut Context, item: @ast::item) {
     match item.node {
         ast::item_trait(_, _, ref methods) => {
             for methods.each |method| {
                 match *method {
                     ast::required(*) => {}
                     ast::provided(*) => {
-                        cx.sess.span_lint(
-                            default_methods,
-                            item.id,
-                            item.id,
-                            item.span,
-                            "default methods are experimental");
+                        cx.span_lint(default_methods, item.span,
+                                     "default methods are experimental");
                     }
                 }
             }
@@ -639,25 +661,21 @@ fn check_item_default_methods(cx: ty::ctxt, item: @ast::item) {
     }
 }
 
-fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
-    fn check_foreign_fn(cx: ty::ctxt, fn_id: ast::node_id,
-                        decl: &ast::fn_decl) {
+fn check_item_ctypes(cx: @mut Context, it: @ast::item) {
+
+    fn check_foreign_fn(cx: @mut Context, decl: &ast::fn_decl) {
         let tys = vec::map(decl.inputs, |a| a.ty );
         for vec::each(vec::append_one(tys, decl.output)) |ty| {
             match ty.node {
               ast::ty_path(_, id) => {
-                match cx.def_map.get_copy(&id) {
+                match cx.tcx.def_map.get_copy(&id) {
                   ast::def_prim_ty(ast::ty_int(ast::ty_i)) => {
-                    cx.sess.span_lint(
-                        ctypes, id, fn_id,
-                        ty.span,
+                    cx.span_lint(ctypes, ty.span,
                         "found rust type `int` in foreign module, while \
                          libc::c_int or libc::c_long should be used");
                   }
                   ast::def_prim_ty(ast::ty_uint(ast::ty_u)) => {
-                    cx.sess.span_lint(
-                        ctypes, id, fn_id,
-                        ty.span,
+                    cx.span_lint(ctypes, ty.span,
                         "found rust type `uint` in foreign module, while \
                          libc::c_uint or libc::c_ulong should be used");
                   }
@@ -674,7 +692,7 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
         for nmod.items.each |ni| {
             match ni.node {
               ast::foreign_item_fn(ref decl, _, _) => {
-                check_foreign_fn(cx, it.id, decl);
+                check_foreign_fn(cx, decl);
               }
               // FIXME #4622: Not implemented.
               ast::foreign_item_const(*) => {}
@@ -685,57 +703,47 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
     }
 }
 
-fn check_item_heap(cx: ty::ctxt, it: @ast::item) {
-
-    fn check_type_for_lint(cx: ty::ctxt, lint: lint,
-                           node: ast::node_id,
-                           item: ast::node_id,
-                           span: span, ty: ty::t) {
-
-        if get_lint_settings_level(cx.sess.lint_settings,
-                                   lint, node, item) != allow {
-            let mut n_box = 0;
-            let mut n_uniq = 0;
-            ty::fold_ty(cx, ty, |t| {
-                match ty::get(t).sty {
-                  ty::ty_box(_) => n_box += 1,
-                  ty::ty_uniq(_) => n_uniq += 1,
-                  _ => ()
-                };
-                t
-            });
+fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) {
+    if cx.get_level(lint) == allow { return }
 
-            if (n_uniq > 0 && lint != managed_heap_memory) {
-                let s = ty_to_str(cx, ty);
-                let m = ~"type uses owned (~ type) pointers: " + s;
-                cx.sess.span_lint(lint, node, item, span, m);
-            }
+    let mut n_box = 0;
+    let mut n_uniq = 0;
+    ty::fold_ty(cx.tcx, ty, |t| {
+        match ty::get(t).sty {
+          ty::ty_box(_) => n_box += 1,
+          ty::ty_uniq(_) => n_uniq += 1,
+          _ => ()
+        };
+        t
+    });
 
-            if (n_box > 0 && lint != owned_heap_memory) {
-                let s = ty_to_str(cx, ty);
-                let m = ~"type uses managed (@ type) pointers: " + s;
-                cx.sess.span_lint(lint, node, item, span, m);
-            }
-        }
+    if n_uniq > 0 && lint != managed_heap_memory {
+        let s = ty_to_str(cx.tcx, ty);
+        let m = ~"type uses owned (~ type) pointers: " + s;
+        cx.span_lint(lint, span, m);
     }
 
-    fn check_type(cx: ty::ctxt,
-                  node: ast::node_id,
-                  item: ast::node_id,
-                  span: span, ty: ty::t) {
-            for [managed_heap_memory,
-                 owned_heap_memory,
-                 heap_memory].each |lint| {
-                check_type_for_lint(cx, *lint, node, item, span, ty);
-            }
+    if n_box > 0 && lint != owned_heap_memory {
+        let s = ty_to_str(cx.tcx, ty);
+        let m = ~"type uses managed (@ type) pointers: " + s;
+        cx.span_lint(lint, span, m);
+    }
+}
+
+fn check_type(cx: @mut Context, span: span, ty: ty::t) {
+    for [managed_heap_memory, owned_heap_memory, heap_memory].each |lint| {
+        check_type_for_lint(cx, *lint, span, ty);
     }
+}
 
+fn check_item_heap(cx: @mut Context, it: @ast::item) {
     match it.node {
       ast::item_fn(*) |
       ast::item_ty(*) |
       ast::item_enum(*) |
-      ast::item_struct(*) => check_type(cx, it.id, it.id, it.span,
-                                       ty::node_id_to_type(cx, it.id)),
+      ast::item_struct(*) => check_type(cx, it.span,
+                                        ty::node_id_to_type(cx.tcx,
+                                                            it.id)),
       _ => ()
     }
 
@@ -743,48 +751,44 @@ fn check_item_heap(cx: ty::ctxt, it: @ast::item) {
     match it.node {
         ast::item_struct(struct_def, _) => {
             for struct_def.fields.each |struct_field| {
-                check_type(cx, struct_field.node.id, it.id,
-                           struct_field.span,
-                           ty::node_id_to_type(cx, struct_field.node.id));
+                check_type(cx, struct_field.span,
+                           ty::node_id_to_type(cx.tcx,
+                                               struct_field.node.id));
             }
         }
         _ => ()
     }
+}
 
-    let visit = item_stopping_visitor(
-        visit::mk_simple_visitor(@visit::SimpleVisitor {
-            visit_expr: |e: @ast::expr| {
-                let ty = ty::expr_ty(cx, e);
-                check_type(cx, e.id, it.id, e.span, ty);
-            },
-            .. *visit::default_simple_visitor()
-        }));
-    visit::visit_item(it, (), visit);
+fn lint_heap(cx: @mut Context) -> visit::vt<()> {
+    visit::mk_simple_visitor(@visit::SimpleVisitor {
+        visit_expr: |e| {
+            let ty = ty::expr_ty(cx.tcx, e);
+            check_type(cx, e.span, ty);
+        },
+        .. *visit::default_simple_visitor()
+    })
 }
 
-fn check_item_path_statement(cx: ty::ctxt, it: @ast::item) {
-    let visit = item_stopping_visitor(
-        visit::mk_simple_visitor(@visit::SimpleVisitor {
-            visit_stmt: |s: @ast::stmt| {
-                match s.node {
-                    ast::stmt_semi(
-                        @ast::expr { id: id, node: ast::expr_path(_), _ },
-                        _
-                    ) => {
-                        cx.sess.span_lint(
-                            path_statement, id, it.id,
-                            s.span,
-                            "path statement with no effect");
-                    }
-                    _ => ()
+fn lint_path_statement(cx: @mut Context) -> visit::vt<()> {
+    visit::mk_simple_visitor(@visit::SimpleVisitor {
+        visit_stmt: |s| {
+            match s.node {
+                ast::stmt_semi(
+                    @ast::expr { node: ast::expr_path(_), _ },
+                    _
+                ) => {
+                    cx.span_lint(path_statement, s.span,
+                                 "path statement with no effect");
                 }
-            },
-            .. *visit::default_simple_visitor()
-        }));
-    visit::visit_item(it, (), visit);
+                _ => ()
+            }
+        },
+        .. *visit::default_simple_visitor()
+    })
 }
 
-fn check_item_non_camel_case_types(cx: ty::ctxt, it: @ast::item) {
+fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
     fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool {
         let ident = cx.sess.str_of(ident);
         assert!(!ident.is_empty());
@@ -808,61 +812,54 @@ fn check_item_non_camel_case_types(cx: ty::ctxt, it: @ast::item) {
         }
     }
 
-    fn check_case(cx: ty::ctxt, ident: ast::ident,
-                  expr_id: ast::node_id, item_id: ast::node_id,
-                  span: span) {
-        if !is_camel_case(cx, ident) {
-            cx.sess.span_lint(
-                non_camel_case_types, expr_id, item_id, span,
-                "type, variant, or trait should have \
-                 a camel case identifier");
+    fn check_case(cx: @mut Context, ident: ast::ident, span: span) {
+        if !is_camel_case(cx.tcx, ident) {
+            cx.span_lint(non_camel_case_types, span,
+                         "type, variant, or trait should have \
+                          a camel case identifier");
         }
     }
 
     match it.node {
         ast::item_ty(*) | ast::item_struct(*) |
         ast::item_trait(*) => {
-            check_case(cx, it.ident, it.id, it.id, it.span)
+            check_case(cx, it.ident, it.span)
         }
         ast::item_enum(ref enum_definition, _) => {
-            check_case(cx, it.ident, it.id, it.id, it.span);
+            check_case(cx, it.ident, it.span);
             for enum_definition.variants.each |variant| {
-                check_case(cx, variant.node.name,
-                           variant.node.id, it.id, variant.span);
+                check_case(cx, variant.node.name, variant.span);
             }
         }
         _ => ()
     }
 }
 
-fn check_item_unused_unsafe(cx: ty::ctxt, it: @ast::item) {
+fn lint_unused_unsafe(cx: @mut Context) -> visit::vt<()> {
     let visit_expr: @fn(@ast::expr) = |e| {
         match e.node {
             ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => {
-                if !cx.used_unsafe.contains(&blk.node.id) {
-                    cx.sess.span_lint(unused_unsafe, blk.node.id, it.id,
-                                      blk.span,
-                                      "unnecessary `unsafe` block");
+                if !cx.tcx.used_unsafe.contains(&blk.node.id) {
+                    cx.span_lint(unused_unsafe, blk.span,
+                                 "unnecessary `unsafe` block");
                 }
             }
             _ => ()
         }
     };
 
-    let visit = item_stopping_visitor(
-        visit::mk_simple_visitor(@visit::SimpleVisitor {
-            visit_expr: visit_expr,
-            .. *visit::default_simple_visitor()
-        }));
-    visit::visit_item(it, (), visit);
+    visit::mk_simple_visitor(@visit::SimpleVisitor {
+        visit_expr: visit_expr,
+        .. *visit::default_simple_visitor()
+    })
 }
 
-fn check_item_unused_mut(tcx: ty::ctxt, it: @ast::item) {
+fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> {
     let check_pat: @fn(@ast::pat) = |p| {
         let mut used = false;
         let mut bindings = 0;
-        do pat_util::pat_bindings(tcx.def_map, p) |_, id, _, _| {
-            used = used || tcx.used_mut_nodes.contains(&id);
+        do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| {
+            used = used || cx.tcx.used_mut_nodes.contains(&id);
             bindings += 1;
         }
         if !used {
@@ -871,7 +868,7 @@ fn check_item_unused_mut(tcx: ty::ctxt, it: @ast::item) {
             } else {
                 "variables do not need to be mutable"
             };
-            tcx.sess.span_lint(unused_mut, p.id, it.id, p.span, msg);
+            cx.span_lint(unused_mut, p.span, msg);
         }
     };
 
@@ -883,45 +880,116 @@ fn check_item_unused_mut(tcx: ty::ctxt, it: @ast::item) {
         }
     };
 
-    let visit = item_stopping_visitor(
-        visit::mk_simple_visitor(@visit::SimpleVisitor {
-            visit_local: |l| {
-                if l.node.is_mutbl {
-                    check_pat(l.node.pat);
-                }
-            },
-            visit_fn: |_, fd, _, _, _| visit_fn_decl(fd),
-            visit_ty_method: |tm| visit_fn_decl(&tm.decl),
-            visit_struct_method: |sm| visit_fn_decl(&sm.decl),
-            visit_trait_method: |tm| {
-                match *tm {
-                    ast::required(ref tm) => visit_fn_decl(&tm.decl),
-                    ast::provided(m) => visit_fn_decl(&m.decl),
-                }
-            },
-            .. *visit::default_simple_visitor()
-        }));
-    visit::visit_item(it, (), visit);
+    visit::mk_simple_visitor(@visit::SimpleVisitor {
+        visit_local: |l| {
+            if l.node.is_mutbl {
+                check_pat(l.node.pat);
+            }
+        },
+        visit_fn: |_, fd, _, _, _| visit_fn_decl(fd),
+        visit_ty_method: |tm| visit_fn_decl(&tm.decl),
+        visit_struct_method: |sm| visit_fn_decl(&sm.decl),
+        visit_trait_method: |tm| {
+            match *tm {
+                ast::required(ref tm) => visit_fn_decl(&tm.decl),
+                ast::provided(m) => visit_fn_decl(&m.decl),
+            }
+        },
+        .. *visit::default_simple_visitor()
+    })
 }
 
-fn check_fn(_: ty::ctxt,
-            fk: &visit::fn_kind,
-            _: &ast::fn_decl,
-            _: &ast::blk,
-            _: span,
-            id: ast::node_id) {
-    debug!("lint check_fn fk=%? id=%?", fk, id);
+fn lint_session(cx: @mut Context) -> visit::vt<()> {
+    ast_util::id_visitor(|id| {
+        match cx.tcx.sess.lints.pop(&id) {
+            None => {},
+            Some(l) => {
+                do vec::consume(l) |_, (lint, span, msg)| {
+                    cx.span_lint(lint, span, msg)
+                }
+            }
+        }
+    })
 }
 
 pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
-    let v = visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_item: |it|
-            check_item(it, tcx),
-        visit_fn: |fk, decl, body, span, id|
-            check_fn(tcx, fk, decl, body, span, id),
-        .. *visit::default_simple_visitor()
-    });
-    visit::visit_crate(crate, (), v);
+    let cx = @mut Context {
+        dict: @get_lint_dict(),
+        curr: SmallIntMap::new(),
+        tcx: tcx,
+        lint_stack: ~[],
+        visitors: ~[],
+    };
+
+    // Install defaults.
+    for cx.dict.each_value |spec| {
+        cx.set_level(spec.lint, spec.default, Default);
+    }
+
+    // Install command-line options, overriding defaults.
+    for tcx.sess.opts.lint_opts.each |&(lint, level)| {
+        cx.set_level(lint, level, CommandLine);
+    }
+
+    // Register each of the lint passes with the context
+    cx.add_lint(lint_while_true(cx));
+    cx.add_lint(lint_path_statement(cx));
+    cx.add_lint(lint_heap(cx));
+    cx.add_lint(lint_type_limits(cx));
+    cx.add_lint(lint_unused_unsafe(cx));
+    cx.add_lint(lint_unused_mut(cx));
+    cx.add_lint(lint_session(cx));
+
+    // type inference doesn't like this being declared below, we need to tell it
+    // what the type of this first function is...
+    let visit_item:
+        @fn(@ast::item, @mut Context, visit::vt<@mut Context>) =
+    |it, cx, vt| {
+        do cx.with_lint_attrs(it.attrs) {
+            check_item_ctypes(cx, it);
+            check_item_non_camel_case_types(cx, it);
+            check_item_default_methods(cx, it);
+            check_item_heap(cx, it);
+
+            cx.process(Item(it));
+            visit::visit_item(it, cx, vt);
+        }
+    };
+
+    // Actually perform the lint checks (iterating the ast)
+    do cx.with_lint_attrs(crate.node.attrs) {
+        cx.process(Crate(crate));
+
+        visit::visit_crate(crate, cx, visit::mk_vt(@visit::Visitor {
+            visit_item: visit_item,
+            visit_fn: |fk, decl, body, span, id, cx, vt| {
+                match *fk {
+                    visit::fk_method(_, _, m) => {
+                        do cx.with_lint_attrs(m.attrs) {
+                            cx.process(Method(m));
+                            visit::visit_fn(fk, decl, body, span, id, cx, vt);
+                        }
+                    }
+                    _ => {
+                        visit::visit_fn(fk, decl, body, span, id, cx, vt);
+                    }
+                }
+            },
+            .. *visit::default_visitor()
+        }));
+    }
+
+    // If we missed any lints added to the session, then there's a bug somewhere
+    // in the iteration code.
+    for tcx.sess.lints.each |_, v| {
+        for v.each |t| {
+            match *t {
+                (lint, span, ref msg) =>
+                    tcx.sess.span_bug(span, fmt!("unprocessed lint %?: %s",
+                                                 lint, *msg))
+            }
+        }
+    }
 
     tcx.sess.abort_if_errors();
 }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 52274f3d305..711e3915277 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -153,15 +153,13 @@ pub fn check_crate(tcx: ty::ctxt,
         visit_local: visit_local,
         visit_expr: visit_expr,
         visit_arm: visit_arm,
-        visit_item: visit_item,
         .. *visit::default_visitor()
     });
 
     let initial_maps = @mut IrMaps(tcx,
                                    method_map,
                                    variable_moves_map,
-                                   capture_map,
-                                   0);
+                                   capture_map);
     visit::visit_crate(crate, initial_maps, visitor);
     tcx.sess.abort_if_errors();
 }
@@ -240,15 +238,12 @@ struct IrMaps {
     capture_info_map: HashMap<node_id, @~[CaptureInfo]>,
     var_kinds: ~[VarKind],
     lnks: ~[LiveNodeKind],
-
-    cur_item: node_id,
 }
 
 fn IrMaps(tcx: ty::ctxt,
           method_map: typeck::method_map,
           variable_moves_map: moves::VariableMovesMap,
-          capture_map: moves::CaptureMap,
-          cur_item: node_id)
+          capture_map: moves::CaptureMap)
        -> IrMaps {
     IrMaps {
         tcx: tcx,
@@ -262,7 +257,6 @@ fn IrMaps(tcx: ty::ctxt,
         capture_info_map: HashMap::new(),
         var_kinds: ~[],
         lnks: ~[],
-        cur_item: cur_item,
     }
 }
 
@@ -341,36 +335,28 @@ pub impl IrMaps {
     }
 }
 
-fn visit_item(item: @item, self: @mut IrMaps, v: vt<@mut IrMaps>) {
-    let old_cur_item = self.cur_item;
-    self.cur_item = item.id;
-    visit::visit_item(item, self, v);
-    self.cur_item = old_cur_item;
-}
-
 fn visit_fn(fk: &visit::fn_kind,
             decl: &fn_decl,
             body: &blk,
             sp: span,
             id: node_id,
-            self: @mut IrMaps,
+            this: @mut IrMaps,
             v: vt<@mut IrMaps>) {
     debug!("visit_fn: id=%d", id);
     let _i = ::util::common::indenter();
 
     // swap in a new set of IR maps for this function body:
-    let fn_maps = @mut IrMaps(self.tcx,
-                              self.method_map,
-                              self.variable_moves_map,
-                              self.capture_map,
-                              self.cur_item);
+    let fn_maps = @mut IrMaps(this.tcx,
+                              this.method_map,
+                              this.variable_moves_map,
+                              this.capture_map);
 
     unsafe {
         debug!("creating fn_maps: %x", transmute(&*fn_maps));
     }
 
     for decl.inputs.each |arg| {
-        do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
+        do pat_util::pat_bindings(this.tcx.def_map, arg.pat)
                 |_bm, arg_id, _x, path| {
             debug!("adding argument %d", arg_id);
             let ident = ast_util::path_to_ident(path);
@@ -378,10 +364,10 @@ fn visit_fn(fk: &visit::fn_kind,
         }
     };
 
-    // Add `self`, whether explicit or implicit.
+    // Add `this`, whether explicit or implicit.
     match *fk {
         fk_method(_, _, method) => {
-            match method.self_ty.node {
+            match method.explicit_self.node {
                 sty_value | sty_region(*) | sty_box(_) | sty_uniq(_) => {
                     fn_maps.add_variable(Arg(method.self_id,
                                              special_idents::self_));
@@ -423,35 +409,35 @@ fn visit_fn(fk: &visit::fn_kind,
     lsets.warn_about_unused_args(decl, entry_ln);
 }
 
-fn visit_local(local: @local, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
-    let def_map = self.tcx.def_map;
+fn visit_local(local: @local, this: @mut IrMaps, vt: vt<@mut IrMaps>) {
+    let def_map = this.tcx.def_map;
     do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| {
         debug!("adding local variable %d", p_id);
         let name = ast_util::path_to_ident(path);
-        self.add_live_node_for_node(p_id, VarDefNode(sp));
+        this.add_live_node_for_node(p_id, VarDefNode(sp));
         let kind = match local.node.init {
           Some(_) => FromLetWithInitializer,
           None => FromLetNoInitializer
         };
-        self.add_variable(Local(LocalInfo {
+        this.add_variable(Local(LocalInfo {
           id: p_id,
           ident: name,
           is_mutbl: local.node.is_mutbl,
           kind: kind
         }));
     }
-    visit::visit_local(local, self, vt);
+    visit::visit_local(local, this, vt);
 }
 
-fn visit_arm(arm: &arm, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
-    let def_map = self.tcx.def_map;
+fn visit_arm(arm: &arm, this: @mut IrMaps, vt: vt<@mut IrMaps>) {
+    let def_map = this.tcx.def_map;
     for arm.pats.each |pat| {
         do pat_util::pat_bindings(def_map, *pat) |bm, p_id, sp, path| {
             debug!("adding local variable %d from match with bm %?",
                    p_id, bm);
             let name = ast_util::path_to_ident(path);
-            self.add_live_node_for_node(p_id, VarDefNode(sp));
-            self.add_variable(Local(LocalInfo {
+            this.add_live_node_for_node(p_id, VarDefNode(sp));
+            this.add_variable(Local(LocalInfo {
                 id: p_id,
                 ident: name,
                 is_mutbl: false,
@@ -459,35 +445,35 @@ fn visit_arm(arm: &arm, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
             }));
         }
     }
-    visit::visit_arm(arm, self, vt);
+    visit::visit_arm(arm, this, vt);
 }
 
-fn visit_expr(expr: @expr, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
+fn visit_expr(expr: @expr, this: @mut IrMaps, vt: vt<@mut IrMaps>) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      expr_path(_) => {
-        let def = self.tcx.def_map.get_copy(&expr.id);
+      expr_path(_) | expr_self => {
+        let def = this.tcx.def_map.get_copy(&expr.id);
         debug!("expr %d: path that leads to %?", expr.id, def);
         if moves::moved_variable_node_id_from_def(def).is_some() {
-            self.add_live_node_for_node(expr.id, ExprNode(expr.span));
+            this.add_live_node_for_node(expr.id, ExprNode(expr.span));
         }
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
       expr_fn_block(*) => {
         // Interesting control flow (for loops can contain labeled
         // breaks or continues)
-        self.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        this.add_live_node_for_node(expr.id, ExprNode(expr.span));
 
         // Make a live_node for each captured variable, with the span
         // being the location that the variable is used.  This results
         // in better error messages than just pointing at the closure
         // construction site.
-        let cvs = self.capture_map.get(&expr.id);
+        let cvs = this.capture_map.get(&expr.id);
         let mut call_caps = ~[];
         for cvs.each |cv| {
             match moves::moved_variable_node_id_from_def(cv.def) {
               Some(rv) => {
-                let cv_ln = self.add_live_node(FreeVarNode(cv.span));
+                let cv_ln = this.add_live_node(FreeVarNode(cv.span));
                 let is_move = match cv.mode {
                     // var must be dead afterwards
                     moves::CapMove => true,
@@ -502,19 +488,19 @@ fn visit_expr(expr: @expr, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
               None => {}
             }
         }
-        self.set_captures(expr.id, call_caps);
+        this.set_captures(expr.id, call_caps);
 
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
 
       // live nodes required for interesting control flow:
       expr_if(*) | expr_match(*) | expr_while(*) | expr_loop(*) => {
-        self.add_live_node_for_node(expr.id, ExprNode(expr.span));
-        visit::visit_expr(expr, self, vt);
+        this.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        visit::visit_expr(expr, this, vt);
       }
       expr_binary(op, _, _) if ast_util::lazy_binop(op) => {
-        self.add_live_node_for_node(expr.id, ExprNode(expr.span));
-        visit::visit_expr(expr, self, vt);
+        this.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        visit::visit_expr(expr, this, vt);
       }
 
       // otherwise, live nodes are not required:
@@ -526,7 +512,7 @@ fn visit_expr(expr: @expr, self: @mut IrMaps, vt: vt<@mut IrMaps>) {
       expr_assign(*) | expr_assign_op(*) | expr_mac(*) |
       expr_struct(*) | expr_repeat(*) | expr_paren(*) |
       expr_inline_asm(*) => {
-          visit::visit_expr(expr, self, vt);
+          visit::visit_expr(expr, this, vt);
       }
     }
 }
@@ -1006,7 +992,7 @@ pub impl Liveness {
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          expr_path(_) => {
+          expr_path(_) | expr_self => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
@@ -1409,13 +1395,13 @@ pub impl Liveness {
 // _______________________________________________________________________
 // Checking for error conditions
 
-fn check_local(local: @local, self: @Liveness, vt: vt<@Liveness>) {
+fn check_local(local: @local, this: @Liveness, vt: vt<@Liveness>) {
     match local.node.init {
       Some(_) => {
 
         // Initializer:
-        self.warn_about_unused_or_dead_vars_in_pat(local.node.pat);
-        self.check_for_reassignments_in_pat(local.node.pat,
+        this.warn_about_unused_or_dead_vars_in_pat(local.node.pat);
+        this.check_for_reassignments_in_pat(local.node.pat,
                                             local.node.is_mutbl);
       }
       None => {
@@ -1424,12 +1410,12 @@ fn check_local(local: @local, self: @Liveness, vt: vt<@Liveness>) {
         // should not be live at this point.
 
         debug!("check_local() with no initializer");
-        do self.pat_bindings(local.node.pat) |ln, var, sp, id| {
-            if !self.warn_about_unused(sp, id, ln, var) {
-                match self.live_on_exit(ln, var) {
+        do this.pat_bindings(local.node.pat) |ln, var, sp, id| {
+            if !this.warn_about_unused(sp, id, ln, var) {
+                match this.live_on_exit(ln, var) {
                   None => { /* not live: good */ }
                   Some(lnk) => {
-                    self.report_illegal_read(
+                    this.report_illegal_read(
                         local.span, lnk, var,
                         PossiblyUninitializedVariable);
                   }
@@ -1439,77 +1425,77 @@ fn check_local(local: @local, self: @Liveness, vt: vt<@Liveness>) {
       }
     }
 
-    visit::visit_local(local, self, vt);
+    visit::visit_local(local, this, vt);
 }
 
-fn check_arm(arm: &arm, self: @Liveness, vt: vt<@Liveness>) {
-    do self.arm_pats_bindings(arm.pats) |ln, var, sp, id| {
-        self.warn_about_unused(sp, id, ln, var);
+fn check_arm(arm: &arm, this: @Liveness, vt: vt<@Liveness>) {
+    do this.arm_pats_bindings(arm.pats) |ln, var, sp, id| {
+        this.warn_about_unused(sp, id, ln, var);
     }
-    visit::visit_arm(arm, self, vt);
+    visit::visit_arm(arm, this, vt);
 }
 
-fn check_expr(expr: @expr, self: @Liveness, vt: vt<@Liveness>) {
+fn check_expr(expr: @expr, this: @Liveness, vt: vt<@Liveness>) {
     match expr.node {
-      expr_path(_) => {
-        for self.variable_from_def_map(expr.id, expr.span).each |var| {
-            let ln = self.live_node(expr.id, expr.span);
+      expr_path(_) | expr_self => {
+        for this.variable_from_def_map(expr.id, expr.span).each |var| {
+            let ln = this.live_node(expr.id, expr.span);
 
-            match self.ir.variable_moves_map.find(&expr.id) {
+            match this.ir.variable_moves_map.find(&expr.id) {
                 None => {}
                 Some(&entire_expr) => {
                     debug!("(checking expr) is a move: `%s`",
-                           expr_to_str(expr, self.tcx.sess.intr()));
-                    self.check_move_from_var(ln, *var, entire_expr);
+                           expr_to_str(expr, this.tcx.sess.intr()));
+                    this.check_move_from_var(ln, *var, entire_expr);
                 }
             }
         }
 
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
 
       expr_fn_block(*) => {
-        let caps = self.ir.captures(expr);
+        let caps = this.ir.captures(expr);
         for caps.each |cap| {
-            let var = self.variable(cap.var_nid, expr.span);
+            let var = this.variable(cap.var_nid, expr.span);
             if cap.is_move {
-                self.check_move_from_var(cap.ln, var, expr);
+                this.check_move_from_var(cap.ln, var, expr);
             }
         }
 
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
 
       expr_assign(l, r) => {
-        self.check_lvalue(l, vt);
-        (vt.visit_expr)(r, self, vt);
+        this.check_lvalue(l, vt);
+        (vt.visit_expr)(r, this, vt);
 
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
 
       expr_assign_op(_, l, _) => {
-        self.check_lvalue(l, vt);
+        this.check_lvalue(l, vt);
 
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
 
       expr_inline_asm(ref ia) => {
         for ia.inputs.each |&(_, in)| {
-          (vt.visit_expr)(in, self, vt);
+          (vt.visit_expr)(in, this, vt);
         }
 
         // Output operands must be lvalues
         for ia.outputs.each |&(_, out)| {
           match out.node {
             expr_addr_of(_, inner) => {
-              self.check_lvalue(inner, vt);
+              this.check_lvalue(inner, vt);
             }
             _ => {}
           }
-          (vt.visit_expr)(out, self, vt);
+          (vt.visit_expr)(out, this, vt);
         }
 
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
 
       // no correctness conditions related to liveness
@@ -1521,7 +1507,7 @@ fn check_expr(expr: @expr, self: @Liveness, vt: vt<@Liveness>) {
       expr_again(*) | expr_lit(_) | expr_block(*) |
       expr_mac(*) | expr_addr_of(*) | expr_struct(*) | expr_repeat(*) |
       expr_paren(*) => {
-        visit::visit_expr(expr, self, vt);
+        visit::visit_expr(expr, this, vt);
       }
     }
 }
@@ -1802,13 +1788,11 @@ pub impl Liveness {
                 };
 
                 if is_assigned {
-                    self.tcx.sess.span_lint(unused_variable, id,
-                        self.ir.cur_item, sp,
+                    self.tcx.sess.add_lint(unused_variable, id, sp,
                         fmt!("variable `%s` is assigned to, \
                                   but never used", **name));
                 } else {
-                    self.tcx.sess.span_lint(unused_variable, id,
-                        self.ir.cur_item, sp,
+                    self.tcx.sess.add_lint(unused_variable, id, sp,
                         fmt!("unused variable: `%s`", **name));
                 }
             }
@@ -1821,8 +1805,7 @@ pub impl Liveness {
                               ln: LiveNode, var: Variable) {
         if self.live_on_exit(ln, var).is_none() {
             for self.should_warn(var).each |name| {
-                self.tcx.sess.span_lint(dead_assignment, id,
-                    self.ir.cur_item, sp,
+                self.tcx.sess.add_lint(dead_assignment, id, sp,
                     fmt!("value assigned to `%s` is never read", **name));
             }
         }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 436905f9a53..91c0b8e61cc 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -406,7 +406,7 @@ pub impl mem_categorization_ctxt {
             self.cat_index(expr, base_cmt, 0)
           }
 
-          ast::expr_path(_) => {
+          ast::expr_path(_) | ast::expr_self => {
             let def = self.tcx.def_map.get_copy(&expr.id);
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
@@ -551,7 +551,7 @@ pub impl mem_categorization_ctxt {
             id:elt.id(),
             span:elt.span(),
             cat:cat_rvalue,
-            mutbl:McImmutable,
+            mutbl:McDeclared,
             ty:expr_ty
         }
     }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 2471e383bca..e81a9d6b78f 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -221,16 +221,14 @@ use syntax::visit::vt;
 use syntax::print::pprust;
 use syntax::codemap::span;
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub enum CaptureMode {
     CapCopy, // Copy the value into the closure.
     CapMove, // Move the value into the closure.
     CapRef,  // Reference directly from parent stack frame (used by `&fn()`).
 }
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub struct CaptureVar {
     def: def,         // Variable being accessed free
     span: span,       // Location of an access to this variable
@@ -435,7 +433,7 @@ pub impl VisitContext {
         debug!("comp_mode = %?", comp_mode);
 
         match expr.node {
-            expr_path(*) => {
+            expr_path(*) | expr_self => {
                 match comp_mode {
                     MoveInPart(entire_expr) => {
                         self.move_maps.variable_moves_map.insert(
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 76d35527104..27b62738793 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -127,7 +127,7 @@ pub impl RegionMaps {
 
         match self.scope_map.find(&id) {
             Some(&r) => r,
-            None => { fail!(fmt!("No enclosing scope for id %?", id)); }
+            None => { fail!("No enclosing scope for id %?", id); }
         }
     }
 
@@ -283,8 +283,8 @@ pub impl RegionMaps {
 
         let a_ancestors = ancestors_of(self, scope_a);
         let b_ancestors = ancestors_of(self, scope_b);
-        let mut a_index = vec::len(a_ancestors) - 1u;
-        let mut b_index = vec::len(b_ancestors) - 1u;
+        let mut a_index = a_ancestors.len() - 1u;
+        let mut b_index = b_ancestors.len() - 1u;
 
         // Here, ~[ab]_ancestors is a vector going from narrow to broad.
         // The end of each vector will be the item where the scope is
@@ -310,14 +310,14 @@ pub impl RegionMaps {
             }
         }
 
-        fn ancestors_of(self: &RegionMaps, scope: ast::node_id)
+        fn ancestors_of(this: &RegionMaps, scope: ast::node_id)
             -> ~[ast::node_id]
         {
             // debug!("ancestors_of(scope=%d)", scope);
             let mut result = ~[scope];
             let mut scope = scope;
             loop {
-                match self.scope_map.find(&scope) {
+                match this.scope_map.find(&scope) {
                     None => return result,
                     Some(&superscope) => {
                         result.push(superscope);
@@ -685,7 +685,7 @@ pub impl DetermineRpCtxt {
             None => {
                 self.anon_implies_rp
             }
-            Some(ref l) if l.ident == special_idents::static => {
+            Some(ref l) if l.ident == special_idents::statik => {
                 false
             }
             Some(ref l) if l.ident == special_idents::self_ => {
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 426df805b58..a7e590e359c 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -10,52 +10,16 @@
 
 use driver::session::Session;
 use metadata::csearch::{each_path, get_trait_method_def_ids};
-use metadata::csearch::get_method_name_and_self_ty;
+use metadata::csearch::get_method_name_and_explicit_self;
 use metadata::csearch::get_static_methods_if_impl;
 use metadata::csearch::get_type_name_if_impl;
 use metadata::cstore::find_extern_mod_stmt_cnum;
 use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
 use middle::lang_items::LanguageItems;
-use middle::lint::{allow, level, unused_imports};
-use middle::lint::{get_lint_level, get_lint_settings_level};
+use middle::lint::unused_imports;
 use middle::pat_util::pat_bindings;
 
-use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm};
-use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk};
-use syntax::ast::{bind_infer, bind_by_ref, bind_by_copy};
-use syntax::ast::{crate, decl_item, def, def_arg, def_binding};
-use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
-use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
-use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty};
-use syntax::ast::{def_ty_param, def_typaram_binder, def_trait};
-use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
-use syntax::ast::{expr_binary, expr_break, expr_field};
-use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
-use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
-use syntax::ast::{def_upvar, def_use, def_variant, div, eq};
-use syntax::ast::{expr, expr_again, expr_assign_op};
-use syntax::ast::{expr_index, expr_loop};
-use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl};
-use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge};
-use syntax::ast::Generics;
-use syntax::ast::{gt, ident, inherited, item, item_struct};
-use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod};
-use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le};
-use syntax::ast::{local, local_crate, lt, method, mul};
-use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident};
-use syntax::ast::{Path, pat_lit, pat_range, pat_struct};
-use syntax::ast::{prim_ty, private, provided};
-use syntax::ast::{public, required, rem, self_ty_, shl, shr, stmt_decl};
-use syntax::ast::{struct_field, struct_variant_kind};
-use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty};
-use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
-use syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, TyParam, ty_path};
-use syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint};
-use syntax::ast::unnamed_field;
-use syntax::ast::{variant, view_item, view_item_extern_mod};
-use syntax::ast::{view_item_use, view_path_glob, view_path_list};
-use syntax::ast::{view_path_simple, anonymous, named, not};
-use syntax::ast::{unsafe_fn};
+use syntax::ast::*;
 use syntax::ast_util::{def_id_of_def, local_def};
 use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
 use syntax::ast_util::{Privacy, Public, Private};
@@ -65,6 +29,7 @@ use syntax::parse::token::ident_interner;
 use syntax::parse::token::special_idents;
 use syntax::print::pprust::path_to_str;
 use syntax::codemap::{span, dummy_sp, BytePos};
+use syntax::visit::{mk_simple_visitor, default_simple_visitor, SimpleVisitor};
 use syntax::visit::{default_visitor, mk_vt, Visitor, visit_block};
 use syntax::visit::{visit_crate, visit_expr, visit_expr_opt};
 use syntax::visit::{visit_foreign_item, visit_item};
@@ -96,7 +61,7 @@ pub struct MethodInfo {
     did: def_id,
     n_tps: uint,
     ident: ident,
-    self_type: self_ty_
+    explicit_self: explicit_self_
 }
 
 pub struct Impl {
@@ -319,19 +284,21 @@ pub fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode)
         ForbidDuplicateModules | ForbidDuplicateTypes |
         ForbidDuplicateTypesAndValues => TypeNS,
         ForbidDuplicateValues => ValueNS,
-        OverwriteDuplicates => fail!(~"OverwriteDuplicates has no namespace")
+        OverwriteDuplicates => fail!("OverwriteDuplicates has no namespace")
     }
 }
 
 /// One local scope.
 pub struct Rib {
     bindings: @mut HashMap<ident,def_like>,
+    self_binding: @mut Option<def_like>,
     kind: RibKind,
 }
 
 pub fn Rib(kind: RibKind) -> Rib {
     Rib {
         bindings: @mut HashMap::new(),
+        self_binding: @mut None,
         kind: kind
     }
 }
@@ -343,18 +310,21 @@ pub struct ImportDirective {
     module_path: ~[ident],
     subclass: @ImportDirectiveSubclass,
     span: span,
+    id: node_id,
 }
 
 pub fn ImportDirective(privacy: Privacy,
                        module_path: ~[ident],
                        subclass: @ImportDirectiveSubclass,
-                       span: span)
+                       span: span,
+                       id: node_id)
                     -> ImportDirective {
     ImportDirective {
         privacy: privacy,
         module_path: module_path,
         subclass: subclass,
-        span: span
+        span: span,
+        id: id
     }
 }
 
@@ -378,7 +348,7 @@ pub struct ImportResolution {
     /// The privacy of this `use` directive (whether it's `use` or
     /// `pub use`.
     privacy: Privacy,
-    span: span,
+    id: node_id,
 
     // The number of outstanding references to this name. When this reaches
     // zero, outside modules can count on the targets being correct. Before
@@ -390,21 +360,16 @@ pub struct ImportResolution {
     value_target: Option<Target>,
     /// The type that this `use` directive names, if there is one.
     type_target: Option<Target>,
-
-    /// There exists one state per import statement
-    state: @mut ImportState,
 }
 
 pub fn ImportResolution(privacy: Privacy,
-                        span: span,
-                        state: @mut ImportState) -> ImportResolution {
+                        id: node_id) -> ImportResolution {
     ImportResolution {
         privacy: privacy,
-        span: span,
+        id: id,
         outstanding_references: 0,
         value_target: None,
         type_target: None,
-        state: state,
     }
 }
 
@@ -417,15 +382,6 @@ pub impl ImportResolution {
     }
 }
 
-pub struct ImportState {
-    used: bool,
-    warned: bool
-}
-
-pub fn ImportState() -> ImportState {
-    ImportState{ used: false, warned: false }
-}
-
 /// The link from a module up to its nearest parent node.
 pub enum ParentLink {
     NoParentLink,
@@ -510,13 +466,15 @@ pub impl Module {
 pub struct TypeNsDef {
     privacy: Privacy,
     module_def: Option<@mut Module>,
-    type_def: Option<def>
+    type_def: Option<def>,
+    type_span: Option<span>
 }
 
 // Records a possibly-private value definition.
 pub struct ValueNsDef {
     privacy: Privacy,
     def: def,
+    value_span: Option<span>,
 }
 
 // Records the definitions (at most one for each namespace) that a name is
@@ -524,11 +482,6 @@ pub struct ValueNsDef {
 pub struct NameBindings {
     type_def: Option<TypeNsDef>,    //< Meaning in type namespace.
     value_def: Option<ValueNsDef>,  //< Meaning in value namespace.
-
-    // For error reporting
-    // FIXME (#3783): Merge me into TypeNsDef and ValueNsDef.
-    type_span: Option<span>,
-    value_span: Option<span>,
 }
 
 pub impl NameBindings {
@@ -546,18 +499,19 @@ pub impl NameBindings {
                 self.type_def = Some(TypeNsDef {
                     privacy: privacy,
                     module_def: Some(module_),
-                    type_def: None
+                    type_def: None,
+                    type_span: Some(sp)
                 });
             }
             Some(copy type_def) => {
                 self.type_def = Some(TypeNsDef {
                     privacy: privacy,
                     module_def: Some(module_),
+                    type_span: Some(sp),
                     .. type_def
                 });
             }
         }
-        self.type_span = Some(sp);
     }
 
     /// Records a type definition.
@@ -568,24 +522,24 @@ pub impl NameBindings {
                 self.type_def = Some(TypeNsDef {
                     privacy: privacy,
                     module_def: None,
-                    type_def: Some(def)
+                    type_def: Some(def),
+                    type_span: Some(sp)
                 });
             }
             Some(copy type_def) => {
                 self.type_def = Some(TypeNsDef {
                     privacy: privacy,
                     type_def: Some(def),
+                    type_span: Some(sp),
                     .. type_def
                 });
             }
         }
-        self.type_span = Some(sp);
     }
 
     /// Records a value definition.
     fn define_value(@mut self, privacy: Privacy, def: def, sp: span) {
-        self.value_def = Some(ValueNsDef { privacy: privacy, def: def });
-        self.value_span = Some(sp);
+        self.value_def = Some(ValueNsDef { privacy: privacy, def: def, value_span: Some(sp) });
     }
 
     /// Returns the module node if applicable.
@@ -603,7 +557,7 @@ pub impl NameBindings {
     fn get_module(@mut self) -> @mut Module {
         match self.get_module_if_available() {
             None => {
-                fail!(~"get_module called on a node with no module \
+                fail!("get_module called on a node with no module \
                        definition!")
             }
             Some(module_def) => module_def
@@ -684,8 +638,18 @@ pub impl NameBindings {
     fn span_for_namespace(&self, namespace: Namespace) -> Option<span> {
         if self.defined_in_namespace(namespace) {
             match namespace {
-                TypeNS  => self.type_span,
-                ValueNS => self.value_span,
+                TypeNS  => {
+                    match self.type_def {
+                        None => None,
+                        Some(type_def) => type_def.type_span
+                    }
+                }
+                ValueNS => {
+                    match self.value_def {
+                        None => None,
+                        Some(value_def) => value_def.value_span
+                    }
+                }
             }
         } else {
             None
@@ -696,9 +660,7 @@ pub impl NameBindings {
 pub fn NameBindings() -> NameBindings {
     NameBindings {
         type_def: None,
-        value_def: None,
-        type_span: None,
-        value_span: None
+        value_def: None
     }
 }
 
@@ -762,7 +724,7 @@ pub fn Resolver(session: Session,
 
     let current_module = graph_root.get_module();
 
-    let self = Resolver {
+    let this = Resolver {
         session: @session,
         lang_items: copy lang_items,
         crate: crate,
@@ -796,11 +758,12 @@ pub fn Resolver(session: Session,
         def_map: @mut HashMap::new(),
         export_map2: @mut HashMap::new(),
         trait_map: HashMap::new(),
+        used_imports: HashSet::new(),
 
         intr: session.intr()
     };
 
-    self
+    this
 }
 
 /// The main resolver class.
@@ -853,6 +816,8 @@ pub struct Resolver {
     def_map: DefMap,
     export_map2: ExportMap2,
     trait_map: TraitMap,
+
+    used_imports: HashSet<node_id>,
 }
 
 pub impl Resolver {
@@ -870,7 +835,7 @@ pub impl Resolver {
         self.resolve_crate();
         self.session.abort_if_errors();
 
-        self.check_for_unused_imports_if_necessary();
+        self.check_for_unused_imports();
     }
 
     //
@@ -1201,7 +1166,7 @@ pub impl Resolver {
                 // Bail out early if there are no static methods.
                 let mut has_static_methods = false;
                 for methods.each |method| {
-                    match method.self_ty.node {
+                    match method.explicit_self.node {
                         sty_static => has_static_methods = true,
                         _ => {}
                     }
@@ -1234,7 +1199,7 @@ pub impl Resolver {
 
                         // For each static method...
                         for methods.each |method| {
-                            match method.self_ty.node {
+                            match method.explicit_self.node {
                                 sty_static => {
                                     // Add the static method to the
                                     // module.
@@ -1272,7 +1237,7 @@ pub impl Resolver {
                 let mut has_static_methods = false;
                 for (*methods).each |method| {
                     let ty_m = trait_method_to_ty_method(method);
-                    match ty_m.self_ty.node {
+                    match ty_m.explicit_self.node {
                         sty_static => {
                             has_static_methods = true;
                             break;
@@ -1304,7 +1269,7 @@ pub impl Resolver {
                     let ident = ty_m.ident;
                     // Add it to the trait info if not static,
                     // add it as a name in the trait module otherwise.
-                    match ty_m.self_ty.node {
+                    match ty_m.explicit_self.node {
                         sty_static => {
                             let def = def_static_method(
                                 local_def(ty_m.id),
@@ -1334,7 +1299,7 @@ pub impl Resolver {
             }
 
             item_mac(*) => {
-                fail!(~"item macros unimplemented")
+                fail!("item macros unimplemented")
             }
         }
     }
@@ -1415,7 +1380,7 @@ pub impl Resolver {
                     // Build up the import directives.
                     let module_ = self.get_module_from_parent(parent);
                     match view_path.node {
-                        view_path_simple(binding, full_path, _) => {
+                        view_path_simple(binding, full_path, id) => {
                             let source_ident = *full_path.idents.last();
                             let subclass = @SingleImport(binding,
                                                          source_ident);
@@ -1423,7 +1388,8 @@ pub impl Resolver {
                                                         module_,
                                                         module_path,
                                                         subclass,
-                                                        view_path.span);
+                                                        view_path.span,
+                                                        id);
                         }
                         view_path_list(_, ref source_idents, _) => {
                             for source_idents.each |source_ident| {
@@ -1433,15 +1399,17 @@ pub impl Resolver {
                                                             module_,
                                                             copy module_path,
                                                             subclass,
-                                                            source_ident.span);
+                                                            source_ident.span,
+                                                            source_ident.node.id);
                             }
                         }
-                        view_path_glob(_, _) => {
+                        view_path_glob(_, id) => {
                             self.build_import_directive(privacy,
                                                         module_,
                                                         module_path,
                                                         @GlobImport,
-                                                        view_path.span);
+                                                        view_path.span,
+                                                        id);
                         }
                     }
                 }
@@ -1566,16 +1534,13 @@ pub impl Resolver {
                     // avoid creating cycles in the
                     // module graph.
 
-                    let resolution =
-                        @mut ImportResolution(Public,
-                                              dummy_sp(),
-                                              @mut ImportState());
+                    let resolution = @mut ImportResolution(Public, 0);
                     resolution.outstanding_references = 0;
 
                     match existing_module.parent_link {
                       NoParentLink |
                       BlockParentLink(*) => {
-                        fail!(~"can't happen");
+                        fail!("can't happen");
                       }
                       ModuleParentLink(parent_module, ident) => {
                         let name_bindings = parent_module.children.get(
@@ -1610,9 +1575,9 @@ pub impl Resolver {
                                                             def_id);
               let mut interned_method_names = HashSet::new();
               for method_def_ids.each |&method_def_id| {
-                  let (method_name, self_ty) =
-                      get_method_name_and_self_ty(self.session.cstore,
-                                                  method_def_id);
+                  let (method_name, explicit_self) =
+                      get_method_name_and_explicit_self(self.session.cstore,
+                                                        method_def_id);
 
                   debug!("(building reduced graph for \
                           external crate) ... adding \
@@ -1620,7 +1585,7 @@ pub impl Resolver {
                          *self.session.str_of(method_name));
 
                   // Add it to the trait info if not static.
-                  if self_ty != sty_static {
+                  if explicit_self != sty_static {
                       interned_method_names.insert(method_name);
                   }
               }
@@ -1645,7 +1610,7 @@ pub impl Resolver {
           def_prim_ty(*) | def_ty_param(*) | def_binding(*) |
           def_use(*) | def_upvar(*) | def_region(*) |
           def_typaram_binder(*) | def_label(*) | def_self_ty(*) => {
-            fail!(fmt!("didn't expect `%?`", def));
+            fail!("didn't expect `%?`", def);
           }
         }
     }
@@ -1831,9 +1796,10 @@ pub impl Resolver {
                               module_: @mut Module,
                               module_path: ~[ident],
                               subclass: @ImportDirectiveSubclass,
-                              span: span) {
+                              span: span,
+                              id: node_id) {
         let directive = @ImportDirective(privacy, module_path,
-                                         subclass, span);
+                                         subclass, span, id);
         module_.imports.push(directive);
 
         // Bump the reference count on the name. Or, if this is a glob, set
@@ -1855,16 +1821,7 @@ pub impl Resolver {
                     }
                     None => {
                         debug!("(building import directive) creating new");
-                        let state = @mut ImportState();
-                        let resolution = @mut ImportResolution(privacy,
-                                                               span,
-                                                               state);
-                        let name = self.idents_to_str(directive.module_path);
-                        // Don't warn about unused intrinsics because they're
-                        // automatically appended to all files
-                        if name == ~"intrinsic::rusti" {
-                            resolution.state.warned = true;
-                        }
+                        let resolution = @mut ImportResolution(privacy, id);
                         resolution.outstanding_references = 1;
                         module_.import_resolutions.insert(target, resolution);
                     }
@@ -2056,16 +2013,16 @@ pub impl Resolver {
                             self.resolve_single_import(module_,
                                                        containing_module,
                                                        target,
-                                                       source);
+                                                       source,
+                                                       import_directive.span);
                     }
                     GlobImport => {
-                        let span = import_directive.span;
                         let privacy = import_directive.privacy;
                         resolution_result =
                             self.resolve_glob_import(privacy,
                                                      module_,
                                                      containing_module,
-                                                     span);
+                                                     import_directive.id);
                     }
                 }
             }
@@ -2108,10 +2065,9 @@ pub impl Resolver {
                 privacy: Public,
                 module_def: Some(module),
                 type_def: None,
+                type_span: None
             }),
             value_def: None,
-            type_span: None,
-            value_span: None,
         }
     }
 
@@ -2119,7 +2075,8 @@ pub impl Resolver {
                              module_: @mut Module,
                              containing_module: @mut Module,
                              target: ident,
-                             source: ident)
+                             source: ident,
+                             span: span)
                           -> ResolveResult<()> {
         debug!("(resolving single import) resolving `%s` = `%s::%s` from \
                 `%s`",
@@ -2192,7 +2149,8 @@ pub impl Resolver {
                             if import_resolution.outstanding_references
                                 == 0 => {
 
-                        fn get_binding(import_resolution:
+                        fn get_binding(this: @mut Resolver,
+                                       import_resolution:
                                           @mut ImportResolution,
                                        namespace: Namespace)
                                     -> NamespaceResult {
@@ -2209,7 +2167,7 @@ pub impl Resolver {
                                     return UnboundResult;
                                 }
                                 Some(target) => {
-                                    import_resolution.state.used = true;
+                                    this.used_imports.insert(import_resolution.id);
                                     return BoundResult(target.target_module,
                                                     target.bindings);
                                 }
@@ -2219,11 +2177,11 @@ pub impl Resolver {
                         // The name is an import which has been fully
                         // resolved. We can, therefore, just follow it.
                         if value_result.is_unknown() {
-                            value_result = get_binding(*import_resolution,
+                            value_result = get_binding(self, *import_resolution,
                                                        ValueNS);
                         }
                         if type_result.is_unknown() {
-                            type_result = get_binding(*import_resolution,
+                            type_result = get_binding(self, *import_resolution,
                                                       TypeNS);
                         }
                     }
@@ -2267,7 +2225,7 @@ pub impl Resolver {
             }
             UnboundResult => { /* Continue. */ }
             UnknownResult => {
-                fail!(~"value result should be known at this point");
+                fail!("value result should be known at this point");
             }
         }
         match type_result {
@@ -2277,22 +2235,24 @@ pub impl Resolver {
             }
             UnboundResult => { /* Continue. */ }
             UnknownResult => {
-                fail!(~"type result should be known at this point");
+                fail!("type result should be known at this point");
             }
         }
 
         let i = import_resolution;
+        let mut resolve_fail = false;
+        let mut priv_fail = false;
         match (i.value_target, i.type_target) {
             // If this name wasn't found in either namespace, it's definitely
             // unresolved.
-            (None, None) => { return Failed; }
+            (None, None) => { resolve_fail = true; }
             // If it's private, it's also unresolved.
             (Some(t), None) | (None, Some(t)) => {
                 let bindings = &mut *t.bindings;
                 match bindings.type_def {
                     Some(ref type_def) => {
                         if type_def.privacy == Private {
-                            return Failed;
+                            priv_fail = true;
                         }
                     }
                     _ => ()
@@ -2300,7 +2260,7 @@ pub impl Resolver {
                 match bindings.value_def {
                     Some(ref value_def) => {
                         if value_def.privacy == Private {
-                            return Failed;
+                            priv_fail = true;
                         }
                     }
                     _ => ()
@@ -2313,13 +2273,25 @@ pub impl Resolver {
                     (Some(ref value_def), Some(ref type_def)) =>
                         if value_def.privacy == Private
                             && type_def.privacy == Private {
-                            return Failed;
+                                priv_fail = true;
                         },
                     _ => ()
                 }
             }
         }
 
+        if resolve_fail {
+            self.session.span_err(span, fmt!("unresolved import: there is no `%s` in `%s`",
+                                             *self.session.str_of(source),
+                                             self.module_to_str(containing_module)));
+            return Failed;
+        } else if priv_fail {
+            self.session.span_err(span, fmt!("unresolved import: found `%s` in `%s` but it is \
+                                             private", *self.session.str_of(source),
+                                             self.module_to_str(containing_module)));
+            return Failed;
+        }
+
         assert!(import_resolution.outstanding_references >= 1);
         import_resolution.outstanding_references -= 1;
 
@@ -2334,13 +2306,12 @@ pub impl Resolver {
                            privacy: Privacy,
                            module_: @mut Module,
                            containing_module: @mut Module,
-                           span: span)
+                           id: node_id)
                         -> ResolveResult<()> {
         // This function works in a highly imperative manner; it eagerly adds
         // everything it can to the list of import resolutions of the module
         // node.
         debug!("(resolving glob import) resolving %? glob import", privacy);
-        let state = @mut ImportState();
 
         // We must bail out if the node has unresolved imports of any kind
         // (including globs).
@@ -2366,9 +2337,7 @@ pub impl Resolver {
                 None if target_import_resolution.privacy == Public => {
                     // Simple: just copy the old import resolution.
                     let new_import_resolution =
-                        @mut ImportResolution(privacy,
-                                              target_import_resolution.span,
-                                              state);
+                        @mut ImportResolution(privacy, id);
                     new_import_resolution.value_target =
                         copy target_import_resolution.value_target;
                     new_import_resolution.type_target =
@@ -2410,9 +2379,7 @@ pub impl Resolver {
             match module_.import_resolutions.find(&ident) {
                 None => {
                     // Create a new import resolution from this child.
-                    dest_import_resolution = @mut ImportResolution(privacy,
-                                                                   span,
-                                                                   state);
+                    dest_import_resolution = @mut ImportResolution(privacy, id);
                     module_.import_resolutions.insert
                         (ident, dest_import_resolution);
                 }
@@ -2491,7 +2458,8 @@ pub impl Resolver {
                                                                     *segment_name));
                         return Failed;
                     }
-                    self.session.span_err(span, ~"unresolved name");
+                    self.session.span_err(span, fmt!("unresolved import: could not find `%s` in \
+                                                     `%s`.", *segment_name, module_name));
                     return Failed;
                 }
                 Indeterminate => {
@@ -2576,7 +2544,18 @@ pub impl Resolver {
         let start_index;
         match module_prefix_result {
             Failed => {
-                self.session.span_err(span, ~"unresolved name");
+                let mpath = self.idents_to_str(module_path);
+                match str::rfind(self.idents_to_str(module_path), |c| { c == ':' }) {
+                    Some(idx) => {
+                        self.session.span_err(span, fmt!("unresolved import: could not find `%s` \
+                                                         in `%s`", str::substr(mpath, idx,
+                                                                               mpath.len() - idx),
+                                                         // idx - 1 to account for the extra
+                                                         // colon
+                                                         str::substr(mpath, 0, idx - 1)));
+                    },
+                    None => (),
+                };
                 return Failed;
             }
             Indeterminate => {
@@ -2678,7 +2657,7 @@ pub impl Resolver {
                     Some(target) => {
                         debug!("(resolving item in lexical scope) using \
                                 import resolution");
-                        import_resolution.state.used = true;
+                        self.used_imports.insert(import_resolution.id);
                         return Success(copy target);
                     }
                 }
@@ -2949,7 +2928,7 @@ pub impl Resolver {
                             import_resolution.privacy == Public => {
                         debug!("(resolving name in module) resolved to \
                                 import");
-                        import_resolution.state.used = true;
+                        self.used_imports.insert(import_resolution.id);
                         return Success(copy target);
                     }
                     Some(_) => {
@@ -3556,7 +3535,7 @@ pub impl Resolver {
             }
 
           item_mac(*) => {
-            fail!(~"item macros unimplemented")
+            fail!("item macros unimplemented")
           }
         }
 
@@ -3654,8 +3633,7 @@ pub impl Resolver {
                 HasSelfBinding(self_node_id, is_implicit) => {
                     let def_like = dl_def(def_self(self_node_id,
                                                    is_implicit));
-                    (*function_value_rib).bindings.insert(self.self_ident,
-                                                          def_like);
+                    *function_value_rib.self_binding = Some(def_like);
                 }
             }
 
@@ -3698,14 +3676,20 @@ pub impl Resolver {
                                type_parameters: &OptVec<TyParam>,
                                visitor: ResolveVisitor) {
         for type_parameters.each |type_parameter| {
-            for type_parameter.bounds.each |&bound| {
-                match bound {
-                    TraitTyParamBound(tref) => {
-                        self.resolve_trait_reference(tref, visitor)
-                    }
-                    RegionTyParamBound => {}
-                }
+            for type_parameter.bounds.each |bound| {
+                self.resolve_type_parameter_bound(bound, visitor);
+            }
+        }
+    }
+
+    fn resolve_type_parameter_bound(@mut self,
+                                    type_parameter_bound: &TyParamBound,
+                                    visitor: ResolveVisitor) {
+        match *type_parameter_bound {
+            TraitTyParamBound(tref) => {
+                self.resolve_trait_reference(tref, visitor)
             }
+            RegionTyParamBound => {}
         }
     }
 
@@ -3758,7 +3742,7 @@ pub impl Resolver {
                               outer_type_parameter_count,
                               rib_kind);
         // we only have self ty if it is a non static method
-        let self_binding = match method.self_ty.node {
+        let self_binding = match method.explicit_self.node {
           sty_static => { NoSelfBinding }
           _ => { HasSelfBinding(method.self_id, false) }
         };
@@ -4036,6 +4020,13 @@ pub impl Resolver {
                 }
             }
 
+            ty_closure(c) => {
+                for c.bounds.each |bound| {
+                    self.resolve_type_parameter_bound(bound, visitor);
+                }
+                visit_ty(ty, (), visitor);
+            }
+
             _ => {
                 // Just resolve embedded types.
                 visit_ty(ty, (), visitor);
@@ -4294,7 +4285,7 @@ pub impl Resolver {
             Success(target) => {
                 match target.bindings.value_def {
                     None => {
-                        fail!(~"resolved name in the value namespace to a \
+                        fail!("resolved name in the value namespace to a \
                               set of name bindings with no def?!");
                     }
                     Some(def) => {
@@ -4314,7 +4305,7 @@ pub impl Resolver {
             }
 
             Indeterminate => {
-                fail!(~"unexpected indeterminate result");
+                fail!("unexpected indeterminate result");
             }
 
             Failed => {
@@ -4418,7 +4409,7 @@ pub impl Resolver {
                                     namespace)) {
                             (Some(def), Some(Public)) => {
                                 // Found it.
-                                import_resolution.state.used = true;
+                                self.used_imports.insert(import_resolution.id);
                                 return ImportNameDefinition(def);
                             }
                             (Some(_), _) | (None, _) => {
@@ -4485,7 +4476,7 @@ pub impl Resolver {
             }
 
             Indeterminate => {
-                fail!(~"indeterminate unexpected");
+                fail!("indeterminate unexpected");
             }
 
             Success(resulting_module) => {
@@ -4534,7 +4525,7 @@ pub impl Resolver {
             }
 
             Indeterminate => {
-                fail!(~"indeterminate unexpected");
+                fail!("indeterminate unexpected");
             }
 
             Success(resulting_module) => {
@@ -4561,7 +4552,7 @@ pub impl Resolver {
                                         ident: ident,
                                         namespace: Namespace,
                                         span: span)
-                                     -> Option<def> {
+                                        -> Option<def> {
         // Check the local set of ribs.
         let search_result;
         match namespace {
@@ -4590,6 +4581,35 @@ pub impl Resolver {
         }
     }
 
+    fn resolve_self_value_in_local_ribs(@mut self, span: span)
+                                        -> Option<def> {
+        // FIXME #4950: This should not use a while loop.
+        let ribs = &mut self.value_ribs;
+        let mut i = ribs.len();
+        while i != 0 {
+            i -= 1;
+            match *ribs[i].self_binding {
+                Some(def_like) => {
+                    match self.upvarify(*ribs,
+                                        i,
+                                        def_like,
+                                        span,
+                                        DontAllowCapturingSelf) {
+                        Some(dl_def(def)) => return Some(def),
+                        _ => {
+                            self.session.span_bug(span,
+                                                  ~"self wasn't mapped to a \
+                                                    def?!")
+                        }
+                    }
+                }
+                None => {}
+            }
+        }
+
+        None
+    }
+
     fn resolve_item_by_identifier_in_lexical_scope(@mut self,
                                                    ident: ident,
                                                    namespace: Namespace)
@@ -4615,7 +4635,7 @@ pub impl Resolver {
                 }
             }
             Indeterminate => {
-                fail!(~"unexpected indeterminate result");
+                fail!("unexpected indeterminate result");
             }
             Failed => {
                 return None;
@@ -4648,7 +4668,7 @@ pub impl Resolver {
             }
         }
 
-        if vec::len(values) > 0 &&
+        if values.len() > 0 &&
             values[smallest] != uint::max_value &&
             values[smallest] < str::len(name) + 2 &&
             values[smallest] <= max_distance &&
@@ -4804,12 +4824,25 @@ pub impl Resolver {
                                                    `%s`",
                                                    *self.session.str_of(
                                                        label))),
-                    Some(dl_def(def @ def_label(_))) =>
-                        self.record_def(expr.id, def),
-                    Some(_) =>
+                    Some(dl_def(def @ def_label(_))) => {
+                        self.record_def(expr.id, def)
+                    }
+                    Some(_) => {
                         self.session.span_bug(expr.span,
                                               ~"label wasn't mapped to a \
                                                 label def!")
+                    }
+                }
+            }
+
+            expr_self => {
+                match self.resolve_self_value_in_local_ribs(expr.span) {
+                    None => {
+                        self.session.span_err(expr.span,
+                                              ~"`self` is not allowed in \
+                                                this context")
+                    }
+                    Some(def) => self.record_def(expr.id, def),
                 }
             }
 
@@ -4956,8 +4989,8 @@ pub impl Resolver {
                                             &mut found_traits,
                                             trait_def_id, name);
                                         if added {
-                                            import_resolution.state.used =
-                                                true;
+                                            self.used_imports.insert(
+                                                import_resolution.id);
                                         }
                                     }
                                     _ => {
@@ -5055,86 +5088,50 @@ pub impl Resolver {
     // resolve data structures.
     //
 
-    fn unused_import_lint_level(@mut self, m: @mut Module) -> level {
-        let settings = self.session.lint_settings;
-        match m.def_id {
-            Some(def) => get_lint_settings_level(settings, unused_imports,
-                                                 def.node, def.node),
-            None => get_lint_level(settings.default_settings, unused_imports)
-        }
-    }
-
-    fn check_for_unused_imports_if_necessary(@mut self) {
-        if self.unused_import_lint_level(self.current_module) == allow {
-            return;
-        }
-
-        let root_module = self.graph_root.get_module();
-        self.check_for_unused_imports_in_module_subtree(root_module);
+    fn check_for_unused_imports(@mut self) {
+        let vt = mk_simple_visitor(@SimpleVisitor {
+            visit_view_item: |vi| self.check_for_item_unused_imports(vi),
+            .. *default_simple_visitor()
+        });
+        visit_crate(self.crate, (), vt);
     }
 
-    fn check_for_unused_imports_in_module_subtree(@mut self,
-                                                  module_: @mut Module) {
-        // If this isn't a local crate, then bail out. We don't need to check
-        // for unused imports in external crates.
-
-        match module_.def_id {
-            Some(def_id) if def_id.crate == local_crate => {
-                // OK. Continue.
-            }
-            None => {
-                // Check for unused imports in the root module.
-            }
-            Some(_) => {
-                // Bail out.
-                debug!("(checking for unused imports in module subtree) not \
-                        checking for unused imports for `%s`",
-                       self.module_to_str(module_));
-                return;
-            }
-        }
-
-        self.check_for_unused_imports_in_module(module_);
+    fn check_for_item_unused_imports(&mut self, vi: @view_item) {
+        // Ignore public import statements because there's no way to be sure
+        // whether they're used or not. Also ignore imports with a dummy span
+        // because this means that they were generated in some fashion by the
+        // compiler and we don't need to consider them.
+        if vi.vis == public { return }
+        if vi.span == dummy_sp() { return }
+
+        match vi.node {
+            view_item_extern_mod(*) => {} // ignore
+            view_item_use(ref path) => {
+                for path.each |p| {
+                    match p.node {
+                        view_path_simple(_, _, id) | view_path_glob(_, id) => {
+                            if !self.used_imports.contains(&id) {
+                                self.session.add_lint(unused_imports,
+                                                      id, vi.span,
+                                                      ~"unused import");
+                            }
+                        }
 
-        for module_.children.each_value |&child_name_bindings| {
-            match (*child_name_bindings).get_module_if_available() {
-                None => {
-                    // Nothing to do.
-                }
-                Some(child_module) => {
-                    self.check_for_unused_imports_in_module_subtree
-                        (child_module);
+                        view_path_list(_, ref list, _) => {
+                            for list.each |i| {
+                                if !self.used_imports.contains(&i.node.id) {
+                                    self.session.add_lint(unused_imports,
+                                                          i.node.id, i.span,
+                                                          ~"unused import");
+                                }
+                            }
+                        }
+                    }
                 }
             }
         }
-
-        for module_.anonymous_children.each_value |&child_module| {
-            self.check_for_unused_imports_in_module_subtree(child_module);
-        }
-    }
-
-    fn check_for_unused_imports_in_module(@mut self, module_: @mut Module) {
-        for module_.import_resolutions.each_value |&import_resolution| {
-            // Ignore dummy spans for things like automatically injected
-            // imports for the prelude, and also don't warn about the same
-            // import statement being unused more than once. Furthermore, if
-            // the import is public, then we can't be sure whether it's unused
-            // or not so don't warn about it.
-            if !import_resolution.state.used &&
-                    !import_resolution.state.warned &&
-                    import_resolution.span != dummy_sp() &&
-                    import_resolution.privacy != Public {
-                import_resolution.state.warned = true;
-                let span = import_resolution.span;
-                self.session.span_lint_level(
-                    self.unused_import_lint_level(module_),
-                    span,
-                    ~"unused import");
-            }
-        }
     }
 
-
     //
     // Diagnostics
     //
diff --git a/src/librustc/middle/resolve_stage0.rs b/src/librustc/middle/resolve_stage0.rs
index 4fd2e967083..713132b12fc 100644
--- a/src/librustc/middle/resolve_stage0.rs
+++ b/src/librustc/middle/resolve_stage0.rs
@@ -11,14 +11,13 @@
 use driver::session;
 use driver::session::Session;
 use metadata::csearch::{each_path, get_trait_method_def_ids};
-use metadata::csearch::get_method_name_and_self_ty;
+use metadata::csearch::get_method_name_and_explicit_self;
 use metadata::csearch::get_static_methods_if_impl;
 use metadata::csearch::get_type_name_if_impl;
 use metadata::cstore::find_extern_mod_stmt_cnum;
 use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
 use middle::lang_items::LanguageItems;
-use middle::lint::{allow, level, unused_imports};
-use middle::lint::{get_lint_level, get_lint_settings_level};
+use middle::lint::{allow, level, warn};
 use middle::pat_util::pat_bindings;
 
 use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm};
@@ -36,7 +35,7 @@ use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
 use syntax::ast::{def_upvar, def_use, def_variant, div, eq};
 use syntax::ast::{expr, expr_again, expr_assign_op};
 use syntax::ast::{expr_index, expr_loop};
-use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl};
+use syntax::ast::{expr_path, expr_self, expr_struct, expr_unary, fn_decl};
 use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge};
 use syntax::ast::Generics;
 use syntax::ast::{gt, ident, inherited, item, item_struct};
@@ -46,7 +45,7 @@ use syntax::ast::{local, local_crate, lt, method, mul};
 use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident};
 use syntax::ast::{Path, pat_lit, pat_range, pat_struct};
 use syntax::ast::{prim_ty, private, provided};
-use syntax::ast::{public, required, rem, self_ty_, shl, shr, stmt_decl};
+use syntax::ast::{public, required, rem, explicit_self_, shl, shr, stmt_decl};
 use syntax::ast::{struct_field, struct_variant_kind};
 use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty};
 use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
@@ -97,7 +96,7 @@ pub struct MethodInfo {
     did: def_id,
     n_tps: uint,
     ident: ident,
-    self_type: self_ty_
+    explicit_self: explicit_self_
 }
 
 pub struct Impl {
@@ -320,19 +319,21 @@ pub fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode)
         ForbidDuplicateModules | ForbidDuplicateTypes |
         ForbidDuplicateTypesAndValues => TypeNS,
         ForbidDuplicateValues => ValueNS,
-        OverwriteDuplicates => fail!(~"OverwriteDuplicates has no namespace")
+        OverwriteDuplicates => fail!("OverwriteDuplicates has no namespace")
     }
 }
 
 /// One local scope.
 pub struct Rib {
     bindings: @mut HashMap<ident,def_like>,
+    self_binding: @mut Option<def_like>,
     kind: RibKind,
 }
 
 pub fn Rib(kind: RibKind) -> Rib {
     Rib {
         bindings: @mut HashMap::new(),
+        self_binding: @mut None,
         kind: kind
     }
 }
@@ -604,7 +605,7 @@ pub impl NameBindings {
     fn get_module(@mut self) -> @mut Module {
         match self.get_module_if_available() {
             None => {
-                fail!(~"get_module called on a node with no module \
+                fail!("get_module called on a node with no module \
                        definition!")
             }
             Some(module_def) => module_def
@@ -763,7 +764,7 @@ pub fn Resolver(session: Session,
 
     let current_module = graph_root.get_module();
 
-    let self = Resolver {
+    let this = Resolver {
         session: @session,
         lang_items: copy lang_items,
         crate: crate,
@@ -806,7 +807,7 @@ pub fn Resolver(session: Session,
         intr: session.intr()
     };
 
-    self
+    this
 }
 
 /// The main resolver class.
@@ -1217,7 +1218,7 @@ pub impl Resolver {
                 // Bail out early if there are no static methods.
                 let mut has_static_methods = false;
                 for methods.each |method| {
-                    match method.self_ty.node {
+                    match method.explicit_self.node {
                         sty_static => has_static_methods = true,
                         _ => {}
                     }
@@ -1250,7 +1251,7 @@ pub impl Resolver {
 
                         // For each static method...
                         for methods.each |method| {
-                            match method.self_ty.node {
+                            match method.explicit_self.node {
                                 sty_static => {
                                     // Add the static method to the
                                     // module.
@@ -1288,7 +1289,7 @@ pub impl Resolver {
                 let mut has_static_methods = false;
                 for (*methods).each |method| {
                     let ty_m = trait_method_to_ty_method(method);
-                    match ty_m.self_ty.node {
+                    match ty_m.explicit_self.node {
                         sty_static => {
                             has_static_methods = true;
                             break;
@@ -1320,7 +1321,7 @@ pub impl Resolver {
                     let ident = ty_m.ident;
                     // Add it to the trait info if not static,
                     // add it as a name in the trait module otherwise.
-                    match ty_m.self_ty.node {
+                    match ty_m.explicit_self.node {
                         sty_static => {
                             let def = def_static_method(
                                 local_def(ty_m.id),
@@ -1350,7 +1351,7 @@ pub impl Resolver {
             }
 
             item_mac(*) => {
-                fail!(~"item macros unimplemented")
+                fail!("item macros unimplemented")
             }
         }
     }
@@ -1591,7 +1592,7 @@ pub impl Resolver {
                     match existing_module.parent_link {
                       NoParentLink |
                       BlockParentLink(*) => {
-                        fail!(~"can't happen");
+                        fail!("can't happen");
                       }
                       ModuleParentLink(parent_module, ident) => {
                         let name_bindings = parent_module.children.get(
@@ -1626,9 +1627,9 @@ pub impl Resolver {
                                                             def_id);
               let mut interned_method_names = HashSet::new();
               for method_def_ids.each |&method_def_id| {
-                  let (method_name, self_ty) =
-                      get_method_name_and_self_ty(self.session.cstore,
-                                                  method_def_id);
+                  let (method_name, explicit_self) =
+                      get_method_name_and_explicit_self(self.session.cstore,
+                                                        method_def_id);
 
                   debug!("(building reduced graph for \
                           external crate) ... adding \
@@ -1636,7 +1637,7 @@ pub impl Resolver {
                          *self.session.str_of(method_name));
 
                   // Add it to the trait info if not static.
-                  if self_ty != sty_static {
+                  if explicit_self != sty_static {
                       interned_method_names.insert(method_name);
                   }
               }
@@ -1661,7 +1662,7 @@ pub impl Resolver {
           def_prim_ty(*) | def_ty_param(*) | def_binding(*) |
           def_use(*) | def_upvar(*) | def_region(*) |
           def_typaram_binder(*) | def_label(*) | def_self_ty(*) => {
-            fail!(fmt!("didn't expect `%?`", def));
+            fail!("didn't expect `%?`", def);
           }
         }
     }
@@ -2284,7 +2285,7 @@ pub impl Resolver {
             }
             UnboundResult => { /* Continue. */ }
             UnknownResult => {
-                fail!(~"value result should be known at this point");
+                fail!("value result should be known at this point");
             }
         }
         match type_result {
@@ -2294,7 +2295,7 @@ pub impl Resolver {
             }
             UnboundResult => { /* Continue. */ }
             UnknownResult => {
-                fail!(~"type result should be known at this point");
+                fail!("type result should be known at this point");
             }
         }
 
@@ -3597,7 +3598,7 @@ pub impl Resolver {
             }
 
           item_mac(*) => {
-            fail!(~"item macros unimplemented")
+            fail!("item macros unimplemented")
           }
         }
 
@@ -3695,8 +3696,7 @@ pub impl Resolver {
                 HasSelfBinding(self_node_id, is_implicit) => {
                     let def_like = dl_def(def_self(self_node_id,
                                                    is_implicit));
-                    (*function_value_rib).bindings.insert(self.self_ident,
-                                                          def_like);
+                    *function_value_rib.self_binding = Some(def_like);
                 }
             }
 
@@ -3799,7 +3799,7 @@ pub impl Resolver {
                               outer_type_parameter_count,
                               rib_kind);
         // we only have self ty if it is a non static method
-        let self_binding = match method.self_ty.node {
+        let self_binding = match method.explicit_self.node {
           sty_static => { NoSelfBinding }
           _ => { HasSelfBinding(method.self_id, false) }
         };
@@ -4336,7 +4336,7 @@ pub impl Resolver {
             Success(target) => {
                 match target.bindings.value_def {
                     None => {
-                        fail!(~"resolved name in the value namespace to a \
+                        fail!("resolved name in the value namespace to a \
                               set of name bindings with no def?!");
                     }
                     Some(def) => {
@@ -4356,7 +4356,7 @@ pub impl Resolver {
             }
 
             Indeterminate => {
-                fail!(~"unexpected indeterminate result");
+                fail!("unexpected indeterminate result");
             }
 
             Failed => {
@@ -4527,7 +4527,7 @@ pub impl Resolver {
             }
 
             Indeterminate => {
-                fail!(~"indeterminate unexpected");
+                fail!("indeterminate unexpected");
             }
 
             Success(resulting_module) => {
@@ -4576,7 +4576,7 @@ pub impl Resolver {
             }
 
             Indeterminate => {
-                fail!(~"indeterminate unexpected");
+                fail!("indeterminate unexpected");
             }
 
             Success(resulting_module) => {
@@ -4603,7 +4603,7 @@ pub impl Resolver {
                                         ident: ident,
                                         namespace: Namespace,
                                         span: span)
-                                     -> Option<def> {
+                                        -> Option<def> {
         // Check the local set of ribs.
         let search_result;
         match namespace {
@@ -4632,6 +4632,35 @@ pub impl Resolver {
         }
     }
 
+    fn resolve_self_value_in_local_ribs(@mut self, span: span)
+                                        -> Option<def> {
+        // FIXME #4950: This should not use a while loop.
+        let ribs = &mut self.value_ribs;
+        let mut i = ribs.len();
+        while i != 0 {
+            i -= 1;
+            match *ribs[i].self_binding {
+                Some(def_like) => {
+                    match self.upvarify(ribs,
+                                        i,
+                                        def_like,
+                                        span,
+                                        DontAllowCapturingSelf) {
+                        Some(dl_def(def)) => return Some(def),
+                        _ => {
+                            self.session.span_bug(span,
+                                                  ~"self wasn't mapped to a \
+                                                    def?!")
+                        }
+                    }
+                }
+                None => {}
+            }
+        }
+
+        None
+    }
+
     fn resolve_item_by_identifier_in_lexical_scope(@mut self,
                                                    ident: ident,
                                                    namespace: Namespace)
@@ -4657,7 +4686,7 @@ pub impl Resolver {
                 }
             }
             Indeterminate => {
-                fail!(~"unexpected indeterminate result");
+                fail!("unexpected indeterminate result");
             }
             Failed => {
                 return None;
@@ -4690,7 +4719,7 @@ pub impl Resolver {
             }
         }
 
-        if vec::len(values) > 0 &&
+        if values.len() > 0 &&
             values[smallest] != uint::max_value &&
             values[smallest] < str::len(name) + 2 &&
             values[smallest] <= max_distance &&
@@ -4845,12 +4874,25 @@ pub impl Resolver {
                                                    `%s`",
                                                    *self.session.str_of(
                                                        label))),
-                    Some(dl_def(def @ def_label(_))) =>
-                        self.record_def(expr.id, def),
-                    Some(_) =>
+                    Some(dl_def(def @ def_label(_))) => {
+                        self.record_def(expr.id, def)
+                    }
+                    Some(_) => {
                         self.session.span_bug(expr.span,
                                               ~"label wasn't mapped to a \
                                                 label def!")
+                    }
+                }
+            }
+
+            expr_self => {
+                match self.resolve_self_value_in_local_ribs(expr.span) {
+                    None => {
+                        self.session.span_err(expr.span,
+                                              ~"`self` is not allowed in \
+                                                this context")
+                    }
+                    Some(def) => self.record_def(expr.id, def),
                 }
             }
 
@@ -5125,14 +5167,7 @@ pub impl Resolver {
     // resolve data structures.
     //
 
-    fn unused_import_lint_level(@mut self, m: @mut Module) -> level {
-        let settings = self.session.lint_settings;
-        match m.def_id {
-            Some(def) => get_lint_settings_level(settings, unused_imports,
-                                                 def.node, def.node),
-            None => get_lint_level(settings.default_settings, unused_imports)
-        }
-    }
+    fn unused_import_lint_level(@mut self, _: @mut Module) -> level { warn }
 
     fn check_for_unused_imports_if_necessary(@mut self) {
         if self.unused_import_lint_level(self.current_module) == allow {
@@ -5194,12 +5229,7 @@ pub impl Resolver {
                     !import_resolution.state.warned &&
                     import_resolution.span != dummy_sp() &&
                     import_resolution.privacy != Public {
-                import_resolution.state.warned = true;
-                let span = import_resolution.span;
-                self.session.span_lint_level(
-                    self.unused_import_lint_level(module_),
-                    span,
-                    ~"unused import");
+                // I swear I work in not(stage0)!
             }
         }
     }
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index e05f9d5f290..d2834a095aa 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -205,7 +205,7 @@ pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
                         a_expr = e.get();
                     }
                     UnitLikeStructLit(_) => {
-                        fail!(~"UnitLikeStructLit should have been handled \
+                        fail!("UnitLikeStructLit should have been handled \
                                above")
                     }
                 }
@@ -218,7 +218,7 @@ pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
                         b_expr = e.get();
                     }
                     UnitLikeStructLit(_) => {
-                        fail!(~"UnitLikeStructLit should have been handled \
+                        fail!("UnitLikeStructLit should have been handled \
                                above")
                     }
                 }
@@ -426,10 +426,10 @@ pub fn enter_match<'r>(bcx: block,
                         vec::append(sub, vec::slice(br.pats, 0u, col)),
                         vec::slice(br.pats, col + 1u, br.pats.len()));
 
-                let self = br.pats[col];
-                match self.node {
+                let this = br.pats[col];
+                match this.node {
                     ast::pat_ident(_, path, None) => {
-                        if pat_is_binding(dm, self) {
+                        if pat_is_binding(dm, this) {
                             let binding_info =
                                 br.data.bindings_map.get(
                                     &path_to_ident(path));
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 9c84b2a4182..9211939cd2a 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -32,12 +32,9 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
     let outputs = do ia.outputs.map |&(c, out)| {
         constraints.push(copy *c);
 
-        let aoutty = ty::arg {
-            ty: expr_ty(bcx, out)
-        };
         aoutputs.push(unpack_result!(bcx, {
             callee::trans_arg_expr(bcx,
-                                   aoutty,
+                                   expr_ty(bcx, out),
                                    ty::ByCopy,
                                    out,
                                    &mut cleanups,
@@ -47,16 +44,12 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
 
         let e = match out.node {
             ast::expr_addr_of(_, e) => e,
-            _ => fail!(~"Expression must be addr of")
-        };
-
-        let outty = ty::arg {
-            ty: expr_ty(bcx, e)
+            _ => fail!("Expression must be addr of")
         };
 
         unpack_result!(bcx, {
             callee::trans_arg_expr(bcx,
-                                   outty,
+                                   expr_ty(bcx, e),
                                    ty::ByCopy,
                                    e,
                                    &mut cleanups,
@@ -75,13 +68,9 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
     let inputs = do ia.inputs.map |&(c, in)| {
         constraints.push(copy *c);
 
-        let inty = ty::arg {
-            ty: expr_ty(bcx, in)
-        };
-
         unpack_result!(bcx, {
             callee::trans_arg_expr(bcx,
-                                   inty,
+                                   expr_ty(bcx, in),
                                    ty::ByCopy,
                                    in,
                                    &mut cleanups,
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 3af58cfcadc..b5cca20d8ec 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1664,12 +1664,12 @@ pub fn new_fn_ctxt(ccx: @CrateContext,
 // the function's fn_ctxt).  create_llargs_for_fn_args populates the llargs
 // field of the fn_ctxt with
 pub fn create_llargs_for_fn_args(cx: fn_ctxt,
-                                 ty_self: self_arg,
+                                 self_arg: self_arg,
                                  args: &[ast::arg])
                               -> ~[ValueRef] {
     let _icx = cx.insn_ctxt("create_llargs_for_fn_args");
 
-    match ty_self {
+    match self_arg {
       impl_self(tt) => {
         cx.llself = Some(ValSelfData {
             v: cx.llenv,
@@ -1701,7 +1701,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
                             bcx: block,
                             args: &[ast::arg],
                             raw_llargs: &[ValueRef],
-                            arg_tys: &[ty::arg]) -> block {
+                            arg_tys: &[ty::t]) -> block {
     let _icx = fcx.insn_ctxt("copy_args_to_allocas");
     let mut bcx = bcx;
 
@@ -1720,7 +1720,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
     }
 
     for uint::range(0, arg_tys.len()) |arg_n| {
-        let arg_ty = &arg_tys[arg_n];
+        let arg_ty = arg_tys[arg_n];
         let raw_llarg = raw_llargs[arg_n];
         let arg_id = args[arg_n].id;
 
@@ -1732,15 +1732,15 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
         // This alloca should be optimized away by LLVM's mem-to-reg pass in
         // the event it's not truly needed.
         // only by value if immediate:
-        let llarg = if datum::appropriate_mode(arg_ty.ty).is_by_value() {
-            let alloc = alloc_ty(bcx, arg_ty.ty);
+        let llarg = if datum::appropriate_mode(arg_ty).is_by_value() {
+            let alloc = alloc_ty(bcx, arg_ty);
             Store(bcx, raw_llarg, alloc);
             alloc
         } else {
             raw_llarg
         };
 
-        add_clean(bcx, llarg, arg_ty.ty);
+        add_clean(bcx, llarg, arg_ty);
 
         bcx = _match::bind_irrefutable_pat(bcx,
                                           args[arg_n].pat,
@@ -1801,7 +1801,7 @@ pub fn trans_closure(ccx: @CrateContext,
                      decl: &ast::fn_decl,
                      body: &ast::blk,
                      llfndecl: ValueRef,
-                     ty_self: self_arg,
+                     self_arg: self_arg,
                      param_substs: Option<@param_substs>,
                      id: ast::node_id,
                      impl_id: Option<ast::def_id>,
@@ -1825,7 +1825,7 @@ pub fn trans_closure(ccx: @CrateContext,
                                impl_id,
                                param_substs,
                                Some(body.span));
-    let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs);
+    let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
 
     // Set the fixed stack segment flag if necessary.
     if attr::attrs_contains_name(attributes, "fixed_stack_segment") {
@@ -1882,7 +1882,7 @@ pub fn trans_fn(ccx: @CrateContext,
                 decl: &ast::fn_decl,
                 body: &ast::blk,
                 llfndecl: ValueRef,
-                ty_self: self_arg,
+                self_arg: self_arg,
                 param_substs: Option<@param_substs>,
                 id: ast::node_id,
                 impl_id: Option<ast::def_id>,
@@ -1890,8 +1890,8 @@ pub fn trans_fn(ccx: @CrateContext,
     let do_time = ccx.sess.trans_stats();
     let start = if do_time { time::get_time() }
                 else { time::Timespec::new(0, 0) };
-    debug!("trans_fn(ty_self=%?, param_substs=%s)",
-           ty_self,
+    debug!("trans_fn(self_arg=%?, param_substs=%s)",
+           self_arg,
            param_substs.repr(ccx.tcx));
     let _icx = ccx.insn_ctxt("trans_fn");
     ccx.stats.n_fns += 1;
@@ -1902,7 +1902,7 @@ pub fn trans_fn(ccx: @CrateContext,
                   decl,
                   body,
                   llfndecl,
-                  ty_self,
+                  self_arg,
                   param_substs,
                   id,
                   impl_id,
@@ -1985,9 +1985,9 @@ pub fn trans_enum_variant(ccx: @CrateContext,
         // works. So we have to cast to the destination's view of the type.
         let llarg = match fcx.llargs.find(&va.id) {
             Some(&local_mem(x)) => x,
-            _ => fail!(~"trans_enum_variant: how do we know this works?"),
+            _ => fail!("trans_enum_variant: how do we know this works?"),
         };
-        let arg_ty = arg_tys[i].ty;
+        let arg_ty = arg_tys[i];
         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
     }
     build_return(bcx);
@@ -2061,7 +2061,7 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
                                    local_mem")
             }
         };
-        let arg_ty = arg_tys[i].ty;
+        let arg_ty = arg_tys[i];
         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
     }
 
@@ -2097,7 +2097,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
     let path = match ccx.tcx.items.get_copy(&item.id) {
         ast_map::node_item(_, p) => p,
         // tjc: ?
-        _ => fail!(~"trans_item"),
+        _ => fail!("trans_item"),
     };
     match item.node {
       ast::item_fn(ref decl, purity, _abis, ref generics, ref body) => {
@@ -2228,8 +2228,7 @@ pub fn register_fn_fuller(ccx: @CrateContext,
         mangle_exported_name(ccx, /*bad*/copy path, node_type)
     };
 
-    // XXX: Bad copy.
-    let llfn: ValueRef = decl_fn(ccx.llmod, copy ps, cc, llfty);
+    let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty);
     ccx.item_symbols.insert(node_id, ps);
 
     // FIXME #4404 android JNI hacks
@@ -2390,7 +2389,7 @@ pub fn item_path(ccx: @CrateContext, i: @ast::item) -> path {
     let base = match ccx.tcx.items.get_copy(&i.id) {
         ast_map::node_item(_, p) => p,
             // separate map for paths?
-        _ => fail!(~"item_path")
+        _ => fail!("item_path")
     };
     vec::append(/*bad*/copy *base, ~[path_name(i.ident)])
 }
@@ -2436,7 +2435,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
                 set_inline_hint_if_appr(i.attrs, llfn);
                 llfn
               }
-              _ => fail!(~"get_item_val: weird result in table")
+              _ => fail!("get_item_val: weird result in table")
             }
           }
           ast_map::node_trait_method(trait_method, _, pth) => {
@@ -2493,11 +2492,11 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
                       ast::item_enum(_, _) => {
                         register_fn(ccx, (*v).span, pth, id, enm.attrs)
                       }
-                      _ => fail!(~"node_variant, shouldn't happen")
+                      _ => fail!("node_variant, shouldn't happen")
                     };
                 }
                 ast::struct_variant_kind(_) => {
-                    fail!(~"struct variant kind unexpected in get_item_val")
+                    fail!("struct variant kind unexpected in get_item_val")
                 }
             }
             set_inline_hint(llfn);
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index b2af91887ec..e8853fd20e9 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -25,7 +25,7 @@ pub fn terminate(cx: block, _: &str) {
 
 pub fn check_not_terminated(cx: block) {
     if cx.terminated {
-        fail!(~"already terminated!");
+        fail!("already terminated!");
     }
 }
 
@@ -544,7 +544,7 @@ pub fn AtomicLoad(cx: block, PointerVal: ValueRef, order: AtomicOrdering) -> Val
             return llvm::LLVMGetUndef(ccx.int_type);
         }
         count_insn(cx, "load.atomic");
-        return llvm::LLVMBuildAtomicLoad(B(cx), PointerVal, order);
+        return llvm::LLVMBuildAtomicLoad(B(cx), PointerVal, noname(), order);
     }
 }
 
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index 702d62f1363..e103bbc5de7 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -65,7 +65,7 @@ pub impl FnType {
 
         let mut llargvals = ~[];
         let mut i = 0u;
-        let n = vec::len(arg_tys);
+        let n = arg_tys.len();
 
         if self.sret {
             let llretptr = GEPi(bcx, llargbundle, [0u, n]);
@@ -113,7 +113,7 @@ pub impl FnType {
         if self.sret || !ret_def {
             return;
         }
-        let n = vec::len(arg_tys);
+        let n = arg_tys.len();
         // R** llretptr = &args->r;
         let llretptr = GEPi(bcx, llargbundle, [0u, n]);
         // R* llretloc = *llretptr; /* (args->r) */
@@ -149,7 +149,7 @@ pub impl FnType {
         };
 
         let mut i = 0u;
-        let n = vec::len(atys);
+        let n = atys.len();
         while i < n {
             let mut argval = get_param(llwrapfn, i + j);
             if attrs[i].is_some() {
diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs
index 1b94e990545..39535609598 100644
--- a/src/librustc/middle/trans/cabi_arm.rs
+++ b/src/librustc/middle/trans/cabi_arm.rs
@@ -52,7 +52,7 @@ fn ty_align(ty: TypeRef) -> uint {
                 let elt = llvm::LLVMGetElementType(ty);
                 ty_align(elt)
             }
-            _ => fail!(~"ty_align: unhandled type")
+            _ => fail!("ty_align: unhandled type")
         };
     }
 }
@@ -84,7 +84,7 @@ fn ty_size(ty: TypeRef) -> uint {
                 let eltsz = ty_size(elt);
                 len * eltsz
             }
-            _ => fail!(~"ty_size: unhandled type")
+            _ => fail!("ty_size: unhandled type")
         };
     }
 }
diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs
index 971f2ae2bdb..a1f54c2d182 100644
--- a/src/librustc/middle/trans/cabi_mips.rs
+++ b/src/librustc/middle/trans/cabi_mips.rs
@@ -60,7 +60,7 @@ fn ty_align(ty: TypeRef) -> uint {
                 let elt = llvm::LLVMGetElementType(ty);
                 ty_align(elt)
             }
-            _ => fail!(~"ty_size: unhandled type")
+            _ => fail!("ty_size: unhandled type")
         };
     }
 }
@@ -92,7 +92,7 @@ fn ty_size(ty: TypeRef) -> uint {
               let eltsz = ty_size(elt);
               len * eltsz
             }
-            _ => fail!(~"ty_size: unhandled type")
+            _ => fail!("ty_size: unhandled type")
         };
     }
 }
diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs
index 4da2199501f..a44f203c7ab 100644
--- a/src/librustc/middle/trans/cabi_x86_64.rs
+++ b/src/librustc/middle/trans/cabi_x86_64.rs
@@ -50,7 +50,7 @@ fn is_sse(c: x86_64_reg_class) -> bool {
 }
 
 fn is_ymm(cls: &[x86_64_reg_class]) -> bool {
-    let len = vec::len(cls);
+    let len = cls.len();
     return (len > 2u &&
          is_sse(cls[0]) &&
          cls[1] == sseup_class &&
@@ -89,7 +89,7 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
                     let elt = llvm::LLVMGetElementType(ty);
                     ty_align(elt)
                 }
-                _ => fail!(~"ty_size: unhandled type")
+                _ => fail!("ty_size: unhandled type")
             };
         }
     }
@@ -121,7 +121,7 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
                   let eltsz = ty_size(elt);
                   len * eltsz
                 }
-                _ => fail!(~"ty_size: unhandled type")
+                _ => fail!("ty_size: unhandled type")
             };
         }
     }
@@ -214,7 +214,7 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
                         i += 1u;
                     }
                 }
-                _ => fail!(~"classify: unhandled type")
+                _ => fail!("classify: unhandled type")
             }
         }
     }
@@ -223,8 +223,8 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
         unsafe {
             let mut i = 0u;
             let llty = llvm::LLVMGetTypeKind(ty) as int;
-            let e = vec::len(cls);
-            if vec::len(cls) > 2u &&
+            let e = cls.len();
+            if cls.len() > 2u &&
                (llty == 10 /* struct */ ||
                 llty == 11 /* array */) {
                 if is_sse(cls[i]) {
@@ -295,7 +295,7 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
     unsafe {
         let mut tys = ~[];
         let mut i = 0u;
-        let e = vec::len(cls);
+        let e = cls.len();
         while i < e {
             match cls[i] {
                 integer_class => {
@@ -315,7 +315,7 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
                 sse_ds_class => {
                     tys.push(T_f64());
                 }
-                _ => fail!(~"llregtype: unhandled class")
+                _ => fail!("llregtype: unhandled class")
             }
             i += 1u;
         }
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 70a0a7d06d3..dc81a980588 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -674,7 +674,7 @@ pub enum AutorefArg {
 // temp_cleanups: cleanups that should run only if failure occurs before the
 // call takes place:
 pub fn trans_arg_expr(bcx: block,
-                      formal_ty: ty::arg,
+                      formal_arg_ty: ty::t,
                       self_mode: ty::SelfMode,
                       arg_expr: @ast::expr,
                       temp_cleanups: &mut ~[ValueRef],
@@ -683,9 +683,9 @@ pub fn trans_arg_expr(bcx: block,
     let _icx = bcx.insn_ctxt("trans_arg_expr");
     let ccx = bcx.ccx();
 
-    debug!("trans_arg_expr(formal_ty=(%s), self_mode=%?, arg_expr=%s, \
+    debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s, \
             ret_flag=%?)",
-           formal_ty.ty.repr(bcx.tcx()),
+           formal_arg_ty.repr(bcx.tcx()),
            self_mode,
            arg_expr.repr(bcx.tcx()),
            ret_flag.map(|v| bcx.val_str(*v)));
@@ -734,9 +734,9 @@ pub fn trans_arg_expr(bcx: block,
         // "undef" value, as such a value should never
         // be inspected. It's important for the value
         // to have type lldestty (the callee's expected type).
-        let llformal_ty = type_of::type_of(ccx, formal_ty.ty);
+        let llformal_arg_ty = type_of::type_of(ccx, formal_arg_ty);
         unsafe {
-            val = llvm::LLVMGetUndef(llformal_ty);
+            val = llvm::LLVMGetUndef(llformal_arg_ty);
         }
     } else {
         // FIXME(#3548) use the adjustments table
@@ -784,16 +784,16 @@ pub fn trans_arg_expr(bcx: block,
             }
         }
 
-        if formal_ty.ty != arg_datum.ty {
+        if formal_arg_ty != arg_datum.ty {
             // this could happen due to e.g. subtyping
-            let llformal_ty = type_of::type_of_explicit_arg(ccx, &formal_ty);
-            let llformal_ty = match self_mode {
-                ty::ByRef => T_ptr(llformal_ty),
-                ty::ByCopy => llformal_ty,
+            let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, &formal_arg_ty);
+            let llformal_arg_ty = match self_mode {
+                ty::ByRef => T_ptr(llformal_arg_ty),
+                ty::ByCopy => llformal_arg_ty,
             };
             debug!("casting actual type (%s) to match formal (%s)",
-                   bcx.val_str(val), bcx.llty_str(llformal_ty));
-            val = PointerCast(bcx, val, llformal_ty);
+                   bcx.val_str(val), bcx.llty_str(llformal_arg_ty));
+            val = PointerCast(bcx, val, llformal_arg_ty);
         }
     }
 
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index aff45cbb993..8000484c055 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -256,13 +256,11 @@ pub impl param_substs {
     }
 }
 
-fn param_substs_to_str(self: &param_substs,
-                       tcx: ty::ctxt) -> ~str
-{
+fn param_substs_to_str(this: &param_substs, tcx: ty::ctxt) -> ~str {
     fmt!("param_substs {tys:%s, vtables:%s, type_param_defs:%s}",
-         self.tys.repr(tcx),
-         self.vtables.repr(tcx),
-         self.type_param_defs.repr(tcx))
+         this.tys.repr(tcx),
+         this.vtables.repr(tcx),
+         this.type_param_defs.repr(tcx))
 }
 
 impl Repr for param_substs {
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 374bb23f2cb..8055d919ffd 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -101,7 +101,6 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux::ty_to_str;
 
-use core::container::Set; // XXX: this should not be necessary
 use core::to_bytes;
 use syntax::ast;
 use syntax::codemap::span;
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index f0fb33136ff..d8252a449ba 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -785,7 +785,7 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span)
             cx.sess.span_bug(span, "debuginfo for rptr NYI")
         },
         ty::ty_bare_fn(ref barefnty) => {
-            let inputs = do barefnty.sig.inputs.map |a| { a.ty };
+            let inputs = barefnty.sig.inputs.map(|a| *a);
             let output = barefnty.sig.output;
             create_fn_ty(cx, t, inputs, output, span)
         },
@@ -837,7 +837,7 @@ pub fn create_local_var(bcx: block, local: @ast::local)
     let name = match local.node.pat.node {
       ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
       // FIXME this should be handled (#2533)
-      _ => fail!(~"no single variable name for local")
+      _ => fail!("no single variable name for local")
     };
     let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
     let ty = node_id_type(bcx, local.node.id);
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index ed3dfdc07c3..59526ffbe49 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -451,7 +451,7 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
     trace_span!(bcx, expr.span, @shorten(bcx.expr_to_str(expr)));
 
     match expr.node {
-        ast::expr_path(_) => {
+        ast::expr_path(_) | ast::expr_self => {
             return trans_def_datum_unadjusted(bcx, expr, bcx.def(expr.id));
         }
         ast::expr_vstore(contents, ast::expr_vstore_box) |
@@ -558,7 +558,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
         ast::expr_paren(e) => {
             return trans_rvalue_dps_unadjusted(bcx, e, dest);
         }
-        ast::expr_path(_) => {
+        ast::expr_path(_) | ast::expr_self => {
             return trans_def_dps_unadjusted(bcx, expr,
                                             bcx.def(expr.id), dest);
         }
@@ -810,7 +810,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
         ast::expr_paren(e) => {
             trans_lvalue_unadjusted(bcx, e)
         }
-        ast::expr_path(_) => {
+        ast::expr_path(_) | ast::expr_self => {
             trans_def_lvalue(bcx, expr, bcx.def(expr.id))
         }
         ast::expr_field(base, ident, _) => {
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 30db63e9c19..fd545ca2c6e 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -29,7 +29,7 @@ use middle::trans::machine;
 use middle::trans::type_of::*;
 use middle::trans::type_of;
 use middle::ty;
-use middle::ty::{FnSig, arg};
+use middle::ty::FnSig;
 use util::ppaux::ty_to_str;
 
 use syntax::codemap::span;
@@ -94,7 +94,7 @@ fn foreign_signature(ccx: @CrateContext, fn_sig: &ty::FnSig)
      * values by pointer like we do.
      */
 
-    let llarg_tys = fn_sig.inputs.map(|arg| type_of(ccx, arg.ty));
+    let llarg_tys = fn_sig.inputs.map(|arg_ty| type_of(ccx, *arg_ty));
     let llret_ty = type_of::type_of(ccx, fn_sig.output);
     LlvmSignature {
         llarg_tys: llarg_tys,
@@ -509,7 +509,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
                       llargbundle: ValueRef) {
             let _icx = bcx.insn_ctxt("foreign::wrap::build_args");
             let ccx = bcx.ccx();
-            let n = vec::len(tys.llsig.llarg_tys);
+            let n = tys.llsig.llarg_tys.len();
             let implicit_args = first_real_arg; // return + env
             for uint::range(0, n) |i| {
                 let mut llargval = get_param(llwrapfn, i + implicit_args);
@@ -753,7 +753,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             if in_type_size != out_type_size {
                 let sp = match ccx.tcx.items.get_copy(&ref_id.get()) {
                     ast_map::node_expr(e) => e.span,
-                    _ => fail!(~"transmute has non-expr arg"),
+                    _ => fail!("transmute has non-expr arg"),
                 };
                 let pluralize = |n| if 1u == n { "" } else { "s" };
                 ccx.sess.span_fatal(sp,
@@ -818,9 +818,10 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                 sigil: ast::BorrowedSigil,
                 onceness: ast::Many,
                 region: ty::re_bound(ty::br_anon(0)),
+                bounds: ty::EmptyBuiltinBounds(),
                 sig: FnSig {
                     bound_lifetime_names: opt_vec::Empty,
-                    inputs: ~[ arg { ty: star_u8 } ],
+                    inputs: ~[ star_u8 ],
                     output: ty::mk_nil()
                 }
             });
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index e5c6244879d..10e019b2a37 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -99,14 +99,14 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id,
               let path = vec::append(
                   ty::item_path(ccx.tcx, impl_did),
                   ~[path_name(mth.ident)]);
-              let self_kind = match mth.self_ty.node {
+              let self_kind = match mth.explicit_self.node {
                   ast::sty_static => no_self,
                   _ => {
                       let self_ty = ty::node_id_to_type(ccx.tcx,
                                                         mth.self_id);
                       debug!("calling inline trans_fn with self_ty %s",
                              ty_to_str(ccx.tcx, self_ty));
-                      match mth.self_ty.node {
+                      match mth.explicit_self.node {
                           ast::sty_value => impl_owned_self(self_ty),
                           _ => impl_self(self_ty),
                       }
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index ffe414ab5b5..6eb2540f1df 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -25,7 +25,6 @@ use middle::trans::inline;
 use middle::trans::monomorphize;
 use middle::trans::type_of::*;
 use middle::ty;
-use middle::ty::arg;
 use middle::typeck;
 use util::common::indenter;
 use util::ppaux::Repr;
@@ -70,7 +69,12 @@ pub fn trans_impl(ccx: @CrateContext, path: path, name: ast::ident,
                 }
             }
 
-            trans_method(ccx, path, *method, param_substs_opt, self_ty, llfn,
+            trans_method(ccx,
+                         path,
+                         *method,
+                         param_substs_opt,
+                         self_ty,
+                         llfn,
                          ast_util::local_def(id));
         }
     }
@@ -99,18 +103,17 @@ pub fn trans_method(ccx: @CrateContext,
                     llfn: ValueRef,
                     impl_id: ast::def_id) {
     // figure out how self is being passed
-    let self_arg = match method.self_ty.node {
+    let self_arg = match method.explicit_self.node {
       ast::sty_static => {
         no_self
       }
       _ => {
         // determine the (monomorphized) type that `self` maps to for
         // this method
-        let self_ty;
-        match base_self_ty {
-            None => self_ty = ty::node_id_to_type(ccx.tcx, method.self_id),
-            Some(provided_self_ty) => self_ty = provided_self_ty
-        }
+        let self_ty = match base_self_ty {
+            None => ty::node_id_to_type(ccx.tcx, method.self_id),
+            Some(provided_self_ty) => provided_self_ty,
+        };
         let self_ty = match param_substs {
             None => self_ty,
             Some(@param_substs {tys: ref tys, _}) => {
@@ -120,7 +123,7 @@ pub fn trans_method(ccx: @CrateContext,
         debug!("calling trans_fn with base_self_ty %s, self_ty %s",
                base_self_ty.repr(ccx.tcx),
                self_ty.repr(ccx.tcx));
-        match method.self_ty.node {
+        match method.explicit_self.node {
           ast::sty_value => {
             impl_owned_self(self_ty)
           }
@@ -151,12 +154,10 @@ pub fn trans_self_arg(bcx: block,
     let mut temp_cleanups = ~[];
 
     // Compute the type of self.
-    let self_arg = arg {
-        ty: monomorphize_type(bcx, mentry.self_arg.ty)
-    };
+    let self_ty = monomorphize_type(bcx, mentry.self_ty);
 
     let result = trans_arg_expr(bcx,
-                                self_arg,
+                                self_ty,
                                 mentry.self_mode,
                                 base,
                                 &mut temp_cleanups,
@@ -174,14 +175,15 @@ pub fn trans_self_arg(bcx: block,
 
 pub fn trans_method_callee(bcx: block,
                            callee_id: ast::node_id,
-                           self: @ast::expr,
+                           this: @ast::expr,
                            mentry: typeck::method_map_entry)
-                        -> Callee {
+                           -> Callee {
     let _icx = bcx.insn_ctxt("impl::trans_method_callee");
     let tcx = bcx.tcx();
 
-    debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%s)",
-           callee_id, bcx.expr_to_str(self),
+    debug!("trans_method_callee(callee_id=%?, this=%s, mentry=%s)",
+           callee_id,
+           bcx.expr_to_str(this),
            mentry.repr(bcx.tcx()));
 
     // Replace method_self with method_static here.
@@ -202,7 +204,7 @@ pub fn trans_method_callee(bcx: block,
         }
         typeck::method_super(trait_id, method_index) => {
             // <self_ty> is the self type for this method call
-            let self_ty = node_id_type(bcx, self.id);
+            let self_ty = node_id_type(bcx, this.id);
             // <impl_id> is the ID of the implementation of
             // trait <trait_id> for type <self_ty>
             let impl_id = ty::get_impl_id(tcx, trait_id, self_ty);
@@ -232,13 +234,13 @@ pub fn trans_method_callee(bcx: block,
     match origin {
         typeck::method_static(did) => {
             let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
-            let Result {bcx, val} = trans_self_arg(bcx, self, mentry);
+            let Result {bcx, val} = trans_self_arg(bcx, this, mentry);
             Callee {
                 bcx: bcx,
                 data: Method(MethodData {
                     llfn: callee_fn.llfn,
                     llself: val,
-                    self_ty: node_id_type(bcx, self.id),
+                    self_ty: node_id_type(bcx, this.id),
                     self_mode: mentry.self_mode,
                 })
             }
@@ -252,23 +254,23 @@ pub fn trans_method_callee(bcx: block,
             match bcx.fcx.param_substs {
                 Some(substs) => {
                     let vtbl = find_vtable(bcx.tcx(), substs, p, b);
-                    trans_monomorphized_callee(bcx, callee_id, self, mentry,
+                    trans_monomorphized_callee(bcx, callee_id, this, mentry,
                                                trait_id, off, vtbl)
                 }
                 // how to get rid of this?
-                None => fail!(~"trans_method_callee: missing param_substs")
+                None => fail!("trans_method_callee: missing param_substs")
             }
         }
         typeck::method_trait(_, off, store) => {
             trans_trait_callee(bcx,
                                callee_id,
                                off,
-                               self,
+                               this,
                                store,
                                mentry.explicit_self)
         }
         typeck::method_self(*) | typeck::method_super(*) => {
-            fail!(~"method_self or method_super should have been handled \
+            fail!("method_self or method_super should have been handled \
                 above")
         }
     }
@@ -316,13 +318,13 @@ pub fn trans_static_method_callee(bcx: block,
             ast_map::node_trait_method(trait_method, _, _) => {
                 ast_util::trait_method_to_ty_method(trait_method).ident
             }
-            _ => fail!(~"callee is not a trait method")
+            _ => fail!("callee is not a trait method")
         }
     } else {
         let path = csearch::get_item_path(bcx.tcx(), method_id);
         match path[path.len()-1] {
             path_name(s) => { s }
-            path_mod(_) => { fail!(~"path doesn't have a name?") }
+            path_mod(_) => { fail!("path doesn't have a name?") }
         }
     };
     debug!("trans_static_method_callee: method_id=%?, callee_id=%?, \
@@ -353,7 +355,7 @@ pub fn trans_static_method_callee(bcx: block,
             FnData {llfn: PointerCast(bcx, lval, llty)}
         }
         _ => {
-            fail!(~"vtable_param left in monomorphized \
+            fail!("vtable_param left in monomorphized \
                    function's vtable substs");
         }
     }
@@ -374,7 +376,7 @@ pub fn method_with_name(ccx: @CrateContext, impl_id: ast::def_id,
             }, _) => {
             method_from_methods(*ms, name).get()
           }
-          _ => fail!(~"method_with_name")
+          _ => fail!("method_with_name")
         }
     } else {
         csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
@@ -409,7 +411,7 @@ pub fn method_with_name_or_default(ccx: @CrateContext,
                   }
               }
           }
-          _ => fail!(~"method_with_name")
+          _ => fail!("method_with_name")
         }
     } else {
         csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
@@ -435,7 +437,7 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id,
                                             _, _)) => {
                 m.generics.ty_params.len()
             }
-            copy e => fail!(fmt!("method_ty_param_count %?", e))
+            copy e => fail!("method_ty_param_count %?", e)
         }
     } else {
         csearch::get_type_param_count(ccx.sess.cstore, m_id) -
@@ -494,8 +496,7 @@ pub fn trans_monomorphized_callee(bcx: block,
           }
       }
       typeck::vtable_param(*) => {
-          fail!(~"vtable_param left in monomorphized function's " +
-              "vtable substs");
+          fail!("vtable_param left in monomorphized function's vtable substs");
       }
     };
 
@@ -589,7 +590,7 @@ pub fn trans_trait_callee(bcx: block,
                           n_method: uint,
                           self_expr: @ast::expr,
                           store: ty::TraitStore,
-                          explicit_self: ast::self_ty_)
+                          explicit_self: ast::explicit_self_)
                        -> Callee {
     //!
     //
@@ -626,7 +627,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
                                      n_method: uint,
                                      llpair: ValueRef,
                                      store: ty::TraitStore,
-                                     explicit_self: ast::self_ty_)
+                                     explicit_self: ast::explicit_self_)
                                   -> Callee {
     //!
     //
@@ -751,7 +752,7 @@ pub fn vtable_id(ccx: @CrateContext,
         }
 
         // can't this be checked at the callee?
-        _ => fail!(~"vtable_id")
+        _ => fail!("vtable_id")
     }
 }
 
@@ -766,7 +767,7 @@ pub fn get_vtable(ccx: @CrateContext,
         typeck::vtable_static(id, substs, sub_vtables) => {
             make_impl_vtable(ccx, id, substs, sub_vtables)
         }
-        _ => fail!(~"get_vtable: expected a static origin")
+        _ => fail!("get_vtable: expected a static origin")
       }
     }
 }
@@ -794,8 +795,11 @@ pub fn make_impl_vtable(ccx: @CrateContext,
     let _icx = ccx.insn_ctxt("impl::make_impl_vtable");
     let tcx = ccx.tcx;
 
-    // XXX: This should support multiple traits.
-    let trt_id = ty::impl_trait_refs(tcx, impl_id)[0].def_id;
+    let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
+        Some(t_id) => t_id.def_id,
+        None       => ccx.sess.bug("make_impl_vtable: don't know how to \
+                                    make a vtable for a type impl!")
+    };
 
     let has_tps =
         !ty::lookup_item_type(ccx.tcx, impl_id).generics.type_param_defs.is_empty();
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 3b0c03cdc99..ccc906f2ee8 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -330,6 +330,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
                 sigil: sigil,
                 onceness: ast::Many,
                 region: ty::re_static,
+                bounds: ty::EmptyBuiltinBounds(),
                 sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
                                 inputs: ~[],
                                 output: ty::mk_nil()}})
diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs
index 9bbf50397c3..dfae7ca0e88 100644
--- a/src/librustc/middle/trans/reachable.rs
+++ b/src/librustc/middle/trans/reachable.rs
@@ -147,7 +147,7 @@ fn traverse_public_item(cx: @mut ctx, item: @item) {
       }
       item_const(*) |
       item_enum(*) | item_trait(*) => (),
-      item_mac(*) => fail!(~"item macros unimplemented")
+      item_mac(*) => fail!("item macros unimplemented")
     }
 }
 
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 2183472d591..1141e0c007f 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -35,7 +35,7 @@ use syntax::parse::token::special_idents;
 
 pub struct Reflector {
     visitor_val: ValueRef,
-    visitor_methods: @~[@ty::method],
+    visitor_methods: @~[@ty::Method],
     final_bcx: block,
     tydesc_ty: TypeRef,
     bcx: block
@@ -93,7 +93,7 @@ pub impl Reflector {
         let mth_ty =
             ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
         let v = self.visitor_val;
-        debug!("passing %u args:", vec::len(args));
+        debug!("passing %u args:", args.len());
         let bcx = self.bcx;
         for args.eachi |i, a| {
             debug!("arg %u: %s", i, val_str(bcx.ccx().tn, *a));
@@ -224,7 +224,7 @@ pub impl Reflector {
             let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
             let extra = ~[self.c_uint(pureval),
                           self.c_uint(sigilval),
-                          self.c_uint(vec::len(fty.sig.inputs)),
+                          self.c_uint(fty.sig.inputs.len()),
                           self.c_uint(retval)];
             self.visit(~"enter_fn", copy extra);    // XXX: Bad copy.
             self.visit_sig(retval, &fty.sig);
@@ -239,7 +239,7 @@ pub impl Reflector {
             let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
             let extra = ~[self.c_uint(pureval),
                           self.c_uint(sigilval),
-                          self.c_uint(vec::len(fty.sig.inputs)),
+                          self.c_uint(fty.sig.inputs.len()),
                           self.c_uint(retval)];
             self.visit(~"enter_fn", copy extra);    // XXX: Bad copy.
             self.visit_sig(retval, &fty.sig);
@@ -284,13 +284,8 @@ pub impl Reflector {
                 let sym = mangle_internal_name_by_path_and_seq(ccx,
                                                                sub_path,
                                                                "get_disr");
-                let args = [
-                    ty::arg {
-                        ty: opaqueptrty
-                    }
-                ];
 
-                let llfty = type_of_fn(ccx, args, ty::mk_int());
+                let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int());
                 let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
                 let arg = unsafe {
                     llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint)
@@ -309,13 +304,13 @@ pub impl Reflector {
                 llfdecl
             };
 
-            let enum_args = ~[self.c_uint(vec::len(variants)), make_get_disr()]
+            let enum_args = ~[self.c_uint(variants.len()), make_get_disr()]
                 + self.c_size_and_align(t);
             do self.bracketed(~"enum", enum_args) |this| {
                 for variants.eachi |i, v| {
                     let variant_args = ~[this.c_uint(i),
                                          this.c_int(v.disr_val),
-                                         this.c_uint(vec::len(v.args)),
+                                         this.c_uint(v.args.len()),
                                          this.c_slice(ccx.sess.str_of(v.name))];
                     do this.bracketed(~"enum_variant", variant_args) |this| {
                         for v.args.eachi |j, a| {
@@ -357,7 +352,7 @@ pub impl Reflector {
             let modeval = 5u;   // "by copy"
             let extra = ~[self.c_uint(i),
                          self.c_uint(modeval),
-                         self.c_tydesc(arg.ty)];
+                         self.c_tydesc(*arg)];
             self.visit(~"fn_input", extra);
         }
         let extra = ~[self.c_uint(retval),
diff --git a/src/librustc/middle/trans/shape.rs b/src/librustc/middle/trans/shape.rs
index 6ff9e1cfc57..31de1280741 100644
--- a/src/librustc/middle/trans/shape.rs
+++ b/src/librustc/middle/trans/shape.rs
@@ -18,7 +18,6 @@ use middle::trans::common::*;
 use middle::trans;
 
 use core::str;
-use core::vec;
 
 pub struct Ctxt {
     next_tag_id: u16,
@@ -71,6 +70,6 @@ pub fn add_u16(dest: &mut ~[u8], val: u16) {
 }
 
 pub fn add_substr(dest: &mut ~[u8], src: ~[u8]) {
-    add_u16(&mut *dest, vec::len(src) as u16);
+    add_u16(&mut *dest, src.len() as u16);
     *dest += src;
 }
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index b8e0b58f866..dfbebd90c29 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -19,21 +19,21 @@ use util::ppaux;
 
 use syntax::ast;
 
-pub fn arg_is_indirect(_: @CrateContext, arg: &ty::arg) -> bool {
-    !ty::type_is_immediate(arg.ty)
+pub fn arg_is_indirect(_: @CrateContext, arg_ty: &ty::t) -> bool {
+    !ty::type_is_immediate(*arg_ty)
 }
 
-pub fn type_of_explicit_arg(ccx: @CrateContext, arg: &ty::arg) -> TypeRef {
-    let llty = type_of(ccx, arg.ty);
-    if arg_is_indirect(ccx, arg) {T_ptr(llty)} else {llty}
+pub fn type_of_explicit_arg(ccx: @CrateContext, arg_ty: &ty::t) -> TypeRef {
+    let llty = type_of(ccx, *arg_ty);
+    if arg_is_indirect(ccx, arg_ty) {T_ptr(llty)} else {llty}
 }
 
 pub fn type_of_explicit_args(ccx: @CrateContext,
-                             inputs: &[ty::arg]) -> ~[TypeRef] {
-    inputs.map(|arg| type_of_explicit_arg(ccx, arg))
+                             inputs: &[ty::t]) -> ~[TypeRef] {
+    inputs.map(|arg_ty| type_of_explicit_arg(ccx, arg_ty))
 }
 
-pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], output: ty::t)
+pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t)
                -> TypeRef {
     unsafe {
         let mut atys: ~[TypeRef] = ~[];
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 6a271f979ca..4a8adfba11c 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -78,7 +78,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
         ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
         ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
             for sig.inputs.each |arg| {
-                type_needs(cx, use_repr, arg.ty);
+                type_needs(cx, use_repr, *arg);
             }
         }
         _ => ()
@@ -154,7 +154,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
                 ~"bswap16" | ~"bswap32" | ~"bswap64" => 0,
 
                 // would be cool to make these an enum instead of strings!
-                _ => fail!(~"unknown intrinsic in type_use")
+                _ => fail!("unknown intrinsic in type_use")
             };
             for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;}
         }
@@ -295,7 +295,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
           _ => ()
         }
       }
-      expr_path(_) => {
+      expr_path(_) | expr_self => {
         let opt_ts = cx.ccx.tcx.node_type_substs.find_copy(&e.id);
         for opt_ts.each |ts| {
             let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get_copy(&e.id));
@@ -331,18 +331,16 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
         node_type_needs(cx, use_tydesc, val.id);
       }
       expr_call(f, _, _) => {
-          for vec::each(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
-                                                           f.id))) |a| {
-              type_needs(cx, use_repr, a.ty);
+          for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id)).each |a| {
+              type_needs(cx, use_repr, *a);
           }
       }
       expr_method_call(rcvr, _, _, _, _) => {
         let base_ty = ty::node_id_to_type(cx.ccx.tcx, rcvr.id);
         type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
 
-        for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
-                                               e.callee_id)).each |a| {
-            type_needs(cx, use_repr, a.ty);
+        for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, e.callee_id)).each |a| {
+            type_needs(cx, use_repr, *a);
         }
         mark_for_method_call(cx, e.id, e.callee_id);
       }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index f5adb2fe108..c51fba8a62b 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -14,8 +14,6 @@ use metadata::csearch;
 use metadata;
 use middle::const_eval;
 use middle::freevars;
-use middle::lint::{get_lint_level, allow};
-use middle::lint;
 use middle::resolve::{Impl, MethodInfo};
 use middle::resolve;
 use middle::ty;
@@ -24,7 +22,7 @@ use middle::typeck;
 use middle;
 use util::ppaux::{note_and_explain_region, bound_region_to_str};
 use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
-use util::ppaux::Repr;
+use util::ppaux::{Repr, UserString};
 use util::common::{indenter};
 use util::enum_set::{EnumSet, CLike};
 
@@ -49,36 +47,56 @@ use syntax;
 
 // Data types
 
-#[deriving(Eq, IterBytes)]
-pub struct arg {
-    ty: t
-}
-
 #[deriving(Eq)]
 pub struct field {
     ident: ast::ident,
     mt: mt
 }
 
-pub struct method {
+pub struct Method {
     ident: ast::ident,
     generics: ty::Generics,
     transformed_self_ty: Option<ty::t>,
     fty: BareFnTy,
-    self_ty: ast::self_ty_,
+    explicit_self: ast::explicit_self_,
     vis: ast::visibility,
     def_id: ast::def_id
 }
 
+pub impl Method {
+    fn new(ident: ast::ident,
+           generics: ty::Generics,
+           transformed_self_ty: Option<ty::t>,
+           fty: BareFnTy,
+           explicit_self: ast::explicit_self_,
+           vis: ast::visibility,
+           def_id: ast::def_id) -> Method {
+        // Check the invariants.
+        if explicit_self == ast::sty_static {
+            assert!(transformed_self_ty.is_none());
+        } else {
+            assert!(transformed_self_ty.is_some());
+        }
+
+       Method {
+            ident: ident,
+            generics: generics,
+            transformed_self_ty: transformed_self_ty,
+            fty: fty,
+            explicit_self: explicit_self,
+            vis: vis,
+            def_id: def_id
+        }
+    }
+}
+
 #[deriving(Eq)]
 pub struct mt {
     ty: t,
     mutbl: ast::mutability,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum vstore {
     vstore_fixed(uint),
     vstore_uniq,
@@ -86,9 +104,7 @@ pub enum vstore {
     vstore_slice(Region)
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq, IterBytes)]
+#[deriving(Eq, IterBytes, Encodable, Decodable)]
 pub enum TraitStore {
     BoxTraitStore,              // @Trait
     UniqTraitStore,             // ~Trait
@@ -97,9 +113,7 @@ pub enum TraitStore {
 
 // XXX: This should probably go away at some point. Maybe after destructors
 // do?
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum SelfMode {
     ByCopy,
     ByRef,
@@ -177,27 +191,22 @@ pub enum ast_ty_to_ty_cache_entry {
 
 pub type opt_region_variance = Option<region_variance>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Decodable, Encodable)]
 pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Decodable, Encodable)]
 pub enum AutoAdjustment {
     AutoAddEnv(ty::Region, ast::Sigil),
     AutoDerefRef(AutoDerefRef)
 }
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Decodable, Encodable)]
 pub struct AutoDerefRef {
     autoderefs: uint,
     autoref: Option<AutoRef>
 }
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Decodable, Encodable)]
 pub enum AutoRef {
     /// Convert from T to &T
     AutoPtr(Region, ast::mutability),
@@ -241,7 +250,6 @@ struct ctxt_ {
     diag: @syntax::diagnostic::span_handler,
     interner: @mut HashMap<intern_key, ~t_box_>,
     next_id: @mut uint,
-    vecs_implicitly_copyable: bool,
     legacy_modes: bool,
     cstore: @mut metadata::cstore::CStore,
     sess: session::Session,
@@ -262,13 +270,13 @@ struct ctxt_ {
     node_type_substs: @mut HashMap<node_id, ~[t]>,
 
     // Maps from a method to the method "descriptor"
-    methods: @mut HashMap<def_id, @method>,
+    methods: @mut HashMap<def_id, @Method>,
 
     // Maps from a trait def-id to a list of the def-ids of its methods
     trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,
 
     // A cache for the trait_methods() routine
-    trait_methods_cache: @mut HashMap<def_id, @~[@method]>,
+    trait_methods_cache: @mut HashMap<def_id, @~[@Method]>,
 
     trait_refs: @mut HashMap<node_id, @TraitRef>,
     trait_defs: @mut HashMap<def_id, @TraitDef>,
@@ -382,7 +390,8 @@ pub struct ClosureTy {
     sigil: ast::Sigil,
     onceness: ast::Onceness,
     region: Region,
-    sig: FnSig
+    bounds: BuiltinBounds,
+    sig: FnSig,
 }
 
 /**
@@ -395,7 +404,7 @@ pub struct ClosureTy {
 #[deriving(Eq)]
 pub struct FnSig {
     bound_lifetime_names: OptVec<ast::ident>,
-    inputs: ~[arg],
+    inputs: ~[t],
     output: t
 }
 
@@ -434,9 +443,7 @@ pub struct param_ty {
 }
 
 /// Representation of regions:
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq, IterBytes)]
+#[deriving(Eq, IterBytes, Encodable, Decodable)]
 pub enum Region {
     /// Bound regions are found (primarily) in function types.  They indicate
     /// region parameters that have yet to be replaced with actual regions
@@ -482,17 +489,13 @@ pub impl Region {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq, IterBytes)]
+#[deriving(Eq, IterBytes, Encodable, Decodable)]
 pub struct FreeRegion {
     scope_id: node_id,
     bound_region: bound_region
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq, IterBytes)]
+#[deriving(Eq, IterBytes, Encodable, Decodable)]
 pub enum bound_region {
     /// The self region for structs, impls (&T in a type defn or &'self T)
     br_self,
@@ -683,6 +686,7 @@ pub enum type_err {
     terr_int_mismatch(expected_found<IntVarValue>),
     terr_float_mismatch(expected_found<ast::float_ty>),
     terr_traits(expected_found<ast::def_id>),
+    terr_builtin_bounds(expected_found<BuiltinBounds>),
 }
 
 #[deriving(Eq, IterBytes)]
@@ -705,6 +709,15 @@ pub fn EmptyBuiltinBounds() -> BuiltinBounds {
     EnumSet::empty()
 }
 
+pub fn AllBuiltinBounds() -> BuiltinBounds {
+    let mut set = EnumSet::empty();
+    set.add(BoundCopy);
+    set.add(BoundStatic);
+    set.add(BoundOwned);
+    set.add(BoundConst);
+    set
+}
+
 impl CLike for BuiltinBound {
     pub fn to_uint(&self) -> uint {
         *self as uint
@@ -723,9 +736,7 @@ pub struct IntVid(uint);
 #[deriving(Eq)]
 pub struct FloatVid(uint);
 
-#[deriving(Eq)]
-#[auto_encode]
-#[auto_decode]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct RegionVid {
     id: uint
 }
@@ -758,8 +769,7 @@ impl to_bytes::IterBytes for InferTy {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub enum InferRegion {
     ReVar(RegionVid),
     ReSkolemized(uint, bound_region)
@@ -992,14 +1002,10 @@ pub fn mk_ctxt(s: session::Session,
         }
     }
 
-    let vecs_implicitly_copyable =
-        get_lint_level(s.lint_settings.default_settings,
-                       lint::vecs_implicitly_copyable) == allow;
     @ctxt_ {
         diag: s.diagnostic(),
         interner: @mut HashMap::new(),
         next_id: @mut primitives::LAST_PRIMITIVE_ID,
-        vecs_implicitly_copyable: vecs_implicitly_copyable,
         legacy_modes: legacy_modes,
         cstore: s.cstore,
         sess: s,
@@ -1114,14 +1120,14 @@ fn mk_t(cx: ctxt, st: sty) -> t {
       }
       &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
       &ty_bare_fn(ref f) => {
-        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
+        for f.sig.inputs.each |a| { flags |= get(*a).flags; }
          flags |= get(f.sig.output).flags;
          // T -> _|_ is *not* _|_ !
          flags &= !(has_ty_bot as uint);
       }
       &ty_closure(ref f) => {
         flags |= rflags(f.region);
-        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
+        for f.sig.inputs.each |a| { flags |= get(*a).flags; }
         flags |= get(f.sig.output).flags;
         // T -> _|_ is *not* _|_ !
         flags &= !(has_ty_bot as uint);
@@ -1305,7 +1311,7 @@ pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
 }
 
 pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
-    let input_args = input_tys.map(|t| arg { ty: *t });
+    let input_args = input_tys.map(|t| *t);
     mk_bare_fn(cx,
                BareFnTy {
                    purity: ast::pure_fn,
@@ -1379,11 +1385,11 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
       }
       ty_tup(ref ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
       ty_bare_fn(ref ft) => {
-        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
+        for ft.sig.inputs.each |a| { maybe_walk_ty(*a, f); }
         maybe_walk_ty(ft.sig.output, f);
       }
       ty_closure(ref ft) => {
-        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
+        for ft.sig.inputs.each |a| { maybe_walk_ty(*a, f); }
         maybe_walk_ty(ft.sig.output, f);
       }
     }
@@ -1394,11 +1400,7 @@ pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
 }
 
 pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
-    let args = do sig.inputs.map |arg| {
-        arg {
-            ty: fldop(arg.ty)
-        }
-    };
+    let args = sig.inputs.map(|arg| fldop(*arg));
 
     FnSig {
         bound_lifetime_names: copy sig.bound_lifetime_names,
@@ -1687,7 +1689,7 @@ pub fn simd_type(cx: ctxt, ty: t) -> t {
             let fields = lookup_struct_fields(cx, did);
             lookup_field_type(cx, did, fields[0].id, substs)
         }
-        _ => fail!(~"simd_type called on invalid type")
+        _ => fail!("simd_type called on invalid type")
     }
 }
 
@@ -1697,14 +1699,14 @@ pub fn simd_size(cx: ctxt, ty: t) -> uint {
             let fields = lookup_struct_fields(cx, did);
             fields.len()
         }
-        _ => fail!(~"simd_size called on invalid type")
+        _ => fail!("simd_size called on invalid type")
     }
 }
 
 pub fn get_element_type(ty: t, i: uint) -> t {
     match get(ty).sty {
       ty_tup(ref ts) => return ts[i],
-      _ => fail!(~"get_element_type called on invalid type")
+      _ => fail!("get_element_type called on invalid type")
     }
 }
 
@@ -1946,8 +1948,7 @@ pub impl TypeContents {
     }
 
     fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
-        let base = TypeContents::noncopyable(cx) + TC_OWNED_POINTER;
-        if cx.vecs_implicitly_copyable {base} else {base + TC_OWNED_VEC}
+        TypeContents::noncopyable(cx) + TC_OWNED_POINTER + TC_OWNED_VEC
     }
 
     fn needs_drop(&self, cx: ctxt) -> bool {
@@ -2624,7 +2625,7 @@ pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
 
       ty_enum(did, ref substs) => {
         let variants = enum_variants(cx, did);
-        if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
+        if (*variants).len() == 1u && variants[0].args.len() == 1u {
             let v_t = subst(cx, substs, variants[0].args[0]);
             Some(mt {ty: v_t, mutbl: ast::m_imm})
         } else {
@@ -3001,18 +3002,18 @@ pub fn ty_fn_sig(fty: t) -> FnSig {
         ty_bare_fn(ref f) => copy f.sig,
         ty_closure(ref f) => copy f.sig,
         ref s => {
-            fail!(fmt!("ty_fn_sig() called on non-fn type: %?", s))
+            fail!("ty_fn_sig() called on non-fn type: %?", s)
         }
     }
 }
 
 // Type accessors for substructures of types
-pub fn ty_fn_args(fty: t) -> ~[arg] {
+pub fn ty_fn_args(fty: t) -> ~[t] {
     match get(fty).sty {
         ty_bare_fn(ref f) => copy f.sig.inputs,
         ty_closure(ref f) => copy f.sig.inputs,
         ref s => {
-            fail!(fmt!("ty_fn_args() called on non-fn type: %?", s))
+            fail!("ty_fn_args() called on non-fn type: %?", s)
         }
     }
 }
@@ -3021,8 +3022,7 @@ pub fn ty_closure_sigil(fty: t) -> Sigil {
     match get(fty).sty {
         ty_closure(ref f) => f.sigil,
         ref s => {
-            fail!(fmt!("ty_closure_sigil() called on non-closure type: %?",
-                       s))
+            fail!("ty_closure_sigil() called on non-closure type: %?", s)
         }
     }
 }
@@ -3032,7 +3032,7 @@ pub fn ty_fn_purity(fty: t) -> ast::purity {
         ty_bare_fn(ref f) => f.purity,
         ty_closure(ref f) => f.purity,
         ref s => {
-            fail!(fmt!("ty_fn_purity() called on non-fn type: %?", s))
+            fail!("ty_fn_purity() called on non-fn type: %?", s)
         }
     }
 }
@@ -3042,7 +3042,7 @@ pub fn ty_fn_ret(fty: t) -> t {
         ty_bare_fn(ref f) => f.sig.output,
         ty_closure(ref f) => f.sig.output,
         ref s => {
-            fail!(fmt!("ty_fn_ret() called on non-fn type: %?", s))
+            fail!("ty_fn_ret() called on non-fn type: %?", s)
         }
     }
 }
@@ -3059,7 +3059,7 @@ pub fn ty_vstore(ty: t) -> vstore {
     match get(ty).sty {
         ty_evec(_, vstore) => vstore,
         ty_estr(vstore) => vstore,
-        ref s => fail!(fmt!("ty_vstore() called on invalid sty: %?", s))
+        ref s => fail!("ty_vstore() called on invalid sty: %?", s)
     }
 }
 
@@ -3112,7 +3112,7 @@ pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
 
 // Returns a vec of all the input and output types of fty.
 pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
-    vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
+    vec::append_one(sig.inputs.map(|a| *a), sig.output)
 }
 
 // Type accessors for AST nodes
@@ -3180,6 +3180,7 @@ pub fn adjust_ty(cx: ctxt,
                                        sigil: s,
                                        onceness: ast::Many,
                                        region: r,
+                                       bounds: ty::AllBuiltinBounds(),
                                        sig: copy b.sig})
                 }
                 ref b => {
@@ -3383,7 +3384,7 @@ pub fn expr_kind(tcx: ctxt,
     }
 
     match expr.node {
-        ast::expr_path(*) => {
+        ast::expr_path(*) | ast::expr_self => {
             match resolve_expr(tcx, expr) {
                 ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
 
@@ -3496,7 +3497,7 @@ pub fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
       ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
         return id;
       }
-      ast::stmt_mac(*) => fail!(~"unexpanded macro in trans")
+      ast::stmt_mac(*) => fail!("unexpanded macro in trans")
     }
 }
 
@@ -3516,7 +3517,7 @@ pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
         fields.map(|f| tcx.sess.str_of(f.ident))));
 }
 
-pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
+pub fn method_idx(id: ast::ident, meths: &[@Method]) -> Option<uint> {
     vec::position(meths, |m| m.ident == id)
 }
 
@@ -3708,6 +3709,19 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
                  item_path_str(cx, values.expected),
                  item_path_str(cx, values.found))
         }
+        terr_builtin_bounds(values) => {
+            if values.expected.is_empty() {
+                fmt!("expected no bounds but found `%s`",
+                     values.found.user_string(cx))
+            } else if values.found.is_empty() {
+                fmt!("expected bounds `%s` but found no bounds",
+                     values.expected.user_string(cx))
+            } else {
+                fmt!("expected bounds `%s` but found bounds `%s`",
+                     values.expected.user_string(cx),
+                     values.found.user_string(cx))
+            }
+        }
         terr_self_substs => {
             ~"inconsistent self substitution" // XXX this is more of a bug
         }
@@ -3833,20 +3847,19 @@ fn lookup_locally_or_in_crate_store<V:Copy>(
     }
 
     if def_id.crate == ast::local_crate {
-        fail!(fmt!("No def'n found for %? in tcx.%s",
-                   def_id, descr));
+        fail!("No def'n found for %? in tcx.%s", def_id, descr);
     }
     let v = load_external();
     map.insert(def_id, v);
     return v;
 }
 
-pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
+pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method {
     let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
     ty::method(cx, method_def_id)
 }
 
-pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
+pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] {
     match cx.trait_methods_cache.find(&trait_did) {
         Some(&methods) => methods,
         None => {
@@ -3858,7 +3871,7 @@ pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
     }
 }
 
-pub fn method(cx: ctxt, id: ast::def_id) -> @method {
+pub fn method(cx: ctxt, id: ast::def_id) -> @Method {
     lookup_locally_or_in_crate_store(
         "methods", id, cx.methods,
         || @csearch::get_method(cx, id))
@@ -3870,23 +3883,23 @@ pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
         || @csearch::get_trait_method_def_ids(cx.cstore, id))
 }
 
-pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
+pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
     if id.crate == ast::local_crate {
-        debug!("(impl_traits) searching for trait impl %?", id);
+        debug!("(impl_trait_ref) searching for trait impl %?", id);
         match cx.items.find(&id.node) {
            Some(&ast_map::node_item(@ast::item {
                         node: ast::item_impl(_, opt_trait, _, _),
                         _},
                     _)) => {
                match opt_trait {
-                   Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
-                   None => ~[]
+                   Some(t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
+                   None => None
                }
            }
-           _ => ~[]
+           _ => None
         }
     } else {
-        csearch::get_impl_traits(cx, id)
+        csearch::get_impl_trait(cx, id)
     }
 }
 
@@ -4071,7 +4084,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
                         let ctor_ty = node_id_to_type(cx, variant.node.id);
                         let arg_tys = {
                             if args.len() > 0u {
-                                ty_fn_args(ctor_ty).map(|a| a.ty)
+                                ty_fn_args(ctor_ty).map(|a| *a)
                             } else {
                                 ~[]
                             }
@@ -4095,7 +4108,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
                          }
                     }
                     ast::struct_variant_kind(_) => {
-                        fail!(~"struct variant kinds unimpl in enum_variants")
+                        fail!("struct variant kinds unimpl in enum_variants")
                     }
                 }
             })
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 0baad7e7b7a..222493b0564 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -53,12 +53,13 @@
  */
 
 use middle::const_eval;
-use middle::ty::{arg, substs};
+use middle::ty::{substs};
 use middle::ty::{ty_param_substs_and_ty};
 use middle::ty;
 use middle::typeck::rscope::in_binding_rscope;
 use middle::typeck::rscope::{region_scope, RegionError};
 use middle::typeck::rscope::RegionParamNames;
+use middle::typeck::lookup_def_tcx;
 
 use syntax::abi::AbiSet;
 use syntax::{ast, ast_util};
@@ -102,7 +103,7 @@ pub fn get_region_reporting_err(
 }
 
 pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     default_span: span,
     opt_lifetime: Option<@ast::Lifetime>) -> ty::Region
@@ -111,7 +112,7 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + 'static>(
         None => {
             (default_span, rscope.anon_region(default_span))
         }
-        Some(ref lifetime) if lifetime.ident == special_idents::static => {
+        Some(ref lifetime) if lifetime.ident == special_idents::statik => {
             (lifetime.span, Ok(ty::re_static))
         }
         Some(ref lifetime) if lifetime.ident == special_idents::self_ => {
@@ -123,11 +124,11 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + 'static>(
         }
     };
 
-    get_region_reporting_err(self.tcx(), span, opt_lifetime, res)
+    get_region_reporting_err(this.tcx(), span, opt_lifetime, res)
 }
 
 fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     def_id: ast::def_id,
     decl_generics: &ty::Generics,
@@ -141,9 +142,9 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
      * set of substitutions for this particular reference to `I`.
      */
 
-    let tcx = self.tcx();
+    let tcx = this.tcx();
 
-    // If the type is parameterized by the self region, then replace self
+    // If the type is parameterized by the this region, then replace this
     // region with the current anon region binding (in other words,
     // whatever & would get replaced with).
     let self_r = match (&decl_generics.region_param, &path.rp) {
@@ -160,55 +161,55 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + 'static>(
       }
       (&Some(_), &None) => {
         let res = rscope.anon_region(path.span);
-        let r = get_region_reporting_err(self.tcx(), path.span, None, res);
+        let r = get_region_reporting_err(this.tcx(), path.span, None, res);
         Some(r)
       }
       (&Some(_), &Some(_)) => {
-        Some(ast_region_to_region(self, rscope, path.span, path.rp))
+        Some(ast_region_to_region(this, rscope, path.span, path.rp))
       }
     };
 
     // Convert the type parameters supplied by the user.
     if !vec::same_length(*decl_generics.type_param_defs, path.types) {
-        self.tcx().sess.span_fatal(
+        this.tcx().sess.span_fatal(
             path.span,
             fmt!("wrong number of type arguments: expected %u but found %u",
                  decl_generics.type_param_defs.len(), path.types.len()));
     }
-    let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t));
+    let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, *a_t));
 
     substs {self_r:self_r, self_ty:self_ty, tps:tps}
 }
 
 pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     did: ast::def_id,
     path: @ast::Path) -> ty_param_substs_and_ty
 {
-    let tcx = self.tcx();
+    let tcx = this.tcx();
     let ty::ty_param_bounds_and_ty {
         generics: generics,
         ty: decl_ty
-    } = self.get_item_ty(did);
+    } = this.get_item_ty(did);
 
-    let substs = ast_path_substs(self, rscope, did, &generics, None, path);
+    let substs = ast_path_substs(this, rscope, did, &generics, None, path);
     let ty = ty::subst(tcx, &substs, decl_ty);
     ty_param_substs_and_ty { substs: substs, ty: ty }
 }
 
 pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     trait_def_id: ast::def_id,
     self_ty: Option<ty::t>,
     path: @ast::Path) -> @ty::TraitRef
 {
     let trait_def =
-        self.get_trait_def(trait_def_id);
+        this.get_trait_def(trait_def_id);
     let substs =
         ast_path_substs(
-            self,
+            this,
             rscope,
             trait_def.trait_ref.def_id,
             &trait_def.generics,
@@ -220,9 +221,8 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + 'static>(
     return trait_ref;
 }
 
-
 pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
-        self: &AC,
+        this: &AC,
         rscope: &RS,
         did: ast::def_id,
         path: @ast::Path)
@@ -233,7 +233,7 @@ pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
     let ty::ty_param_substs_and_ty {
         substs: substs,
         ty: ty
-    } = ast_path_to_substs_and_ty(self, rscope, did, path);
+    } = ast_path_to_substs_and_ty(this, rscope, did, path);
     ty_param_substs_and_ty { substs: substs, ty: ty }
 }
 
@@ -244,29 +244,29 @@ pub static NO_TPS: uint = 2;
 // internal notion of a type. `getter` is a function that returns the type
 // corresponding to a definition ID:
 pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
-    self: &AC, rscope: &RS, ast_ty: @ast::Ty) -> ty::t {
+    this: &AC, rscope: &RS, ast_ty: @ast::Ty) -> ty::t {
 
     fn ast_mt_to_mt<AC:AstConv, RS:region_scope + Copy + 'static>(
-        self: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt {
+        this: &AC, rscope: &RS, mt: &ast::mt) -> ty::mt {
 
-        ty::mt {ty: ast_ty_to_ty(self, rscope, mt.ty), mutbl: mt.mutbl}
+        ty::mt {ty: ast_ty_to_ty(this, rscope, mt.ty), mutbl: mt.mutbl}
     }
 
     // Handle @, ~, and & being able to mean estrs and evecs.
     // If a_seq_ty is a str or a vec, make it an estr/evec.
     // Also handle first-class trait types.
     fn mk_pointer<AC:AstConv,RS:region_scope + Copy + 'static>(
-        self: &AC,
+        this: &AC,
         rscope: &RS,
         a_seq_ty: &ast::mt,
         vst: ty::vstore,
         constr: &fn(ty::mt) -> ty::t) -> ty::t
     {
-        let tcx = self.tcx();
+        let tcx = this.tcx();
 
         match a_seq_ty.ty.node {
             ast::ty_vec(ref mt) => {
-                let mut mt = ast_mt_to_mt(self, rscope, mt);
+                let mut mt = ast_mt_to_mt(this, rscope, mt);
                 if a_seq_ty.mutbl == ast::m_mutbl ||
                         a_seq_ty.mutbl == ast::m_const {
                     mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
@@ -281,7 +281,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
                     }
                     Some(&ast::def_trait(trait_def_id)) => {
                         let result = ast_path_to_trait_ref(
-                            self, rscope, trait_def_id, None, path);
+                            this, rscope, trait_def_id, None, path);
                         let trait_store = match vst {
                             ty::vstore_box => ty::BoxTraitStore,
                             ty::vstore_uniq => ty::UniqTraitStore,
@@ -308,7 +308,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
             _ => {}
         }
 
-        let seq_ty = ast_mt_to_mt(self, rscope, a_seq_ty);
+        let seq_ty = ast_mt_to_mt(this, rscope, a_seq_ty);
         return constr(seq_ty);
     }
 
@@ -332,7 +332,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
         }
     }
 
-    let tcx = self.tcx();
+    let tcx = this.tcx();
 
     match tcx.ast_ty_to_ty_cache.find(&ast_ty.id) {
       Some(&ty::atttce_resolved(ty)) => return ty,
@@ -348,40 +348,42 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
       ast::ty_nil => ty::mk_nil(),
       ast::ty_bot => ty::mk_bot(),
       ast::ty_box(ref mt) => {
-        mk_pointer(self, rscope, mt, ty::vstore_box,
+        mk_pointer(this, rscope, mt, ty::vstore_box,
                    |tmt| ty::mk_box(tcx, tmt))
       }
       ast::ty_uniq(ref mt) => {
-        mk_pointer(self, rscope, mt, ty::vstore_uniq,
+        mk_pointer(this, rscope, mt, ty::vstore_uniq,
                    |tmt| ty::mk_uniq(tcx, tmt))
       }
       ast::ty_vec(ref mt) => {
         tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
         // return /something/ so they can at least get more errors
-        ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, mt), ty::vstore_uniq)
+        ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, mt), ty::vstore_uniq)
       }
       ast::ty_ptr(ref mt) => {
-        ty::mk_ptr(tcx, ast_mt_to_mt(self, rscope, mt))
+        ty::mk_ptr(tcx, ast_mt_to_mt(this, rscope, mt))
       }
       ast::ty_rptr(region, ref mt) => {
-        let r = ast_region_to_region(self, rscope, ast_ty.span, region);
-        mk_pointer(self, rscope, mt, ty::vstore_slice(r),
+        let r = ast_region_to_region(this, rscope, ast_ty.span, region);
+        mk_pointer(this, rscope, mt, ty::vstore_slice(r),
                    |tmt| ty::mk_rptr(tcx, r, tmt))
       }
       ast::ty_tup(ref fields) => {
-        let flds = fields.map(|t| ast_ty_to_ty(self, rscope, *t));
+        let flds = fields.map(|t| ast_ty_to_ty(this, rscope, *t));
         ty::mk_tup(tcx, flds)
       }
       ast::ty_bare_fn(ref bf) => {
-          ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity,
+          ty::mk_bare_fn(tcx, ty_of_bare_fn(this, rscope, bf.purity,
                                             bf.abis, &bf.lifetimes, &bf.decl))
       }
       ast::ty_closure(ref f) => {
-          let fn_decl = ty_of_closure(self,
+          let bounds = conv_builtin_bounds(this.tcx(), &f.bounds);
+          let fn_decl = ty_of_closure(this,
                                       rscope,
                                       f.sigil,
                                       f.purity,
                                       f.onceness,
+                                      bounds,
                                       f.region,
                                       &f.decl,
                                       None,
@@ -407,7 +409,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
               ty::mk_err()
           }
           ast::def_ty(did) | ast::def_struct(did) => {
-            ast_path_to_ty(self, rscope, did, path).ty
+            ast_path_to_ty(this, rscope, did, path).ty
           }
           ast::def_prim_ty(nty) => {
             match nty {
@@ -440,7 +442,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
             ty::mk_param(tcx, n, id)
           }
           ast::def_self_ty(id) => {
-            // n.b.: resolve guarantees that the self type only appears in a
+            // 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);
@@ -458,10 +460,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
           Ok(ref r) => {
             match *r {
               const_eval::const_int(i) =>
-                ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, a_mt),
+                ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, a_mt),
                             ty::vstore_fixed(i as uint)),
               const_eval::const_uint(i) =>
-                ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, a_mt),
+                ty::mk_evec(tcx, ast_mt_to_mt(this, rscope, a_mt),
                             ty::vstore_fixed(i as uint)),
               _ => {
                 tcx.sess.span_fatal(
@@ -482,7 +484,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
         // values in a fn_expr, or as the type of local variables.  Both of
         // these cases are handled specially and should not descend into this
         // routine.
-        self.tcx().sess.span_bug(
+        this.tcx().sess.span_bug(
             ast_ty.span,
             "found `ty_infer` in unexpected place");
       }
@@ -498,45 +500,41 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + 'static>(
 
 pub fn ty_of_arg<AC:AstConv,
                  RS:region_scope + Copy + 'static>(
-                 self: &AC,
+                 this: &AC,
                  rscope: &RS,
                  a: ast::arg,
-                 expected_ty: Option<ty::arg>)
-                 -> ty::arg {
-    let ty = match a.ty.node {
-        ast::ty_infer if expected_ty.is_some() => expected_ty.get().ty,
-        ast::ty_infer => self.ty_infer(a.ty.span),
-        _ => ast_ty_to_ty(self, rscope, a.ty),
-    };
-
-    arg {
-        ty: ty
+                 expected_ty: Option<ty::t>)
+                 -> ty::t {
+    match a.ty.node {
+        ast::ty_infer if expected_ty.is_some() => expected_ty.get(),
+        ast::ty_infer => this.ty_infer(a.ty.span),
+        _ => ast_ty_to_ty(this, rscope, a.ty),
     }
 }
 
 pub fn bound_lifetimes<AC:AstConv>(
-    self: &AC,
+    this: &AC,
     ast_lifetimes: &OptVec<ast::Lifetime>) -> OptVec<ast::ident>
 {
     /*!
      *
      * Converts a list of lifetimes into a list of bound identifier
-     * names.  Does not permit special names like 'static or 'self to
+     * names.  Does not permit special names like 'static or 'this to
      * be bound.  Note that this function is for use in closures,
-     * methods, and fn definitions.  It is legal to bind 'self in a
+     * methods, and fn definitions.  It is legal to bind 'this in a
      * type.  Eventually this distinction should go away and the same
-     * rules should apply everywhere ('self would not be a special name
+     * rules should apply everywhere ('this would not be a special name
      * at that point).
      */
 
-    let special_idents = [special_idents::static, special_idents::self_];
+    let special_idents = [special_idents::statik, special_idents::self_];
     let mut bound_lifetime_names = opt_vec::Empty;
     ast_lifetimes.map_to_vec(|ast_lifetime| {
         if special_idents.any(|&i| i == ast_lifetime.ident) {
-            self.tcx().sess.span_err(
+            this.tcx().sess.span_err(
                 ast_lifetime.span,
                 fmt!("illegal lifetime parameter name: `%s`",
-                     lifetime_to_str(ast_lifetime, self.tcx().sess.intr())));
+                     lifetime_to_str(ast_lifetime, this.tcx().sess.intr())));
         } else {
             bound_lifetime_names.push(ast_lifetime.ident);
         }
@@ -546,29 +544,29 @@ pub fn bound_lifetimes<AC:AstConv>(
 
 struct SelfInfo {
     untransformed_self_ty: ty::t,
-    self_transform: ast::self_ty
+    explicit_self: ast::explicit_self
 }
 
 pub fn ty_of_method<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     purity: ast::purity,
     lifetimes: &OptVec<ast::Lifetime>,
     untransformed_self_ty: ty::t,
-    self_transform: ast::self_ty,
+    explicit_self: ast::explicit_self,
     decl: &ast::fn_decl) -> (Option<ty::t>, ty::BareFnTy)
 {
     let self_info = SelfInfo {
         untransformed_self_ty: untransformed_self_ty,
-        self_transform: self_transform
+        explicit_self: explicit_self
     };
     let (a, b) = ty_of_method_or_bare_fn(
-        self, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl);
+        this, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl);
     (a.get(), b)
 }
 
 pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     purity: ast::purity,
     abi: AbiSet,
@@ -576,12 +574,12 @@ pub fn ty_of_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
     decl: &ast::fn_decl) -> ty::BareFnTy
 {
     let (_, b) = ty_of_method_or_bare_fn(
-        self, rscope, purity, abi, lifetimes, None, decl);
+        this, rscope, purity, abi, lifetimes, None, decl);
     b
 }
 
 fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
-    self: &AC,
+    this: &AC,
     rscope: &RS,
     purity: ast::purity,
     abi: AbiSet,
@@ -593,18 +591,18 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
 
     // new region names that appear inside of the fn decl are bound to
     // that function type
-    let bound_lifetime_names = bound_lifetimes(self, lifetimes);
+    let bound_lifetime_names = bound_lifetimes(this, lifetimes);
     let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
 
     let opt_transformed_self_ty = opt_self_info.map(|&self_info| {
-        transform_self_ty(self, &rb, self_info)
+        transform_self_ty(this, &rb, self_info)
     });
 
-    let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None));
+    let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, *a, None));
 
     let output_ty = match decl.output.node {
-        ast::ty_infer => self.ty_infer(decl.output.span),
-        _ => ast_ty_to_ty(self, &rb, decl.output)
+        ast::ty_infer => this.ty_infer(decl.output.span),
+        _ => ast_ty_to_ty(this, &rb, decl.output)
     };
 
     return (opt_transformed_self_ty,
@@ -617,31 +615,31 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
             });
 
     fn transform_self_ty<AC:AstConv,RS:region_scope + Copy + 'static>(
-        self: &AC,
+        this: &AC,
         rscope: &RS,
         self_info: &SelfInfo) -> Option<ty::t>
     {
-        match self_info.self_transform.node {
+        match self_info.explicit_self.node {
             ast::sty_static => None,
             ast::sty_value => {
                 Some(self_info.untransformed_self_ty)
             }
             ast::sty_region(lifetime, mutability) => {
                 let region =
-                    ast_region_to_region(self, rscope,
-                                         self_info.self_transform.span,
+                    ast_region_to_region(this, rscope,
+                                         self_info.explicit_self.span,
                                          lifetime);
-                Some(ty::mk_rptr(self.tcx(), region,
+                Some(ty::mk_rptr(this.tcx(), region,
                                  ty::mt {ty: self_info.untransformed_self_ty,
                                          mutbl: mutability}))
             }
             ast::sty_box(mutability) => {
-                Some(ty::mk_box(self.tcx(),
+                Some(ty::mk_box(this.tcx(),
                                 ty::mt {ty: self_info.untransformed_self_ty,
                                         mutbl: mutability}))
             }
             ast::sty_uniq(mutability) => {
-                Some(ty::mk_uniq(self.tcx(),
+                Some(ty::mk_uniq(this.tcx(),
                                  ty::mt {ty: self_info.untransformed_self_ty,
                                          mutbl: mutability}))
             }
@@ -650,17 +648,18 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:region_scope + Copy + 'static>(
 }
 
 pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
-        self: &AC,
-        rscope: &RS,
-        sigil: ast::Sigil,
-        purity: ast::purity,
-        onceness: ast::Onceness,
-        opt_lifetime: Option<@ast::Lifetime>,
-        decl: &ast::fn_decl,
-        expected_sig: Option<ty::FnSig>,
-        lifetimes: &OptVec<ast::Lifetime>,
-        span: span)
-     -> ty::ClosureTy
+    this: &AC,
+    rscope: &RS,
+    sigil: ast::Sigil,
+    purity: ast::purity,
+    onceness: ast::Onceness,
+    bounds: ty::BuiltinBounds,
+    opt_lifetime: Option<@ast::Lifetime>,
+    decl: &ast::fn_decl,
+    expected_sig: Option<ty::FnSig>,
+    lifetimes: &OptVec<ast::Lifetime>,
+    span: span)
+    -> ty::ClosureTy
 {
     // The caller should not both provide explicit bound lifetime
     // names and expected types.  Either we infer the bound lifetime
@@ -674,7 +673,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
     // scope `rscope`, not the scope of the function parameters
     let bound_region = match opt_lifetime {
         Some(_) => {
-            ast_region_to_region(self, rscope, span, opt_lifetime)
+            ast_region_to_region(this, rscope, span, opt_lifetime)
         }
         None => {
             match sigil {
@@ -685,7 +684,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
                 }
                 ast::BorrowedSigil => {
                     // &fn() defaults as normal for an omitted lifetime:
-                    ast_region_to_region(self, rscope, span, opt_lifetime)
+                    ast_region_to_region(this, rscope, span, opt_lifetime)
                 }
             }
         }
@@ -693,7 +692,7 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
 
     // new region names that appear inside of the fn decl are bound to
     // that function type
-    let bound_lifetime_names = bound_lifetimes(self, lifetimes);
+    let bound_lifetime_names = bound_lifetimes(this, lifetimes);
     let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names));
 
     let input_tys = do decl.inputs.mapi |i, a| {
@@ -702,14 +701,14 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
             // were supplied
             if i < e.inputs.len() {Some(e.inputs[i])} else {None}
         };
-        ty_of_arg(self, &rb, *a, expected_arg_ty)
+        ty_of_arg(this, &rb, *a, expected_arg_ty)
     };
 
     let expected_ret_ty = expected_sig.map(|e| e.output);
     let output_ty = match decl.output.node {
         ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
-        ast::ty_infer => self.ty_infer(decl.output.span),
-        _ => ast_ty_to_ty(self, &rb, decl.output)
+        ast::ty_infer => this.ty_infer(decl.output.span),
+        _ => ast_ty_to_ty(this, &rb, decl.output)
     };
 
     ty::ClosureTy {
@@ -717,8 +716,69 @@ pub fn ty_of_closure<AC:AstConv,RS:region_scope + Copy + 'static>(
         sigil: sigil,
         onceness: onceness,
         region: bound_region,
+        bounds: bounds,
         sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names,
                         inputs: input_tys,
                         output: output_ty}
     }
 }
+
+fn conv_builtin_bounds(tcx: ty::ctxt,
+                       ast_bounds: &OptVec<ast::TyParamBound>)
+                       -> ty::BuiltinBounds {
+    //! Converts a list of bounds from the AST into a `BuiltinBounds`
+    //! struct. Reports an error if any of the bounds that appear
+    //! in the AST refer to general traits and not the built-in traits
+    //! like `Copy` or `Owned`. Used to translate the bounds that
+    //! appear in closure and trait types, where only builtin bounds are
+    //! legal.
+
+    let mut builtin_bounds = ty::EmptyBuiltinBounds();
+    for ast_bounds.each |ast_bound| {
+        match *ast_bound {
+            ast::TraitTyParamBound(b) => {
+                match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
+                    ast::def_trait(trait_did) => {
+                        if try_add_builtin_trait(tcx,
+                                                 trait_did,
+                                                 &mut builtin_bounds) {
+                            loop; // success
+                        }
+                    }
+                    _ => { }
+                }
+                tcx.sess.span_fatal(
+                    b.path.span,
+                    fmt!("only the builtin traits can be used \
+                          as closure or object bounds"));
+            }
+            ast::RegionTyParamBound => {
+                builtin_bounds.add(ty::BoundStatic);
+            }
+        }
+    }
+    builtin_bounds
+}
+
+pub fn try_add_builtin_trait(tcx: ty::ctxt,
+                             trait_def_id: ast::def_id,
+                             builtin_bounds: &mut ty::BuiltinBounds) -> bool {
+    //! Checks whether `trait_ref` refers to one of the builtin
+    //! traits, like `Copy` or `Owned`, and adds the corresponding
+    //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
+    //! is a builtin trait.
+
+    let li = &tcx.lang_items;
+    if trait_def_id == li.owned_trait() {
+        builtin_bounds.add(ty::BoundOwned);
+        true
+    } else if trait_def_id == li.copy_trait() {
+        builtin_bounds.add(ty::BoundCopy);
+        true
+    } else if trait_def_id == li.const_trait() {
+        builtin_bounds.add(ty::BoundConst);
+        true
+    } else {
+        false
+    }
+}
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 08398f9880a..9e8103f4527 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -170,7 +170,7 @@ pub struct LookupContext<'self> {
 pub struct Candidate {
     rcvr_ty: ty::t,
     rcvr_substs: ty::substs,
-    method_ty: @ty::method,
+    method_ty: @ty::Method,
     origin: method_origin,
 }
 
@@ -381,7 +381,7 @@ pub impl<'self> LookupContext<'self> {
             let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
             let pos = {
                 match trait_methods.position(|m| {
-                    m.self_ty != ast::sty_static &&
+                    m.explicit_self != ast::sty_static &&
                         m.ident == self.m_name })
                 {
                     Some(pos) => pos,
@@ -469,7 +469,7 @@ pub impl<'self> LookupContext<'self> {
                                           did: def_id,
                                           substs: &ty::substs) {
         struct MethodInfo {
-            method_ty: @ty::method,
+            method_ty: @ty::Method,
             trait_def_id: ast::def_id,
             index: uint
         }
@@ -830,10 +830,10 @@ pub impl<'self> LookupContext<'self> {
     }
 
     fn search_for_method(&self,
-                         self_ty: ty::t)
+                         rcvr_ty: ty::t)
         -> Option<method_map_entry>
     {
-        debug!("search_for_method(self_ty=%s)", self.ty_to_str(self_ty));
+        debug!("search_for_method(rcvr_ty=%s)", self.ty_to_str(rcvr_ty));
         let _indenter = indenter();
 
         // I am not sure that inherent methods should have higher
@@ -841,7 +841,7 @@ pub impl<'self> LookupContext<'self> {
         // existing code.
 
         debug!("searching inherent candidates");
-        match self.consider_candidates(self_ty, self.inherent_candidates) {
+        match self.consider_candidates(rcvr_ty, self.inherent_candidates) {
             None => {}
             Some(mme) => {
                 return Some(mme);
@@ -849,7 +849,7 @@ pub impl<'self> LookupContext<'self> {
         }
 
         debug!("searching extension candidates");
-        match self.consider_candidates(self_ty, self.extension_candidates) {
+        match self.consider_candidates(rcvr_ty, self.extension_candidates) {
             None => {
                 return None;
             }
@@ -860,12 +860,12 @@ pub impl<'self> LookupContext<'self> {
     }
 
     fn consider_candidates(&self,
-                           self_ty: ty::t,
+                           rcvr_ty: ty::t,
                            candidates: &mut ~[Candidate])
         -> Option<method_map_entry>
     {
         let relevant_candidates =
-            candidates.filter_to_vec(|c| self.is_relevant(self_ty, c));
+            candidates.filter_to_vec(|c| self.is_relevant(rcvr_ty, c));
 
         let relevant_candidates = self.merge_candidates(relevant_candidates);
 
@@ -882,7 +882,7 @@ pub impl<'self> LookupContext<'self> {
             }
         }
 
-        Some(self.confirm_candidate(self_ty, &relevant_candidates[0]))
+        Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0]))
     }
 
     fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
@@ -932,7 +932,7 @@ pub impl<'self> LookupContext<'self> {
     }
 
     fn confirm_candidate(&self,
-                         self_ty: ty::t,
+                         rcvr_ty: ty::t,
                          candidate: &Candidate)
         -> method_map_entry
     {
@@ -948,11 +948,11 @@ pub impl<'self> LookupContext<'self> {
         self.enforce_drop_trait_limitations(candidate);
 
         // static methods should never have gotten this far:
-        assert!(candidate.method_ty.self_ty != sty_static);
+        assert!(candidate.method_ty.explicit_self != sty_static);
 
         let transformed_self_ty = match candidate.origin {
             method_trait(*) => {
-                match candidate.method_ty.self_ty {
+                match candidate.method_ty.explicit_self {
                     sty_region(*) => {
                         // FIXME(#5762) again, preserving existing
                         // behavior here which (for &self) desires
@@ -1033,7 +1033,7 @@ pub impl<'self> LookupContext<'self> {
         let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
         debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));
 
-        let self_mode = get_mode_from_self_type(candidate.method_ty.self_ty);
+        let self_mode = get_mode_from_explicit_self(candidate.method_ty.explicit_self);
 
         // before we only checked whether self_ty could be a subtype
         // of rcvr_ty; now we actually make it so (this may cause
@@ -1041,11 +1041,11 @@ pub impl<'self> LookupContext<'self> {
         // nothing has changed in the meantime, this unification
         // should never fail.
         match self.fcx.mk_subty(false, self.self_expr.span,
-                                self_ty, transformed_self_ty) {
+                                rcvr_ty, transformed_self_ty) {
             result::Ok(_) => (),
             result::Err(_) => {
                 self.bug(fmt!("%s was a subtype of %s but now is not?",
-                              self.ty_to_str(self_ty),
+                              self.ty_to_str(rcvr_ty),
                               self.ty_to_str(transformed_self_ty)));
             }
         }
@@ -1053,11 +1053,9 @@ pub impl<'self> LookupContext<'self> {
         self.fcx.write_ty(self.callee_id, fty);
         self.fcx.write_substs(self.callee_id, all_substs);
         method_map_entry {
-            self_arg: arg {
-                ty: candidate.rcvr_ty,
-            },
+            self_ty: candidate.rcvr_ty,
             self_mode: self_mode,
-            explicit_self: candidate.method_ty.self_ty,
+            explicit_self: candidate.method_ty.explicit_self,
             origin: candidate.origin,
         }
     }
@@ -1116,9 +1114,11 @@ pub impl<'self> LookupContext<'self> {
         }
     }
 
-    fn is_relevant(&self, self_ty: ty::t, candidate: &Candidate) -> bool {
-        debug!("is_relevant(self_ty=%s, candidate=%s)",
-               self.ty_to_str(self_ty), self.cand_to_str(candidate));
+    // `rcvr_ty` is the type of the expression. It may be a subtype of a
+    // candidate method's `self_ty`.
+    fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
+        debug!("is_relevant(rcvr_ty=%s, candidate=%s)",
+               self.ty_to_str(rcvr_ty), self.cand_to_str(candidate));
 
         // Check for calls to object methods.  We resolve these differently.
         //
@@ -1126,7 +1126,7 @@ pub impl<'self> LookupContext<'self> {
         // on an @Trait object here and so forth
         match candidate.origin {
             method_trait(*) => {
-                match candidate.method_ty.self_ty {
+                match candidate.method_ty.explicit_self {
                     sty_static | sty_value => {
                         return false;
                     }
@@ -1136,7 +1136,7 @@ pub impl<'self> LookupContext<'self> {
                         // an &@Trait receiver (wacky)
                     }
                     sty_box(*) | sty_uniq(*) => {
-                        return self.fcx.can_mk_subty(self_ty,
+                        return self.fcx.can_mk_subty(rcvr_ty,
                                                      candidate.rcvr_ty).is_ok();
                     }
                 };
@@ -1144,17 +1144,17 @@ pub impl<'self> LookupContext<'self> {
             _ => {}
         }
 
-        return match candidate.method_ty.self_ty {
+        return match candidate.method_ty.explicit_self {
             sty_static => {
                 false
             }
 
             sty_value => {
-                self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok()
+                self.fcx.can_mk_subty(rcvr_ty, candidate.rcvr_ty).is_ok()
             }
 
             sty_region(_, m) => {
-                match ty::get(self_ty).sty {
+                match ty::get(rcvr_ty).sty {
                     ty::ty_rptr(_, mt) => {
                         mutability_matches(mt.mutbl, m) &&
                         self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
@@ -1165,7 +1165,7 @@ pub impl<'self> LookupContext<'self> {
             }
 
             sty_box(m) => {
-                match ty::get(self_ty).sty {
+                match ty::get(rcvr_ty).sty {
                     ty::ty_box(mt) => {
                         mutability_matches(mt.mutbl, m) &&
                         self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
@@ -1176,7 +1176,7 @@ pub impl<'self> LookupContext<'self> {
             }
 
             sty_uniq(m) => {
-                match ty::get(self_ty).sty {
+                match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(mt) => {
                         mutability_matches(mt.mutbl, m) &&
                         self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
@@ -1244,7 +1244,7 @@ pub impl<'self> LookupContext<'self> {
         let span = if did.crate == ast::local_crate {
             match self.tcx().items.find(&did.node) {
               Some(&ast_map::node_method(m, _, _)) => m.span,
-              _ => fail!(fmt!("report_static_candidate: bad item %?", did))
+              _ => fail!("report_static_candidate: bad item %?", did)
             }
         } else {
             self.expr.span
@@ -1301,8 +1301,8 @@ pub impl<'self> LookupContext<'self> {
     }
 }
 
-pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> SelfMode {
-    match self_type {
+pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMode {
+    match explicit_self {
         sty_value => ty::ByCopy,
         _ => ty::ByRef,
     }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 7f73ed94c03..8d32bb7f677 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -81,7 +81,7 @@ use middle::pat_util::pat_id_map;
 use middle::pat_util;
 use middle::ty::{FnSig, VariantInfo_};
 use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
-use middle::ty::{substs, arg, param_ty};
+use middle::ty::{substs, param_ty};
 use middle::ty;
 use middle::typeck::astconv::AstConv;
 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
@@ -352,7 +352,7 @@ pub fn check_fn(ccx: @mut CrateCtxt,
 
     relate_free_regions(tcx, opt_self_info.map(|s| s.self_ty), &fn_sig);
 
-    let arg_tys = fn_sig.inputs.map(|a| a.ty);
+    let arg_tys = fn_sig.inputs.map(|a| *a);
     let ret_ty = fn_sig.output;
 
     debug!("check_fn(arg_tys=%?, ret_ty=%?, opt_self_ty=%?)",
@@ -527,7 +527,7 @@ pub fn check_method(ccx: @mut CrateCtxt,
     let opt_self_info = method_ty.transformed_self_ty.map(|&ty| {
         SelfInfo {self_ty: ty,
                   self_id: method.self_id,
-                  span: method.self_ty.span}
+                  span: method.explicit_self.span}
     });
 
     check_bare_fn(
@@ -1192,7 +1192,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
     fn check_argument_types(
         fcx: @mut FnCtxt,
         sp: span,
-        fn_inputs: &[ty::arg],
+        fn_inputs: &[ty::t],
         callee_expr: @ast::expr,
         args: &[@ast::expr],
         sugar: ast::CallSugar,
@@ -1211,7 +1211,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         let supplied_arg_count = args.len();
         let expected_arg_count = fn_inputs.len();
         let formal_tys = if expected_arg_count == supplied_arg_count {
-            fn_inputs.map(|a| a.ty)
+            fn_inputs.map(|a| *a)
         } else {
             let suffix = match sugar {
                 ast::NoSugar => "",
@@ -1287,8 +1287,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         }
     }
 
-    fn err_args(len: uint) -> ~[ty::arg] {
-        vec::from_fn(len, |_| ty::arg { ty: ty::mk_err() })
+    fn err_args(len: uint) -> ~[ty::t] {
+        vec::from_fn(len, |_| ty::mk_err())
     }
 
     // A generic function for checking assignment expressions
@@ -1661,7 +1661,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         let (expected_sig,
              expected_purity,
              expected_sigil,
-             expected_onceness) = {
+             expected_onceness,
+             expected_bounds) = {
             match expected_sty {
                 Some(ty::ty_closure(ref cenv)) => {
                     let id = expr.id;
@@ -1669,11 +1670,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                         replace_bound_regions_in_fn_sig(
                             tcx, @Nil, None, &cenv.sig,
                             |br| ty::re_bound(ty::br_cap_avoid(id, @br)));
-                    (Some(sig), cenv.purity, cenv.sigil, cenv.onceness)
+                    (Some(sig), cenv.purity, cenv.sigil,
+                     cenv.onceness, cenv.bounds)
                 }
                 _ => {
                     // Not an error! Means we're inferring the closure type
-                    (None, ast::impure_fn, ast::BorrowedSigil, ast::Many)
+                    (None, ast::impure_fn, ast::BorrowedSigil,
+                     ast::Many, ty::EmptyBuiltinBounds())
                 }
             }
         };
@@ -1687,25 +1690,22 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
         // construct the function type
         let fn_ty = astconv::ty_of_closure(fcx,
-                                               fcx,
-                                               sigil,
-                                               purity,
-                                               expected_onceness,
-                                               None,
-                                               decl,
-                                               expected_sig,
-                                               &opt_vec::Empty,
-                                               expr.span);
+                                           fcx,
+                                           sigil,
+                                           purity,
+                                           expected_onceness,
+                                           expected_bounds,
+                                           None,
+                                           decl,
+                                           expected_sig,
+                                           &opt_vec::Empty,
+                                           expr.span);
 
         let fty_sig;
         let fty = if error_happened {
             fty_sig = FnSig {
                 bound_lifetime_names: opt_vec::Empty,
-                inputs: fn_ty.sig.inputs.map(|_| {
-                    arg {
-                        ty: ty::mk_err()
-                    }
-                }),
+                inputs: fn_ty.sig.inputs.map(|_| ty::mk_err()),
                 output: ty::mk_err()
             };
             ty::mk_err()
@@ -2147,8 +2147,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                 inner_ty, fcx.expr_ty(loop_body));
             }
             ref n => {
-                fail!(fmt!(
-                    "check_loop_body expected expr_fn_block, not %?", n))
+                fail!("check_loop_body expected expr_fn_block, not %?", n)
             }
         }
 
@@ -2391,6 +2390,12 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
         instantiate_path(fcx, pth, tpt, expr.span, expr.id);
       }
+      ast::expr_self => {
+        let definition = lookup_def(fcx, expr.span, id);
+        let ty_param_bounds_and_ty =
+            ty_param_bounds_and_ty_for_def(fcx, expr.span, definition);
+        fcx.write_ty(id, ty_param_bounds_and_ty.ty);
+      }
       ast::expr_inline_asm(ref ia) => {
           fcx.require_unsafe(expr.span, ~"use of inline assembly");
 
@@ -2567,7 +2572,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
           }
           // argh
-          _ => fail!(~"expected fn ty")
+          _ => fail!("expected fn ty")
         }
         fcx.write_ty(expr.id, fcx.node_ty(b.id));
       }
@@ -3127,24 +3132,23 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
             }
             disr_vals.push(*disr_val);
             let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
-            let arg_tys;
 
             let this_disr_val = *disr_val;
             *disr_val += 1;
 
-            match v.node.kind {
+            let arg_tys = match v.node.kind {
                 ast::tuple_variant_kind(ref args) if args.len() > 0u => {
-                    arg_tys = Some(ty::ty_fn_args(ctor_ty).map(|a| a.ty));
+                    Some(ty::ty_fn_args(ctor_ty).map(|a| *a))
                 }
                 ast::tuple_variant_kind(_) => {
-                    arg_tys = Some(~[]);
+                    Some(~[])
                 }
                 ast::struct_variant_kind(_) => {
-                    arg_tys = Some(ty::lookup_struct_fields(
+                    Some(ty::lookup_struct_fields(
                         ccx.tcx, local_def(v.node.id)).map(|cf|
-                            ty::node_id_to_type(ccx.tcx, cf.id.node)));
+                            ty::node_id_to_type(ccx.tcx, cf.id.node)))
                 }
-            }
+            };
 
             match arg_tys {
                 None => {}
@@ -3276,7 +3280,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
     debug!(">>> instantiate_path");
 
     let ty_param_count = tpt.generics.type_param_defs.len();
-    let ty_substs_len = vec::len(pth.types);
+    let ty_substs_len = pth.types.len();
 
     debug!("ty_param_count=%? ty_substs_len=%?",
            ty_param_count,
@@ -3449,11 +3453,6 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
     fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
         ty::mk_param(ccx.tcx, n, local_def(0))
     }
-    fn arg(ty: ty::t) -> ty::arg {
-        arg {
-            ty: ty
-        }
-    }
 
     let tcx = ccx.tcx;
     let (n_tps, inputs, output) = match *ccx.tcx.sess.str_of(it.ident) {
@@ -3461,15 +3460,13 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
       ~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()),
       ~"init" => (1u, ~[], param(ccx, 0u)),
       ~"uninit" => (1u, ~[], param(ccx, 0u)),
-      ~"forget" => (1u, ~[arg(param(ccx, 0u))], ty::mk_nil()),
-      ~"transmute" => (2, ~[ arg(param(ccx, 0)) ], param(ccx, 1)),
+      ~"forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()),
+      ~"transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)),
       ~"move_val" | ~"move_val_init" => {
           (1u,
            ~[
-            arg(ty::mk_mut_rptr(tcx,
-                                ty::re_bound(ty::br_anon(0)),
-                                param(ccx, 0))),
-               arg(param(ccx, 0u))
+              ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)),
+              param(ccx, 0u)
             ],
          ty::mk_nil())
       }
@@ -3478,30 +3475,26 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
       ~"atomic_cxchg"    | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => {
         (0,
          ~[
-            arg(ty::mk_mut_rptr(tcx,
-                                ty::re_bound(ty::br_anon(0)),
-                                ty::mk_int())),
-               arg(ty::mk_int()),
-               arg(ty::mk_int())
+            ty::mk_mut_rptr(tcx,
+                            ty::re_bound(ty::br_anon(0)),
+                            ty::mk_int()),
+            ty::mk_int(),
+            ty::mk_int()
          ],
          ty::mk_int())
       }
       ~"atomic_load"     | ~"atomic_load_acq" => {
         (0,
          ~[
-            arg(ty::mk_imm_rptr(tcx,
-                            ty::re_bound(ty::br_anon(0)),
-                            ty::mk_int()))
+            ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int())
          ],
         ty::mk_int())
       }
       ~"atomic_store"    | ~"atomic_store_rel" => {
         (0,
          ~[
-            arg(ty::mk_mut_rptr(tcx,
-                                ty::re_bound(ty::br_anon(0)),
-                                ty::mk_int())),
-            arg(ty::mk_int())
+            ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
+            ty::mk_int()
          ],
          ty::mk_nil())
       }
@@ -3510,10 +3503,8 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
       ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => {
         (0,
          ~[
-            arg(ty::mk_mut_rptr(tcx,
-                                ty::re_bound(ty::br_anon(0)),
-                                ty::mk_int())),
-            arg(ty::mk_int())
+            ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
+            ty::mk_int()
          ],
          ty::mk_int())
       }
@@ -3531,7 +3522,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
             ty: tydesc_ty,
             mutbl: ast::m_imm
         });
-        (0, ~[ arg(td_ptr), arg(visitor_object_ty) ], ty::mk_nil())
+        (0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil())
       }
       ~"frame_address" => {
         let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
@@ -3539,18 +3530,14 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
             sigil: ast::BorrowedSigil,
             onceness: ast::Once,
             region: ty::re_bound(ty::br_anon(0)),
+            bounds: ty::EmptyBuiltinBounds(),
             sig: ty::FnSig {
                 bound_lifetime_names: opt_vec::Empty,
-                inputs: ~[
-                    arg {
-                        ty: ty::mk_imm_ptr(ccx.tcx,
-                                           ty::mk_mach_uint(ast::ty_u8))
-                    }
-                ],
+                inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))],
                 output: ty::mk_nil()
             }
         });
-        (0u, ~[ arg(fty) ], ty::mk_nil())
+        (0u, ~[fty], ty::mk_nil())
       }
       ~"morestack_addr" => {
         (0u, ~[], ty::mk_nil_ptr(ccx.tcx))
@@ -3558,101 +3545,102 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
       ~"memmove32" => {
         (0,
          ~[
-            arg(ty::mk_ptr(tcx, ty::mt {
+            ty::mk_ptr(tcx, ty::mt {
                 ty: ty::mk_u8(),
                 mutbl: ast::m_mutbl
-            })),
-            arg(ty::mk_ptr(tcx, ty::mt {
+            }),
+            ty::mk_ptr(tcx, ty::mt {
                 ty: ty::mk_u8(),
                 mutbl: ast::m_imm
-            })),
-            arg(ty::mk_u32())
+            }),
+            ty::mk_u32()
          ],
          ty::mk_nil())
       }
       ~"memmove64" => {
         (0,
-         ~[arg(ty::mk_ptr(tcx, ty::mt {
-            ty: ty::mk_u8(),
-            mutbl: ast::m_mutbl
-           })),
-           arg(ty::mk_ptr(tcx, ty::mt {
-            ty: ty::mk_u8(),
-            mutbl: ast::m_imm
-           })),
-           arg(ty::mk_u64())
+         ~[
+            ty::mk_ptr(tcx, ty::mt {
+                ty: ty::mk_u8(),
+                mutbl: ast::m_mutbl
+            }),
+            ty::mk_ptr(tcx, ty::mt {
+                ty: ty::mk_u8(),
+                mutbl: ast::m_imm
+            }),
+            ty::mk_u64()
          ],
          ty::mk_nil())
       }
-        ~"sqrtf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"sqrtf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+        ~"sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
         ~"powif32" => {
            (0,
-            ~[ arg(ty::mk_f32()), arg(ty::mk_i32()) ],
+            ~[ ty::mk_f32(), ty::mk_i32() ],
             ty::mk_f32())
         }
         ~"powif64" => {
            (0,
-            ~[ arg(ty::mk_f64()), arg(ty::mk_i32()) ],
+            ~[ ty::mk_f64(), ty::mk_i32() ],
             ty::mk_f64())
         }
-        ~"sinf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"sinf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"cosf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"cosf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+        ~"sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
         ~"powf32" => {
            (0,
-            ~[ arg(ty::mk_f32()), arg(ty::mk_f32()) ],
+            ~[ ty::mk_f32(), ty::mk_f32() ],
             ty::mk_f32())
         }
         ~"powf64" => {
            (0,
-            ~[ arg(ty::mk_f64()), arg(ty::mk_f64()) ],
+            ~[ ty::mk_f64(), ty::mk_f64() ],
             ty::mk_f64())
         }
-        ~"expf32"   => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"expf64"   => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"exp2f32"  => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"exp2f64"  => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"logf32"   => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"logf64"   => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"log10f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"log10f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"log2f32"  => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"log2f64"  => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+        ~"expf32"   => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"expf64"   => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"exp2f32"  => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"exp2f64"  => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"logf32"   => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"logf64"   => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"log2f32"  => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"log2f64"  => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
         ~"fmaf32" => {
             (0,
-             ~[ arg(ty::mk_f32()), arg(ty::mk_f32()), arg(ty::mk_f32()) ],
+             ~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ],
              ty::mk_f32())
         }
         ~"fmaf64" => {
             (0,
-             ~[ arg(ty::mk_f64()), arg(ty::mk_f64()), arg(ty::mk_f64()) ],
+             ~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ],
              ty::mk_f64())
         }
-        ~"fabsf32"  => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"fabsf64"  => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"floorf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"floorf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"ceilf32"  => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"ceilf64"  => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"truncf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
-        ~"truncf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
-        ~"ctpop8"   => (0, ~[ arg(ty::mk_i8())  ], ty::mk_i8()),
-        ~"ctpop16"  => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
-        ~"ctpop32"  => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
-        ~"ctpop64"  => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
-        ~"ctlz8"    => (0, ~[ arg(ty::mk_i8())  ], ty::mk_i8()),
-        ~"ctlz16"   => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
-        ~"ctlz32"   => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
-        ~"ctlz64"   => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
-        ~"cttz8"    => (0, ~[ arg(ty::mk_i8())  ], ty::mk_i8()),
-        ~"cttz16"   => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
-        ~"cttz32"   => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
-        ~"cttz64"   => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
-        ~"bswap16"  => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
-        ~"bswap32"  => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
-        ~"bswap64"  => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
+        ~"fabsf32"  => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"fabsf64"  => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"ceilf32"  => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"ceilf64"  => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
+        ~"truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
+        ~"ctpop8"   => (0, ~[ ty::mk_i8()  ], ty::mk_i8()),
+        ~"ctpop16"  => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
+        ~"ctpop32"  => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
+        ~"ctpop64"  => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
+        ~"ctlz8"    => (0, ~[ ty::mk_i8()  ], ty::mk_i8()),
+        ~"ctlz16"   => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
+        ~"ctlz32"   => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
+        ~"ctlz64"   => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
+        ~"cttz8"    => (0, ~[ ty::mk_i8()  ], ty::mk_i8()),
+        ~"cttz16"   => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
+        ~"cttz32"   => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
+        ~"cttz64"   => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
+        ~"bswap16"  => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
+        ~"bswap32"  => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
+        ~"bswap64"  => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
         ref other => {
             tcx.sess.span_err(it.span,
                               ~"unrecognized intrinsic function: `" +
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 55c1f03b330..ecec07ec512 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -993,7 +993,7 @@ pub mod guarantor {
                 guarantor(rcx, e)
             }
 
-            ast::expr_path(*) => {
+            ast::expr_path(*) | ast::expr_self => {
                 // Either a variable or constant and hence resides
                 // in constant memory or on the stack frame.  Either way,
                 // not guaranteed by a region pointer.
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index cfbd012b7b7..87b105e3c7d 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -258,7 +258,7 @@ pub fn relate_free_regions(
 
     let mut all_tys = ~[];
     for fn_sig.inputs.each |arg| {
-        all_tys.push(arg.ty);
+        all_tys.push(*arg);
     }
     for self_ty.each |&t| {
         all_tys.push(t);
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 12777159821..2e2b4550f63 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -140,7 +140,7 @@ fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
     do fixup_ty(vcx, location_info, t, is_early).map |t_f| {
         match ty::get(*t_f).sty {
           ty::ty_trait(_, ref substs_f, _, _) => (/*bad*/copy *substs_f),
-          _ => fail!(~"t_f should be a trait")
+          _ => fail!("t_f should be a trait")
         }
     }
 }
@@ -261,24 +261,14 @@ fn lookup_vtable(vcx: &VtableContext,
                         }
                         impls_seen.insert(im.did);
 
-                        // ty::impl_traits gives us the list of all
-                        // traits that im implements. Again, usually
-                        // there's just one.
+                        // ty::impl_traits gives us the trait im implements,
+                        // if there is one (there's either zero or one).
                         //
-                        // For example, if im represented the struct
-                        // in:
-                        //
-                        //   struct foo : baz<int>, bar, quux { ... }
-                        //
-                        // then ty::impl_traits would return
-                        //
-                        //   ~[baz<int>, bar, quux]
-                        //
-                        // For each of the traits foo implements, if
-                        // it's the same trait as trait_ref, we need to
+                        // If foo implements a trait t, and if t is the
+                        // same trait as trait_ref, we need to
                         // unify it with trait_ref in order to get all
                         // the ty vars sorted out.
-                        for ty::impl_trait_refs(tcx, im.did).each |&of_trait_ref|
+                        for ty::impl_trait_ref(tcx, im.did).each |&of_trait_ref|
                         {
                             if of_trait_ref.def_id != trait_ref.def_id { loop; }
 
@@ -456,8 +446,12 @@ fn connect_trait_tps(vcx: &VtableContext,
 {
     let tcx = vcx.tcx();
 
-    // XXX: This should work for multiple traits.
-    let impl_trait_ref = ty::impl_trait_refs(tcx, impl_did)[0];
+    let impl_trait_ref = match ty::impl_trait_ref(tcx, impl_did) {
+        Some(t) => t,
+        None => vcx.tcx().sess.span_bug(location_info.span,
+                                  "connect_trait_tps invoked on a type impl")
+    };
+
     let impl_trait_ref = (*impl_trait_ref).subst(tcx, impl_substs);
     relate_trait_refs(vcx, location_info, &impl_trait_ref, trait_ref);
 }
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 2869c3737c9..394d00bef2d 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -13,7 +13,6 @@
 // substitutions.
 
 use middle::pat_util;
-use middle::ty::arg;
 use middle::ty;
 use middle::typeck::check::{FnCtxt, SelfInfo};
 use middle::typeck::infer::{force_all, resolve_all, resolve_region};
@@ -63,14 +62,9 @@ fn resolve_method_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
     match fcx.inh.method_map.find(&id) {
         None => {}
         Some(mme) => {
-            for resolve_type_vars_in_type(fcx, sp, mme.self_arg.ty).each |t| {
+            for resolve_type_vars_in_type(fcx, sp, mme.self_ty).each |t| {
                 let method_map = fcx.ccx.method_map;
-                let new_entry = method_map_entry {
-                    self_arg: arg {
-                        ty: *t
-                    },
-                    ..*mme
-                };
+                let new_entry = method_map_entry { self_ty: *t, ..*mme };
                 debug!("writeback::resolve_method_map_entry(id=%?, \
                         new_entry=%?)",
                        id, new_entry);
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 260d3f440f9..311aa551601 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -16,7 +16,7 @@
 
 
 use driver;
-use metadata::csearch::{each_path, get_impl_traits};
+use metadata::csearch::{each_path, get_impl_trait};
 use metadata::csearch::{get_impls_for_mod};
 use metadata::csearch;
 use metadata::cstore::{CStore, iter_crate_data};
@@ -142,7 +142,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt,
                     return Some(def_id);
                 }
                 _ => {
-                    fail!(~"get_base_type() returned a type that wasn't an \
+                    fail!("get_base_type() returned a type that wasn't an \
                            enum, class, or trait");
                 }
             }
@@ -156,7 +156,7 @@ pub fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
         did: local_def(ast_method.id),
         n_tps: ast_method.generics.ty_params.len(),
         ident: ast_method.ident,
-        self_type: ast_method.self_ty.node
+        explicit_self: ast_method.explicit_self.node
     }
 }
 
@@ -383,7 +383,7 @@ pub impl CoherenceChecker {
                         did: new_did,
                         n_tps: trait_method.generics.type_param_defs.len(),
                         ident: trait_method.ident,
-                        self_type: trait_method.self_ty
+                        explicit_self: trait_method.explicit_self
                     },
                     trait_method_def_id: trait_method.def_id
                 };
@@ -527,7 +527,7 @@ pub impl CoherenceChecker {
     #[cfg(stage0)]
     fn each_provided_trait_method(&self,
             trait_did: ast::def_id,
-            f: &fn(x: @ty::method) -> bool) {
+            f: &fn(@ty::Method) -> bool) {
         // Make a list of all the names of the provided methods.
         // XXX: This is horrible.
         let mut provided_method_idents = HashSet::new();
@@ -547,7 +547,7 @@ pub impl CoherenceChecker {
     #[cfg(not(stage0))]
     fn each_provided_trait_method(&self,
             trait_did: ast::def_id,
-            f: &fn(x: @ty::method) -> bool) -> bool {
+            f: &fn(x: @ty::Method) -> bool) -> bool {
         // Make a list of all the names of the provided methods.
         // XXX: This is horrible.
         let mut provided_method_idents = HashSet::new();
@@ -898,13 +898,13 @@ pub impl CoherenceChecker {
 
             let self_type = lookup_item_type(self.crate_context.tcx,
                                              implementation.did);
-            let associated_traits = get_impl_traits(self.crate_context.tcx,
+            let associated_traits = get_impl_trait(self.crate_context.tcx,
                                                     implementation.did);
 
             // Do a sanity check to make sure that inherent methods have base
             // types.
 
-            if associated_traits.len() == 0 {
+            if associated_traits.is_none() {
                 match get_base_type_def_id(self.inference_context,
                                            dummy_sp(),
                                            self_type.ty) {
@@ -940,7 +940,7 @@ pub impl CoherenceChecker {
                 Some(base_type_def_id) => {
                     // inherent methods apply to `impl Type` but not
                     // `impl Trait for Type`:
-                    if associated_traits.len() == 0 {
+                    if associated_traits.is_none() {
                         self.add_inherent_method(base_type_def_id,
                                                  *implementation);
                     }
@@ -975,7 +975,7 @@ pub impl CoherenceChecker {
                         did: new_did,
                         n_tps: trait_method_info.ty.generics.type_param_defs.len(),
                         ident: trait_method_info.ty.ident,
-                        self_type: trait_method_info.ty.self_ty
+                        explicit_self: trait_method_info.ty.explicit_self
                     },
                     trait_method_def_id: trait_method_info.def_id
                 };
@@ -1073,7 +1073,7 @@ fn subst_receiver_types_in_method_ty(
     impl_id: ast::node_id,
     trait_ref: &ty::TraitRef,
     new_def_id: ast::def_id,
-    method: &ty::method) -> ty::method
+    method: &ty::Method) -> ty::Method
 {
     /*!
      * Substitutes the values for the receiver's type parameters
@@ -1117,19 +1117,22 @@ fn subst_receiver_types_in_method_ty(
         tps: combined_tps
     };
 
-    ty::method {
-        ident: method.ident,
+    ty::Method::new(
+        method.ident,
+
+        // method types *can* appear in the generic bounds
+        method.generics.subst(tcx, &combined_substs),
 
         // method tps cannot appear in the self_ty, so use `substs` from trait ref
-        transformed_self_ty: method.transformed_self_ty.subst(tcx, &trait_ref.substs),
-
-        // method types *can* appear in the generic bounds or the fty
-        generics: method.generics.subst(tcx, &combined_substs),
-        fty: method.fty.subst(tcx, &combined_substs),
-        self_ty: method.self_ty,
-        vis: method.vis,
-        def_id: new_def_id
-    }
+        method.transformed_self_ty.subst(tcx, &trait_ref.substs),
+
+        // method types *can* appear in the fty
+        method.fty.subst(tcx, &combined_substs),
+
+        method.explicit_self,
+        method.vis,
+        new_def_id
+    )
 }
 
 pub fn check_coherence(crate_context: @mut CrateCtxt, crate: @crate) {
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 6de87762031..6c7f73177fa 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -52,7 +52,7 @@ use syntax::ast_map;
 use syntax::ast_util::{local_def, split_trait_methods};
 use syntax::codemap::span;
 use syntax::codemap;
-use syntax::print::pprust::{path_to_str, self_ty_to_str};
+use syntax::print::pprust::{path_to_str, explicit_self_to_str};
 use syntax::visit;
 use syntax::opt_vec::OptVec;
 use syntax::opt_vec;
@@ -227,26 +227,26 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
         }, _) => {
             let trait_ty_generics = ty_generics(ccx, region_paramd, generics, 0);
 
-            // For each method, construct a suitable ty::method and
+            // For each method, construct a suitable ty::Method and
             // store it into the `tcx.methods` table:
             for ms.each |m| {
                 let ty_method = @match m {
                     &ast::required(ref m) => {
                         ty_method_of_trait_method(
                             ccx, trait_id, region_paramd, generics,
-                            &m.id, &m.ident, &m.self_ty,
+                            &m.id, &m.ident, &m.explicit_self,
                             &m.generics, &m.purity, &m.decl)
                     }
 
                     &ast::provided(ref m) => {
                         ty_method_of_trait_method(
                             ccx, trait_id, region_paramd, generics,
-                            &m.id, &m.ident, &m.self_ty,
+                            &m.id, &m.ident, &m.explicit_self,
                             &m.generics, &m.purity, &m.decl)
                     }
                 };
 
-                if ty_method.self_ty == ast::sty_static {
+                if ty_method.explicit_self == ast::sty_static {
                     make_static_method_ty(ccx, trait_id, ty_method,
                                           &trait_ty_generics);
                 }
@@ -270,7 +270,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
 
     fn make_static_method_ty(ccx: &CrateCtxt,
                              trait_id: ast::node_id,
-                             m: &ty::method,
+                             m: &ty::Method,
                              trait_ty_generics: &ty::Generics) {
         // If declaration is
         //
@@ -370,33 +370,33 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                           });
     }
 
-    fn ty_method_of_trait_method(self: &CrateCtxt,
+    fn ty_method_of_trait_method(this: &CrateCtxt,
                                  trait_id: ast::node_id,
                                  trait_rp: Option<ty::region_variance>,
                                  trait_generics: &ast::Generics,
                                  m_id: &ast::node_id,
                                  m_ident: &ast::ident,
-                                 m_self_ty: &ast::self_ty,
+                                 m_explicit_self: &ast::explicit_self,
                                  m_generics: &ast::Generics,
                                  m_purity: &ast::purity,
-                                 m_decl: &ast::fn_decl) -> ty::method
+                                 m_decl: &ast::fn_decl) -> ty::Method
     {
-        let trait_self_ty = ty::mk_self(self.tcx, local_def(trait_id));
-        let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics);
+        let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
+        let rscope = MethodRscope::new(m_explicit_self.node, trait_rp, trait_generics);
         let (transformed_self_ty, fty) =
-            astconv::ty_of_method(self, &rscope, *m_purity, &m_generics.lifetimes,
-                                  trait_self_ty, *m_self_ty, m_decl);
+            astconv::ty_of_method(this, &rscope, *m_purity, &m_generics.lifetimes,
+                                  trait_self_ty, *m_explicit_self, m_decl);
         let num_trait_type_params = trait_generics.ty_params.len();
-        ty::method {
-            ident: *m_ident,
-            generics: ty_generics(self, None, m_generics, num_trait_type_params),
-            transformed_self_ty: transformed_self_ty,
-            fty: fty,
-            self_ty: m_self_ty.node,
+        ty::Method::new(
+            *m_ident,
+            ty_generics(this, None, m_generics, num_trait_type_params),
+            transformed_self_ty,
+            fty,
+            m_explicit_self.node,
             // assume public, because this is only invoked on trait methods
-            vis: ast::public,
-            def_id: local_def(*m_id)
-        }
+            ast::public,
+            local_def(*m_id)
+        )
     }
 }
 
@@ -444,7 +444,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
 pub fn compare_impl_method(tcx: ty::ctxt,
                            impl_tps: uint,
                            cm: &ConvertedMethod,
-                           trait_m: &ty::method,
+                           trait_m: &ty::Method,
                            trait_substs: &ty::substs,
                            self_ty: ty::t) {
     debug!("compare_impl_method()");
@@ -459,7 +459,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
     // that the error messages you get out of this code are a bit more
     // inscrutable, particularly for cases where one method has no
     // self.
-    match (&trait_m.self_ty, &impl_m.self_ty) {
+    match (&trait_m.explicit_self, &impl_m.explicit_self) {
         (&ast::sty_static, &ast::sty_static) => {}
         (&ast::sty_static, _) => {
             tcx.sess.span_err(
@@ -467,7 +467,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
                 fmt!("method `%s` has a `%s` declaration in the impl, \
                       but not in the trait",
                      *tcx.sess.str_of(trait_m.ident),
-                     self_ty_to_str(impl_m.self_ty, tcx.sess.intr())));
+                     explicit_self_to_str(impl_m.explicit_self, tcx.sess.intr())));
             return;
         }
         (_, &ast::sty_static) => {
@@ -476,7 +476,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
                 fmt!("method `%s` has a `%s` declaration in the trait, \
                       but not in the impl",
                      *tcx.sess.str_of(trait_m.ident),
-                     self_ty_to_str(trait_m.self_ty, tcx.sess.intr())));
+                     explicit_self_to_str(trait_m.explicit_self, tcx.sess.intr())));
             return;
         }
         _ => {
@@ -499,15 +499,15 @@ pub fn compare_impl_method(tcx: ty::ctxt,
         return;
     }
 
-    if vec::len(impl_m.fty.sig.inputs) != vec::len(trait_m.fty.sig.inputs) {
+    if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
         tcx.sess.span_err(
             cm.span,
             fmt!("method `%s` has %u parameter%s \
                   but the trait has %u",
                  *tcx.sess.str_of(trait_m.ident),
-                 vec::len(impl_m.fty.sig.inputs),
-                 if vec::len(impl_m.fty.sig.inputs) == 1 { "" } else { "s" },
-                 vec::len(trait_m.fty.sig.inputs)));
+                 impl_m.fty.sig.inputs.len(),
+                 if impl_m.fty.sig.inputs.len() == 1 { "" } else { "s" },
+                 trait_m.fty.sig.inputs.len()));
         return;
     }
 
@@ -576,14 +576,10 @@ pub fn compare_impl_method(tcx: ty::ctxt,
     // represent the self argument (unless this is a static method).
     // This argument will have the *transformed* self type.
     for trait_m.transformed_self_ty.each |&t| {
-        trait_fn_args.push(ty::arg {
-            ty: t
-        });
+        trait_fn_args.push(t);
     }
     for impl_m.transformed_self_ty.each |&t| {
-        impl_fn_args.push(ty::arg {
-            ty: t
-        });
+        impl_fn_args.push(t);
     }
 
     // Add in the normal arguments.
@@ -727,7 +723,7 @@ pub fn convert_field(ccx: &CrateCtxt,
 }
 
 pub struct ConvertedMethod {
-    mty: @ty::method,
+    mty: @ty::Method,
     id: ast::node_id,
     span: span,
     body_id: ast::node_id
@@ -780,16 +776,16 @@ pub fn convert_methods(ccx: &CrateCtxt,
                     untransformed_rcvr_ty: ty::t,
                     rcvr_generics: &ast::Generics,
                     rcvr_visibility: ast::visibility,
-                    method_generics: &ast::Generics) -> ty::method
+                    method_generics: &ast::Generics) -> ty::Method
     {
-        let rscope = MethodRscope::new(m.self_ty.node,
+        let rscope = MethodRscope::new(m.explicit_self.node,
                                        rp,
                                        rcvr_generics);
         let (transformed_self_ty, fty) =
             astconv::ty_of_method(ccx, &rscope, m.purity,
                                   &method_generics.lifetimes,
                                   untransformed_rcvr_ty,
-                                  m.self_ty, &m.decl);
+                                  m.explicit_self, &m.decl);
 
         // if the method specifies a visibility, use that, otherwise
         // inherit the visibility from the impl (so `foo` in `pub impl
@@ -798,15 +794,15 @@ pub fn convert_methods(ccx: &CrateCtxt,
         let method_vis = m.vis.inherit_from(rcvr_visibility);
 
         let num_rcvr_type_params = rcvr_generics.ty_params.len();
-        ty::method {
-            ident: m.ident,
-            generics: ty_generics(ccx, None, &m.generics, num_rcvr_type_params),
-            transformed_self_ty: transformed_self_ty,
-            fty: fty,
-            self_ty: m.self_ty.node,
-            vis: method_vis,
-            def_id: local_def(m.id)
-        }
+        ty::Method::new(
+            m.ident,
+            ty_generics(ccx, None, &m.generics, num_rcvr_type_params),
+            transformed_self_ty,
+            fty,
+            m.explicit_self.node,
+            method_vis,
+            local_def(m.id)
+        )
     }
 }
 
@@ -1137,7 +1133,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
       }
       ast::item_impl(*) | ast::item_mod(_) |
       ast::item_foreign_mod(_) => fail!(),
-      ast::item_mac(*) => fail!(~"item macros unimplemented")
+      ast::item_mac(*) => fail!("item macros unimplemented")
     }
 }
 
@@ -1211,25 +1207,21 @@ pub fn ty_generics(ccx: &CrateCtxt,
             builtin_bounds: ty::EmptyBuiltinBounds(),
             trait_bounds: ~[]
         };
-        for ast_bounds.each |b| {
-            match b {
-                &TraitTyParamBound(b) => {
-                    let li = &ccx.tcx.lang_items;
+        for ast_bounds.each |ast_bound| {
+            match *ast_bound {
+                TraitTyParamBound(b) => {
                     let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
                     let trait_ref = instantiate_trait_ref(ccx, b, rp, generics, ty);
-                    if trait_ref.def_id == li.owned_trait() {
-                        param_bounds.builtin_bounds.add(ty::BoundOwned);
-                    } else if trait_ref.def_id == li.copy_trait() {
-                        param_bounds.builtin_bounds.add(ty::BoundCopy);
-                    } else if trait_ref.def_id == li.const_trait() {
-                        param_bounds.builtin_bounds.add(ty::BoundConst);
-                    } else {
+                    if !astconv::try_add_builtin_trait(
+                        ccx.tcx, trait_ref.def_id,
+                        &mut param_bounds.builtin_bounds)
+                    {
                         // Must be a user-defined trait
                         param_bounds.trait_bounds.push(trait_ref);
                     }
                 }
 
-                &RegionTyParamBound => {
+                RegionTyParamBound => {
                     param_bounds.builtin_bounds.add(ty::BoundStatic);
                 }
             }
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index 362104e98b0..3c337d17f86 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -55,7 +55,8 @@
 // now.
 
 use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
-use middle::ty::{IntType, UintType, arg, substs};
+use middle::ty::{IntType, UintType, substs};
+use middle::ty::{BuiltinBounds};
 use middle::ty;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::lub::Lub;
@@ -95,11 +96,12 @@ pub trait Combine {
                    b: &ty::ClosureTy) -> cres<ty::ClosureTy>;
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
     fn flds(&self, a: ty::field, b: ty::field) -> cres<ty::field>;
-    fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg>;
+    fn args(&self, a: ty::t, b: ty::t) -> cres<ty::t>;
     fn sigils(&self, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil>;
     fn purities(&self, a: purity, b: purity) -> cres<purity>;
     fn abis(&self, a: AbiSet, b: AbiSet) -> cres<AbiSet>;
     fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<Onceness>;
+    fn bounds(&self, a: BuiltinBounds, b: BuiltinBounds) -> cres<BuiltinBounds>;
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                   -> cres<ty::Region>;
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region>;
@@ -120,31 +122,31 @@ pub struct CombineFields {
 }
 
 pub fn expected_found<C:Combine,T>(
-        self: &C, a: T, b: T) -> ty::expected_found<T> {
-    if self.a_is_expected() {
+        this: &C, a: T, b: T) -> ty::expected_found<T> {
+    if this.a_is_expected() {
         ty::expected_found {expected: a, found: b}
     } else {
         ty::expected_found {expected: b, found: a}
     }
 }
 
-pub fn eq_tys<C:Combine>(self: &C, a: ty::t, b: ty::t) -> ures {
-    let suber = self.sub();
-    do self.infcx().try {
+pub fn eq_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> ures {
+    let suber = this.sub();
+    do this.infcx().try {
         do suber.tys(a, b).chain |_ok| {
             suber.contratys(a, b)
         }.to_ures()
     }
 }
 
-pub fn eq_regions<C:Combine>(self: &C, a: ty::Region, b: ty::Region)
+pub fn eq_regions<C:Combine>(this: &C, a: ty::Region, b: ty::Region)
                           -> ures {
     debug!("eq_regions(%s, %s)",
-           a.inf_str(self.infcx()),
-           b.inf_str(self.infcx()));
-    let sub = self.sub();
+           a.inf_str(this.infcx()),
+           b.inf_str(this.infcx()));
+    let sub = this.sub();
     do indent {
-        self.infcx().try(|| {
+        this.infcx().try(|| {
             do sub.regions(a, b).chain |_r| {
                 sub.contraregions(a, b)
             }
@@ -161,7 +163,7 @@ pub fn eq_regions<C:Combine>(self: &C, a: ty::Region, b: ty::Region)
 }
 
 pub fn eq_opt_regions<C:Combine>(
-    self: &C,
+    this: &C,
     a: Option<ty::Region>,
     b: Option<ty::Region>) -> cres<Option<ty::Region>> {
 
@@ -170,7 +172,7 @@ pub fn eq_opt_regions<C:Combine>(
         Ok(None)
       }
       (Some(a), Some(b)) => {
-        do eq_regions(self, a, b).then {
+        do eq_regions(this, a, b).then {
             Ok(Some(a))
         }
       }
@@ -179,21 +181,21 @@ pub fn eq_opt_regions<C:Combine>(
         // they should be), then the type should either
         // consistently have a region parameter or not have a
         // region parameter.
-        self.infcx().tcx.sess.bug(
+        this.infcx().tcx.sess.bug(
             fmt!("substitution a had opt_region %s and \
                   b had opt_region %s",
-                 a.inf_str(self.infcx()),
-                 b.inf_str(self.infcx())));
+                 a.inf_str(this.infcx()),
+                 b.inf_str(this.infcx())));
       }
     }
 }
 
 pub fn super_substs<C:Combine>(
-    self: &C, generics: &ty::Generics,
+    this: &C, generics: &ty::Generics,
     a: &ty::substs, b: &ty::substs) -> cres<ty::substs> {
 
     fn relate_region_param<C:Combine>(
-        self: &C,
+        this: &C,
         generics: &ty::Generics,
         a: Option<ty::Region>,
         b: Option<ty::Region>)
@@ -204,17 +206,17 @@ pub fn super_substs<C:Combine>(
             Ok(None)
           }
           (&Some(ty::rv_invariant), &Some(a), &Some(b)) => {
-            do eq_regions(self, a, b).then {
+            do eq_regions(this, a, b).then {
                 Ok(Some(a))
             }
           }
           (&Some(ty::rv_covariant), &Some(a), &Some(b)) => {
-            do self.regions(a, b).chain |r| {
+            do this.regions(a, b).chain |r| {
                 Ok(Some(r))
             }
           }
           (&Some(ty::rv_contravariant), &Some(a), &Some(b)) => {
-            do self.contraregions(a, b).chain |r| {
+            do this.contraregions(a, b).chain |r| {
                 Ok(Some(r))
             }
           }
@@ -224,19 +226,19 @@ pub fn super_substs<C:Combine>(
             // consistently have a region parameter or not have a
             // region parameter, and that should match with the
             // polytype.
-            self.infcx().tcx.sess.bug(
+            this.infcx().tcx.sess.bug(
                 fmt!("substitution a had opt_region %s and \
                       b had opt_region %s with variance %?",
-                      a.inf_str(self.infcx()),
-                      b.inf_str(self.infcx()),
+                      a.inf_str(this.infcx()),
+                      b.inf_str(this.infcx()),
                      generics.region_param));
           }
         }
     }
 
-    do self.tps(a.tps, b.tps).chain |tps| {
-        do self.self_tys(a.self_ty, b.self_ty).chain |self_ty| {
-            do relate_region_param(self, generics,
+    do this.tps(a.tps, b.tps).chain |tps| {
+        do this.self_tys(a.self_ty, b.self_ty).chain |self_ty| {
+            do relate_region_param(this, generics,
                                    a.self_r, b.self_r).chain |self_r|
             {
                 Ok(substs {
@@ -250,7 +252,7 @@ pub fn super_substs<C:Combine>(
 }
 
 pub fn super_tps<C:Combine>(
-    self: &C, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
+    this: &C, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
 
     // Note: type parameters are always treated as *invariant*
     // (otherwise the type system would be unsound).  In the
@@ -259,16 +261,16 @@ pub fn super_tps<C:Combine>(
 
     if vec::same_length(as_, bs) {
         iter_vec2(as_, bs, |a, b| {
-            eq_tys(self, *a, *b)
+            eq_tys(this, *a, *b)
         }).then(|| Ok(as_.to_vec()) )
     } else {
         Err(ty::terr_ty_param_size(
-            expected_found(self, as_.len(), bs.len())))
+            expected_found(this, as_.len(), bs.len())))
     }
 }
 
 pub fn super_self_tys<C:Combine>(
-    self: &C, a: Option<ty::t>, b: Option<ty::t>) -> cres<Option<ty::t>> {
+    this: &C, a: Option<ty::t>, b: Option<ty::t>) -> cres<Option<ty::t>> {
 
     match (a, b) {
       (None, None) => {
@@ -276,8 +278,8 @@ pub fn super_self_tys<C:Combine>(
       }
       (Some(a), Some(b)) => {
           // FIXME(#5781) this should be eq_tys
-          // eq_tys(self, a, b).then(|| Ok(Some(a)) )
-          self.contratys(a, b).chain(|t| Ok(Some(t)))
+          // eq_tys(this, a, b).then(|| Ok(Some(a)) )
+          this.contratys(a, b).chain(|t| Ok(Some(t)))
       }
       (None, Some(_)) |
       (Some(_), None) => {
@@ -290,46 +292,43 @@ pub fn super_self_tys<C:Combine>(
 }
 
 pub fn super_sigils<C:Combine>(
-    self: &C, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
+    this: &C, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
     if p1 == p2 {
         Ok(p1)
     } else {
-        Err(ty::terr_sigil_mismatch(expected_found(self, p1, p2)))
+        Err(ty::terr_sigil_mismatch(expected_found(this, p1, p2)))
     }
 }
 
 pub fn super_flds<C:Combine>(
-    self: &C, a: ty::field, b: ty::field) -> cres<ty::field> {
+    this: &C, a: ty::field, b: ty::field) -> cres<ty::field> {
 
     if a.ident == b.ident {
-        self.mts(&a.mt, &b.mt)
+        this.mts(&a.mt, &b.mt)
             .chain(|mt| Ok(ty::field {ident: a.ident, mt: mt}) )
             .chain_err(|e| Err(ty::terr_in_field(@e, a.ident)) )
     } else {
         Err(ty::terr_record_fields(
-            expected_found(self, a.ident, b.ident)))
+            expected_found(this, a.ident, b.ident)))
     }
 }
 
-pub fn super_args<C:Combine>(self: &C, a: ty::arg, b: ty::arg)
-                             -> cres<ty::arg> {
-    do self.contratys(a.ty, b.ty).chain |t| {
-        Ok(arg {
-            ty: t
-        })
+pub fn super_args<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
+    do this.contratys(a, b).chain |t| {
+        Ok(t)
     }
 }
 
-pub fn super_vstores<C:Combine>(self: &C,
+pub fn super_vstores<C:Combine>(this: &C,
                                 vk: ty::terr_vstore_kind,
                                 a: ty::vstore,
                                 b: ty::vstore)
                                 -> cres<ty::vstore> {
-    debug!("%s.super_vstores(a=%?, b=%?)", self.tag(), a, b);
+    debug!("%s.super_vstores(a=%?, b=%?)", this.tag(), a, b);
 
     match (a, b) {
       (ty::vstore_slice(a_r), ty::vstore_slice(b_r)) => {
-        do self.contraregions(a_r, b_r).chain |r| {
+        do this.contraregions(a_r, b_r).chain |r| {
             Ok(ty::vstore_slice(r))
         }
       }
@@ -339,21 +338,21 @@ pub fn super_vstores<C:Combine>(self: &C,
       }
 
       _ => {
-        Err(ty::terr_vstores_differ(vk, expected_found(self, a, b)))
+        Err(ty::terr_vstores_differ(vk, expected_found(this, a, b)))
       }
     }
 }
 
-pub fn super_trait_stores<C:Combine>(self: &C,
+pub fn super_trait_stores<C:Combine>(this: &C,
                                      vk: ty::terr_vstore_kind,
                                      a: ty::TraitStore,
                                      b: ty::TraitStore)
                                   -> cres<ty::TraitStore> {
-    debug!("%s.super_vstores(a=%?, b=%?)", self.tag(), a, b);
+    debug!("%s.super_vstores(a=%?, b=%?)", this.tag(), a, b);
 
     match (a, b) {
       (ty::RegionTraitStore(a_r), ty::RegionTraitStore(b_r)) => {
-        do self.contraregions(a_r, b_r).chain |r| {
+        do this.contraregions(a_r, b_r).chain |r| {
             Ok(ty::RegionTraitStore(r))
         }
       }
@@ -363,64 +362,63 @@ pub fn super_trait_stores<C:Combine>(self: &C,
       }
 
       _ => {
-        Err(ty::terr_trait_stores_differ(vk, expected_found(self, a, b)))
+        Err(ty::terr_trait_stores_differ(vk, expected_found(this, a, b)))
       }
     }
 }
 
 pub fn super_closure_tys<C:Combine>(
-    self: &C, a_f: &ty::ClosureTy, b_f: &ty::ClosureTy) -> cres<ty::ClosureTy>
+    this: &C, a_f: &ty::ClosureTy, b_f: &ty::ClosureTy) -> cres<ty::ClosureTy>
 {
-    let p = if_ok!(self.sigils(a_f.sigil, b_f.sigil));
-    let r = if_ok!(self.contraregions(a_f.region, b_f.region));
-    let purity = if_ok!(self.purities(a_f.purity, b_f.purity));
-    let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness));
-    let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig));
+    let p = if_ok!(this.sigils(a_f.sigil, b_f.sigil));
+    let r = if_ok!(this.contraregions(a_f.region, b_f.region));
+    let purity = if_ok!(this.purities(a_f.purity, b_f.purity));
+    let onceness = if_ok!(this.oncenesses(a_f.onceness, b_f.onceness));
+    let bounds = if_ok!(this.bounds(a_f.bounds, b_f.bounds));
+    let sig = if_ok!(this.fn_sigs(&a_f.sig, &b_f.sig));
     Ok(ty::ClosureTy {purity: purity,
                       sigil: p,
                       onceness: onceness,
                       region: r,
+                      bounds: bounds,
                       sig: sig})
 }
 
 pub fn super_abis<C:Combine>(
-    self: &C, a: AbiSet, b: AbiSet) -> cres<AbiSet>
+    this: &C, a: AbiSet, b: AbiSet) -> cres<AbiSet>
 {
     if a == b {
         Ok(a)
     } else {
-        Err(ty::terr_abi_mismatch(expected_found(self, a, b)))
+        Err(ty::terr_abi_mismatch(expected_found(this, a, b)))
     }
 }
 
 pub fn super_bare_fn_tys<C:Combine>(
-    self: &C, a_f: &ty::BareFnTy, b_f: &ty::BareFnTy) -> cres<ty::BareFnTy>
+    this: &C, a_f: &ty::BareFnTy, b_f: &ty::BareFnTy) -> cres<ty::BareFnTy>
 {
-    let purity = if_ok!(self.purities(a_f.purity, b_f.purity));
-    let abi = if_ok!(self.abis(a_f.abis, b_f.abis));
-    let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig));
+    let purity = if_ok!(this.purities(a_f.purity, b_f.purity));
+    let abi = if_ok!(this.abis(a_f.abis, b_f.abis));
+    let sig = if_ok!(this.fn_sigs(&a_f.sig, &b_f.sig));
     Ok(ty::BareFnTy {purity: purity,
                      abis: abi,
                      sig: sig})
 }
 
 pub fn super_fn_sigs<C:Combine>(
-    self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig>
+    this: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig>
 {
-    fn argvecs<C:Combine>(self: &C,
-                          a_args: &[ty::arg],
-                          b_args: &[ty::arg]) -> cres<~[ty::arg]>
-    {
+    fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<~[ty::t]> {
         if vec::same_length(a_args, b_args) {
-            map_vec2(a_args, b_args, |a, b| self.args(*a, *b))
+            map_vec2(a_args, b_args, |a, b| this.args(*a, *b))
         } else {
             Err(ty::terr_arg_count)
         }
     }
 
-    do argvecs(self, a_f.inputs, b_f.inputs)
+    do argvecs(this, a_f.inputs, b_f.inputs)
             .chain |inputs| {
-        do self.tys(a_f.output, b_f.output).chain |output| {
+        do this.tys(a_f.output, b_f.output).chain |output| {
             Ok(FnSig {bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
                       inputs: /*bad*/copy inputs,
                       output: output})
@@ -429,8 +427,8 @@ pub fn super_fn_sigs<C:Combine>(
 }
 
 pub fn super_tys<C:Combine>(
-    self: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
-    let tcx = self.infcx().tcx;
+    this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
+    let tcx = this.infcx().tcx;
     return match (/*bad*/copy ty::get(a).sty, /*bad*/copy ty::get(b).sty) {
       // The "subtype" ought to be handling cases involving bot or var:
       (ty::ty_bot, _) |
@@ -439,45 +437,45 @@ pub fn super_tys<C:Combine>(
       (_, ty::ty_infer(TyVar(_))) => {
         tcx.sess.bug(
             fmt!("%s: bot and var types should have been handled (%s,%s)",
-                 self.tag(),
-                 a.inf_str(self.infcx()),
-                 b.inf_str(self.infcx())));
+                 this.tag(),
+                 a.inf_str(this.infcx()),
+                 b.inf_str(this.infcx())));
       }
 
         // Relate integral variables to other types
         (ty::ty_infer(IntVar(a_id)), ty::ty_infer(IntVar(b_id))) => {
-            if_ok!(self.infcx().simple_vars(self.a_is_expected(),
+            if_ok!(this.infcx().simple_vars(this.a_is_expected(),
                                             a_id, b_id));
             Ok(a)
         }
         (ty::ty_infer(IntVar(v_id)), ty::ty_int(v)) => {
-            unify_integral_variable(self, self.a_is_expected(),
+            unify_integral_variable(this, this.a_is_expected(),
                                     v_id, IntType(v))
         }
         (ty::ty_int(v), ty::ty_infer(IntVar(v_id))) => {
-            unify_integral_variable(self, !self.a_is_expected(),
+            unify_integral_variable(this, !this.a_is_expected(),
                                     v_id, IntType(v))
         }
         (ty::ty_infer(IntVar(v_id)), ty::ty_uint(v)) => {
-            unify_integral_variable(self, self.a_is_expected(),
+            unify_integral_variable(this, this.a_is_expected(),
                                     v_id, UintType(v))
         }
         (ty::ty_uint(v), ty::ty_infer(IntVar(v_id))) => {
-            unify_integral_variable(self, !self.a_is_expected(),
+            unify_integral_variable(this, !this.a_is_expected(),
                                     v_id, UintType(v))
         }
 
         // Relate floating-point variables to other types
         (ty::ty_infer(FloatVar(a_id)), ty::ty_infer(FloatVar(b_id))) => {
-            if_ok!(self.infcx().simple_vars(self.a_is_expected(),
+            if_ok!(this.infcx().simple_vars(this.a_is_expected(),
                                             a_id, b_id));
             Ok(a)
         }
         (ty::ty_infer(FloatVar(v_id)), ty::ty_float(v)) => {
-            unify_float_variable(self, self.a_is_expected(), v_id, v)
+            unify_float_variable(this, this.a_is_expected(), v_id, v)
         }
         (ty::ty_float(v), ty::ty_infer(FloatVar(v_id))) => {
-            unify_float_variable(self, !self.a_is_expected(), v_id, v)
+            unify_float_variable(this, !this.a_is_expected(), v_id, v)
         }
 
       (ty::ty_nil, _) |
@@ -488,7 +486,7 @@ pub fn super_tys<C:Combine>(
         if ty::get(a).sty == ty::get(b).sty {
             Ok(a)
         } else {
-            Err(ty::terr_sorts(expected_found(self, a, b)))
+            Err(ty::terr_sorts(expected_found(this, a, b)))
         }
       }
 
@@ -500,7 +498,7 @@ pub fn super_tys<C:Combine>(
        ty::ty_enum(b_id, ref b_substs))
       if a_id == b_id => {
           let type_def = ty::lookup_item_type(tcx, a_id);
-          do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
+          do this.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
               Ok(ty::mk_enum(tcx, a_id, substs))
           }
       }
@@ -509,8 +507,8 @@ pub fn super_tys<C:Combine>(
        ty::ty_trait(b_id, ref b_substs, b_store, b_mutbl))
       if a_id == b_id && a_mutbl == b_mutbl => {
           let trait_def = ty::lookup_trait_def(tcx, a_id);
-          do self.substs(&trait_def.generics, a_substs, b_substs).chain |substs| {
-              do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
+          do this.substs(&trait_def.generics, a_substs, b_substs).chain |substs| {
+              do this.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
                   Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s, a_mutbl))
               }
           }
@@ -519,76 +517,76 @@ pub fn super_tys<C:Combine>(
       (ty::ty_struct(a_id, ref a_substs), ty::ty_struct(b_id, ref b_substs))
       if a_id == b_id => {
           let type_def = ty::lookup_item_type(tcx, a_id);
-          do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
+          do this.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
               Ok(ty::mk_struct(tcx, a_id, substs))
           }
       }
 
       (ty::ty_box(ref a_mt), ty::ty_box(ref b_mt)) => {
-        do self.mts(a_mt, b_mt).chain |mt| {
+        do this.mts(a_mt, b_mt).chain |mt| {
             Ok(ty::mk_box(tcx, mt))
         }
       }
 
       (ty::ty_uniq(ref a_mt), ty::ty_uniq(ref b_mt)) => {
-        do self.mts(a_mt, b_mt).chain |mt| {
+        do this.mts(a_mt, b_mt).chain |mt| {
             Ok(ty::mk_uniq(tcx, mt))
         }
       }
 
       (ty::ty_ptr(ref a_mt), ty::ty_ptr(ref b_mt)) => {
-        do self.mts(a_mt, b_mt).chain |mt| {
+        do this.mts(a_mt, b_mt).chain |mt| {
             Ok(ty::mk_ptr(tcx, mt))
         }
       }
 
       (ty::ty_rptr(a_r, ref a_mt), ty::ty_rptr(b_r, ref b_mt)) => {
-          let r = if_ok!(self.contraregions(a_r, b_r));
-          let mt = if_ok!(self.mts(a_mt, b_mt));
+          let r = if_ok!(this.contraregions(a_r, b_r));
+          let mt = if_ok!(this.mts(a_mt, b_mt));
           Ok(ty::mk_rptr(tcx, r, mt))
       }
 
       (ty::ty_evec(ref a_mt, vs_a), ty::ty_evec(ref b_mt, vs_b)) => {
-        do self.mts(a_mt, b_mt).chain |mt| {
-            do self.vstores(ty::terr_vec, vs_a, vs_b).chain |vs| {
+        do this.mts(a_mt, b_mt).chain |mt| {
+            do this.vstores(ty::terr_vec, vs_a, vs_b).chain |vs| {
                 Ok(ty::mk_evec(tcx, mt, vs))
             }
         }
       }
 
       (ty::ty_estr(vs_a), ty::ty_estr(vs_b)) => {
-        do self.vstores(ty::terr_str, vs_a, vs_b).chain |vs| {
+        do this.vstores(ty::terr_str, vs_a, vs_b).chain |vs| {
             Ok(ty::mk_estr(tcx,vs))
         }
       }
 
       (ty::ty_tup(ref as_), ty::ty_tup(ref bs)) => {
         if as_.len() == bs.len() {
-            map_vec2(*as_, *bs, |a, b| self.tys(*a, *b) )
+            map_vec2(*as_, *bs, |a, b| this.tys(*a, *b) )
                 .chain(|ts| Ok(ty::mk_tup(tcx, ts)) )
         } else {
             Err(ty::terr_tuple_size(
-                expected_found(self, as_.len(), bs.len())))
+                expected_found(this, as_.len(), bs.len())))
         }
       }
 
       (ty::ty_bare_fn(ref a_fty), ty::ty_bare_fn(ref b_fty)) => {
-        do self.bare_fn_tys(a_fty, b_fty).chain |fty| {
+        do this.bare_fn_tys(a_fty, b_fty).chain |fty| {
             Ok(ty::mk_bare_fn(tcx, fty))
         }
       }
 
       (ty::ty_closure(ref a_fty), ty::ty_closure(ref b_fty)) => {
-        do self.closure_tys(a_fty, b_fty).chain |fty| {
+        do this.closure_tys(a_fty, b_fty).chain |fty| {
             Ok(ty::mk_closure(tcx, fty))
         }
       }
 
-      _ => Err(ty::terr_sorts(expected_found(self, a, b)))
+      _ => Err(ty::terr_sorts(expected_found(this, a, b)))
     };
 
     fn unify_integral_variable<C:Combine>(
-        self: &C,
+        this: &C,
         vid_is_expected: bool,
         vid: ty::IntVid,
         val: ty::IntVarValue) -> cres<ty::t>
@@ -596,7 +594,7 @@ pub fn super_tys<C:Combine>(
         if val == IntType(ast::ty_char) {
             Err(ty::terr_integer_as_char)
         } else {
-            if_ok!(self.infcx().simple_var_t(vid_is_expected, vid, val));
+            if_ok!(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))
@@ -605,18 +603,18 @@ pub fn super_tys<C:Combine>(
     }
 
     fn unify_float_variable<C:Combine>(
-        self: &C,
+        this: &C,
         vid_is_expected: bool,
         vid: ty::FloatVid,
         val: ast::float_ty) -> cres<ty::t>
     {
-        if_ok!(self.infcx().simple_var_t(vid_is_expected, vid, val));
+        if_ok!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         Ok(ty::mk_mach_float(val))
     }
 }
 
 pub fn super_trait_refs<C:Combine>(
-    self: &C, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef>
+    this: &C, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef>
 {
     // Different traits cannot be related
 
@@ -624,11 +622,11 @@ pub fn super_trait_refs<C:Combine>(
 
     if a.def_id != b.def_id {
         Err(ty::terr_traits(
-            expected_found(self, a.def_id, b.def_id)))
+            expected_found(this, a.def_id, b.def_id)))
     } else {
-        let tcx = self.infcx().tcx;
+        let tcx = this.infcx().tcx;
         let trait_def = ty::lookup_trait_def(tcx, a.def_id);
-        let substs = if_ok!(self.substs(&trait_def.generics, &a.substs, &b.substs));
+        let substs = if_ok!(this.substs(&trait_def.generics, &a.substs, &b.substs));
         Ok(ty::TraitRef {
             def_id: a.def_id,
             substs: substs
diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs
index c195454b532..9ade6de6cf4 100644
--- a/src/librustc/middle/typeck/infer/glb.rs
+++ b/src/librustc/middle/typeck/infer/glb.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::ty::{BuiltinBounds};
 use middle::ty::RegionVid;
 use middle::ty;
 use middle::typeck::infer::combine::*;
@@ -114,6 +115,12 @@ impl Combine for Glb {
         }
     }
 
+    fn bounds(&self, a: BuiltinBounds, b: BuiltinBounds) -> cres<BuiltinBounds> {
+        // More bounds is a subtype of fewer bounds, so
+        // the GLB (mutual subtype) is the union.
+        Ok(a.union(b))
+    }
+
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("%s.regions(%?, %?)",
                self.tag(),
@@ -153,7 +160,7 @@ impl Combine for Glb {
         super_trait_stores(self, vk, a, b)
     }
 
-    fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
+    fn args(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         super_args(self, a, b)
     }
 
@@ -198,7 +205,7 @@ impl Combine for Glb {
         debug!("sig1 = %s", sig1.inf_str(self.infcx));
         return Ok(sig1);
 
-        fn generalize_region(self: &Glb,
+        fn generalize_region(this: &Glb,
                              snapshot: uint,
                              new_vars: &[RegionVid],
                              a_isr: isr_alist,
@@ -209,19 +216,19 @@ impl Combine for Glb {
                 return r0;
             }
 
-            let tainted = self.infcx.region_vars.tainted(snapshot, r0);
+            let tainted = this.infcx.region_vars.tainted(snapshot, r0);
 
             let mut a_r = None, b_r = None, only_new_vars = true;
             for tainted.each |r| {
                 if is_var_in_set(a_vars, *r) {
                     if a_r.is_some() {
-                        return fresh_bound_variable(self);
+                        return fresh_bound_variable(this);
                     } else {
                         a_r = Some(*r);
                     }
                 } else if is_var_in_set(b_vars, *r) {
                     if b_r.is_some() {
-                        return fresh_bound_variable(self);
+                        return fresh_bound_variable(this);
                     } else {
                         b_r = Some(*r);
                     }
@@ -246,17 +253,17 @@ impl Combine for Glb {
 
             if a_r.is_some() && b_r.is_some() && only_new_vars {
                 // Related to exactly one bound variable from each fn:
-                return rev_lookup(self, a_isr, a_r.get());
+                return rev_lookup(this, a_isr, a_r.get());
             } else if a_r.is_none() && b_r.is_none() {
                 // Not related to bound variables from either fn:
                 return r0;
             } else {
                 // Other:
-                return fresh_bound_variable(self);
+                return fresh_bound_variable(this);
             }
         }
 
-        fn rev_lookup(self: &Glb,
+        fn rev_lookup(this: &Glb,
                       a_isr: isr_alist,
                       r: ty::Region) -> ty::Region
         {
@@ -267,13 +274,13 @@ impl Combine for Glb {
                 }
             }
 
-            self.infcx.tcx.sess.span_bug(
-                self.span,
+            this.infcx.tcx.sess.span_bug(
+                this.span,
                 fmt!("could not find original bound region for %?", r));
         }
 
-        fn fresh_bound_variable(self: &Glb) -> ty::Region {
-            self.infcx.region_vars.new_bound()
+        fn fresh_bound_variable(this: &Glb) -> ty::Region {
+            this.infcx.region_vars.new_bound()
         }
     }
 
diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs
index b9344724f60..3c48e09c057 100644
--- a/src/librustc/middle/typeck/infer/lattice.rs
+++ b/src/librustc/middle/typeck/infer/lattice.rs
@@ -330,27 +330,27 @@ impl TyLatticeDir for Glb {
 }
 
 pub fn super_lattice_tys<L:LatticeDir + TyLatticeDir + Combine>(
-    self: &L,
+    this: &L,
     a: ty::t,
     b: ty::t) -> cres<ty::t> {
-    debug!("%s.lattice_tys(%s, %s)", self.tag(),
-           a.inf_str(self.infcx()),
-           b.inf_str(self.infcx()));
+    debug!("%s.lattice_tys(%s, %s)", this.tag(),
+           a.inf_str(this.infcx()),
+           b.inf_str(this.infcx()));
     let _r = indenter();
 
     if a == b {
         return Ok(a);
     }
 
-    let tcx = self.infcx().tcx;
+    let tcx = this.infcx().tcx;
 
     match (&ty::get(a).sty, &ty::get(b).sty) {
-        (&ty::ty_bot, _) => { return self.ty_bot(b); }
-        (_, &ty::ty_bot) => { return self.ty_bot(a); }
+        (&ty::ty_bot, _) => { return this.ty_bot(b); }
+        (_, &ty::ty_bot) => { return this.ty_bot(a); }
 
         (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
-            let r = if_ok!(lattice_vars(self, a_id, b_id,
-                                        |x, y| self.tys(*x, *y)));
+            let r = if_ok!(lattice_vars(this, a_id, b_id,
+                                        |x, y| this.tys(*x, *y)));
             return match r {
                 VarResult(v) => Ok(ty::mk_var(tcx, v)),
                 ValueResult(t) => Ok(t)
@@ -358,17 +358,17 @@ pub fn super_lattice_tys<L:LatticeDir + TyLatticeDir + Combine>(
         }
 
         (&ty::ty_infer(TyVar(a_id)), _) => {
-            return lattice_var_and_t(self, a_id, &b,
-                                     |x, y| self.tys(*x, *y));
+            return lattice_var_and_t(this, a_id, &b,
+                                     |x, y| this.tys(*x, *y));
         }
 
         (_, &ty::ty_infer(TyVar(b_id))) => {
-            return lattice_var_and_t(self, b_id, &a,
-                                     |x, y| self.tys(*x, *y));
+            return lattice_var_and_t(this, b_id, &a,
+                                     |x, y| this.tys(*x, *y));
         }
 
         _ => {
-            return super_tys(self, a, b);
+            return super_tys(this, a, b);
         }
     }
 }
@@ -398,22 +398,22 @@ pub enum LatticeVarResult<V,T> {
 pub fn lattice_vars<L:LatticeDir + Combine,
                     T:Copy + InferStr + LatticeValue,
                     V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
-    self: &L,                           // defines whether we want LUB or GLB
+    this: &L,                           // defines whether we want LUB or GLB
     a_vid: V,                          // first variable
     b_vid: V,                          // second variable
     lattice_dir_op: LatticeDirOp<T>)    // LUB or GLB operation on types
     -> cres<LatticeVarResult<V,T>> {
-    let nde_a = self.infcx().get(a_vid);
-    let nde_b = self.infcx().get(b_vid);
+    let nde_a = this.infcx().get(a_vid);
+    let nde_b = this.infcx().get(b_vid);
     let a_vid = nde_a.root;
     let b_vid = nde_b.root;
     let a_bounds = &nde_a.possible_types;
     let b_bounds = &nde_b.possible_types;
 
     debug!("%s.lattice_vars(%s=%s <: %s=%s)",
-           self.tag(),
-           a_vid.to_str(), a_bounds.inf_str(self.infcx()),
-           b_vid.to_str(), b_bounds.inf_str(self.infcx()));
+           this.tag(),
+           a_vid.to_str(), a_bounds.inf_str(this.infcx()),
+           b_vid.to_str(), b_bounds.inf_str(this.infcx()));
 
     // Same variable: the easy case.
     if a_vid == b_vid {
@@ -422,10 +422,10 @@ pub fn lattice_vars<L:LatticeDir + Combine,
 
     // If both A and B have an UB type, then we can just compute the
     // LUB of those types:
-    let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds);
+    let a_bnd = this.bnd(a_bounds), b_bnd = this.bnd(b_bounds);
     match (a_bnd, b_bnd) {
         (Some(ref a_ty), Some(ref b_ty)) => {
-            match self.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) {
+            match this.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) {
                 Ok(t) => return Ok(ValueResult(t)),
                 Err(_) => { /*fallthrough */ }
             }
@@ -435,7 +435,7 @@ pub fn lattice_vars<L:LatticeDir + Combine,
 
     // Otherwise, we need to merge A and B into one variable.  We can
     // then use either variable as an upper bound:
-    let cf = self.combine_fields();
+    let cf = this.combine_fields();
     do cf.var_sub_var(a_vid, b_vid).then {
         Ok(VarResult(a_vid))
     }
@@ -444,12 +444,12 @@ pub fn lattice_vars<L:LatticeDir + Combine,
 pub fn lattice_var_and_t<L:LatticeDir + Combine,
                          T:Copy + InferStr + LatticeValue,
                          V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
-    self: &L,
+    this: &L,
     a_id: V,
     b: &T,
     lattice_dir_op: LatticeDirOp<T>)
     -> cres<T> {
-    let nde_a = self.infcx().get(a_id);
+    let nde_a = this.infcx().get(a_id);
     let a_id = nde_a.root;
     let a_bounds = &nde_a.possible_types;
 
@@ -457,24 +457,24 @@ pub fn lattice_var_and_t<L:LatticeDir + Combine,
     // apply equally well to GLB if you inverse upper/lower/sub/super/etc.
 
     debug!("%s.lattice_var_and_t(%s=%s <: %s)",
-           self.tag(),
+           this.tag(),
            a_id.to_str(),
-           a_bounds.inf_str(self.infcx()),
-           b.inf_str(self.infcx()));
+           a_bounds.inf_str(this.infcx()),
+           b.inf_str(this.infcx()));
 
-    match self.bnd(a_bounds) {
+    match this.bnd(a_bounds) {
         Some(ref a_bnd) => {
             // If a has an upper bound, return the LUB(a.ub, b)
-            debug!("bnd=Some(%s)", a_bnd.inf_str(self.infcx()));
+            debug!("bnd=Some(%s)", a_bnd.inf_str(this.infcx()));
             lattice_dir_op(a_bnd, b)
         }
         None => {
             // If a does not have an upper bound, make b the upper bound of a
             // and then return b.
             debug!("bnd=None");
-            let a_bounds = self.with_bnd(a_bounds, *b);
-            do self.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then {
-                self.infcx().set(a_id, Root(a_bounds, nde_a.rank));
+            let a_bounds = this.with_bnd(a_bounds, *b);
+            do this.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then {
+                this.infcx().set(a_id, Root(a_bounds, nde_a.rank));
                 Ok(*b)
             }
         }
@@ -485,14 +485,14 @@ pub fn lattice_var_and_t<L:LatticeDir + Combine,
 // Random utility functions used by LUB/GLB when computing LUB/GLB of
 // fn types
 
-pub fn var_ids<T:Combine>(self: &T, isr: isr_alist) -> ~[RegionVid] {
+pub fn var_ids<T:Combine>(this: &T, isr: isr_alist) -> ~[RegionVid] {
     let mut result = ~[];
     for list::each(isr) |pair| {
         match pair.second() {
             ty::re_infer(ty::ReVar(r)) => { result.push(r); }
             r => {
-                self.infcx().tcx.sess.span_bug(
-                    self.span(),
+                this.infcx().tcx.sess.span_bug(
+                    this.span(),
                     fmt!("Found non-region-vid: %?", r));
             }
         }
diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs
index 34e006c9615..82fd4e3ae6d 100644
--- a/src/librustc/middle/typeck/infer/lub.rs
+++ b/src/librustc/middle/typeck/infer/lub.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::ty::{BuiltinBounds};
 use middle::ty::RegionVid;
 use middle::ty;
 use middle::typeck::infer::combine::*;
@@ -100,6 +101,12 @@ impl Combine for Lub {
         }
     }
 
+    fn bounds(&self, a: BuiltinBounds, b: BuiltinBounds) -> cres<BuiltinBounds> {
+        // More bounds is a subtype of fewer bounds, so
+        // the LUB (mutual supertype) is the intersection.
+        Ok(a.intersection(b))
+    }
+
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
         return Glb(**self).regions(a, b);
@@ -149,7 +156,7 @@ impl Combine for Lub {
                                               a_isr, r));
         return Ok(sig1);
 
-        fn generalize_region(self: &Lub,
+        fn generalize_region(this: &Lub,
                              snapshot: uint,
                              new_vars: &[RegionVid],
                              a_isr: isr_alist,
@@ -160,7 +167,7 @@ impl Combine for Lub {
                 return r0;
             }
 
-            let tainted = self.infcx.region_vars.tainted(snapshot, r0);
+            let tainted = this.infcx.region_vars.tainted(snapshot, r0);
 
             // Variables created during LUB computation which are
             // *related* to regions that pre-date the LUB computation
@@ -187,8 +194,8 @@ impl Combine for Lub {
                 }
             }
 
-            self.infcx.tcx.sess.span_bug(
-                self.span,
+            this.infcx.tcx.sess.span_bug(
+                this.span,
                 fmt!("Region %? is not associated with \
                       any bound region from A!", r0));
         }
@@ -236,7 +243,7 @@ impl Combine for Lub {
         super_trait_stores(self, vk, a, b)
     }
 
-    fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
+    fn args(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         super_args(self, a, b)
     }
 
diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs
index 96e289bc497..a5e8b42dee5 100644
--- a/src/librustc/middle/typeck/infer/region_inference.rs
+++ b/src/librustc/middle/typeck/infer/region_inference.rs
@@ -876,7 +876,7 @@ pub impl RegionVarBindings {
                     a: Region,
                     b: Region,
                     span: span,
-                    relate: &fn(self: &mut RegionVarBindings,
+                    relate: &fn(this: &mut RegionVarBindings,
                                 old_r: Region,
                                 new_r: Region) -> cres<()>)
                  -> cres<Region> {
@@ -1103,11 +1103,11 @@ priv impl RegionVarBindings {
             Equal => ty::re_free(*a)
         };
 
-        fn helper(self: &RegionVarBindings,
+        fn helper(this: &RegionVarBindings,
                   a: &FreeRegion,
                   b: &FreeRegion) -> ty::Region
         {
-            let rm = self.tcx.region_maps;
+            let rm = this.tcx.region_maps;
             if rm.sub_free_region(*a, *b) {
                 ty::re_free(*b)
             } else if rm.sub_free_region(*b, *a) {
@@ -1198,17 +1198,17 @@ priv impl RegionVarBindings {
             Equal => Ok(ty::re_free(*a))
         };
 
-        fn helper(self: &RegionVarBindings,
+        fn helper(this: &RegionVarBindings,
                   a: &FreeRegion,
                   b: &FreeRegion) -> cres<ty::Region>
         {
-            let rm = self.tcx.region_maps;
+            let rm = this.tcx.region_maps;
             if rm.sub_free_region(*a, *b) {
                 Ok(ty::re_free(*a))
             } else if rm.sub_free_region(*b, *a) {
                 Ok(ty::re_free(*b))
             } else {
-                self.intersect_scopes(ty::re_free(*a), ty::re_free(*b),
+                this.intersect_scopes(ty::re_free(*a), ty::re_free(*b),
                                       a.scope_id, b.scope_id)
             }
         }
@@ -1461,13 +1461,13 @@ pub impl RegionVarBindings {
             }
         };
 
-        fn check_node(self: &mut RegionVarBindings,
+        fn check_node(this: &mut RegionVarBindings,
                       a_vid: RegionVid,
                       a_node: &mut GraphNode,
                       a_region: Region,
                       b_region: Region)
                    -> bool {
-            if !self.is_subregion_of(a_region, b_region) {
+            if !this.is_subregion_of(a_region, b_region) {
                 debug!("Setting %? to ErrorValue: %? not subregion of %?",
                        a_vid, a_region, b_region);
                 a_node.value = ErrorValue;
@@ -1475,13 +1475,13 @@ pub impl RegionVarBindings {
             false
         }
 
-        fn adjust_node(self: &mut RegionVarBindings,
+        fn adjust_node(this: &mut RegionVarBindings,
                        a_vid: RegionVid,
                        a_node: &mut GraphNode,
                        a_region: Region,
                        b_region: Region)
                     -> bool {
-            match self.glb_concrete_regions(a_region, b_region) {
+            match this.glb_concrete_regions(a_region, b_region) {
                 Ok(glb) => {
                     if glb == a_region {
                         false
@@ -1744,14 +1744,14 @@ pub impl RegionVarBindings {
         let WalkState {result, dup_found, _} = state;
         return (result, dup_found);
 
-        fn process_edges(self: &mut RegionVarBindings,
+        fn process_edges(this: &mut RegionVarBindings,
                          state: &mut WalkState,
                          graph: &Graph,
                          source_vid: RegionVid,
                          dir: Direction) {
             debug!("process_edges(source_vid=%?, dir=%?)", source_vid, dir);
 
-            for self.each_edge(graph, source_vid, dir) |edge| {
+            for this.each_edge(graph, source_vid, dir) |edge| {
                 match edge.constraint {
                     ConstrainVarSubVar(from_vid, to_vid) => {
                         let opp_vid =
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 48d7765f88e..8da3d7bfa00 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::ty::{BuiltinBounds};
 use middle::ty;
 use middle::ty::TyVar;
 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
@@ -99,6 +100,19 @@ impl Combine for Sub {
         })
     }
 
+    fn bounds(&self, a: BuiltinBounds, b: BuiltinBounds) -> cres<BuiltinBounds> {
+        // More bounds is a subtype of fewer bounds.
+        //
+        // e.g., fn:Copy() <: fn(), because the former is a function
+        // that only closes over copyable things, but the latter is
+        // any function at all.
+        if a.contains(b) {
+            Ok(a)
+        } else {
+            Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
+        }
+    }
+
     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         debug!("%s.tys(%s, %s)", self.tag(),
                a.inf_str(self.infcx), b.inf_str(self.infcx));
@@ -245,7 +259,7 @@ impl Combine for Sub {
         super_trait_stores(self, vk, a, b)
     }
 
-    fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
+    fn args(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         super_args(self, a, b)
     }
 
diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs
index 7c992db6703..1d24a4dbd4f 100644
--- a/src/librustc/middle/typeck/infer/test.rs
+++ b/src/librustc/middle/typeck/infer/test.rs
@@ -100,7 +100,7 @@ pub impl Env {
         return match search_mod(self, &self.crate.node.module, 0, names) {
             Some(id) => id,
             None => {
-                fail!(fmt!("No item found: `%s`", str::connect(names, "::")));
+                fail!("No item found: `%s`", str::connect(names, "::"));
             }
         };
 
@@ -153,17 +153,17 @@ pub impl Env {
 
     fn assert_subtype(&self, a: ty::t, b: ty::t) {
         if !self.is_subtype(a, b) {
-            fail!(fmt!("%s is not a subtype of %s, but it should be",
-                      self.ty_to_str(a),
-                      self.ty_to_str(b)));
+            fail!("%s is not a subtype of %s, but it should be",
+                  self.ty_to_str(a),
+                  self.ty_to_str(b));
         }
     }
 
     fn assert_not_subtype(&self, a: ty::t, b: ty::t) {
         if self.is_subtype(a, b) {
-            fail!(fmt!("%s is a subtype of %s, but it shouldn't be",
-                      self.ty_to_str(a),
-                      self.ty_to_str(b)));
+            fail!("%s is a subtype of %s, but it shouldn't be",
+                  self.ty_to_str(a),
+                  self.ty_to_str(b));
         }
     }
 
@@ -240,7 +240,7 @@ pub impl Env {
     fn check_lub(&self, t1: ty::t, t2: ty::t, t_lub: ty::t) {
         match self.lub().tys(t1, t2) {
             Err(e) => {
-                fail!(fmt!("Unexpected error computing LUB: %?", e))
+                fail!("Unexpected error computing LUB: %?", e)
             }
             Ok(t) => {
                 self.assert_eq(t, t_lub);
@@ -262,7 +262,7 @@ pub impl Env {
                self.ty_to_str(t_glb));
         match self.glb().tys(t1, t2) {
             Err(e) => {
-                fail!(fmt!("Unexpected error computing LUB: %?", e))
+                fail!("Unexpected error computing LUB: %?", e)
             }
             Ok(t) => {
                 self.assert_eq(t, t_glb);
@@ -281,8 +281,7 @@ pub impl Env {
         match self.lub().tys(t1, t2) {
             Err(_) => {}
             Ok(t) => {
-                fail!(fmt!("Unexpected success computing LUB: %?",
-                          self.ty_to_str(t)))
+                fail!("Unexpected success computing LUB: %?", self.ty_to_str(t))
             }
         }
     }
@@ -292,8 +291,7 @@ pub impl Env {
         match self.glb().tys(t1, t2) {
             Err(_) => {}
             Ok(t) => {
-                fail!(fmt!("Unexpected success computing GLB: %?",
-                          self.ty_to_str(t)))
+                fail!("Unexpected success computing GLB: %?", self.ty_to_str(t))
             }
         }
     }
diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs
index 779346c380c..d9088c06493 100644
--- a/src/librustc/middle/typeck/infer/to_str.rs
+++ b/src/librustc/middle/typeck/infer/to_str.rs
@@ -31,7 +31,7 @@ impl InferStr for ty::t {
 impl InferStr for FnSig {
     fn inf_str(&self, cx: &InferCtxt) -> ~str {
         fmt!("(%s) -> %s",
-             str::connect(self.inputs.map(|a| a.ty.inf_str(cx)), ", "),
+             str::connect(self.inputs.map(|a| a.inf_str(cx)), ", "),
              self.output.inf_str(cx))
     }
 }
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 5da14d99171..dd313c54efb 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -73,8 +73,7 @@ pub mod infer;
 pub mod collect;
 pub mod coherence;
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub enum method_origin {
     // supertrait method invoked on "self" inside a default method
     // first field is supertrait ID;
@@ -98,8 +97,7 @@ pub enum method_origin {
 
 // details for a method invoked with a receiver whose type is a type parameter
 // with a bounded trait.
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub struct method_param {
     // the trait containing the method to be invoked
     trait_id: ast::def_id,
@@ -118,13 +116,13 @@ pub struct method_param {
 pub struct method_map_entry {
     // the type of the self parameter, which is not reflected in the fn type
     // (FIXME #3446)
-    self_arg: ty::arg,
+    self_ty: ty::t,
 
     // the mode of `self`
     self_mode: ty::SelfMode,
 
     // the type of explicit self on the method
-    explicit_self: ast::self_ty_,
+    explicit_self: ast::explicit_self_,
 
     // method details being invoked
     origin: method_origin,
@@ -310,7 +308,7 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt,
                 _ => ()
             }
             let mut ok = ty::type_is_nil(fn_ty.sig.output);
-            let num_args = vec::len(fn_ty.sig.inputs);
+            let num_args = fn_ty.sig.inputs.len();
             ok &= num_args == 0u;
             if !ok {
                 tcx.sess.span_err(
@@ -351,22 +349,15 @@ fn check_start_fn_ty(ccx: @mut CrateCtxt,
                 _ => ()
             }
 
-            fn arg(ty: ty::t) -> ty::arg {
-                ty::arg {
-                    ty: ty
-                }
-            }
-
             let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy {
                 purity: ast::impure_fn,
                 abis: abi::AbiSet::Rust(),
                 sig: ty::FnSig {
                     bound_lifetime_names: opt_vec::Empty,
                     inputs: ~[
-                        arg(ty::mk_int()),
-                        arg(ty::mk_imm_ptr(tcx,
-                                           ty::mk_imm_ptr(tcx, ty::mk_u8()))),
-                        arg(ty::mk_imm_ptr(tcx, ty::mk_u8()))
+                        ty::mk_int(),
+                        ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8())),
+                        ty::mk_imm_ptr(tcx, ty::mk_u8())
                     ],
                     output: ty::mk_int()
                 }
diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs
index 316792f688f..7c37784b09d 100644
--- a/src/librustc/middle/typeck/rscope.rs
+++ b/src/librustc/middle/typeck/rscope.rs
@@ -142,7 +142,7 @@ impl RegionParameterization {
 }
 
 pub struct MethodRscope {
-    self_ty: ast::self_ty_,
+    explicit_self: ast::explicit_self_,
     variance: Option<ty::region_variance>,
     region_param_names: RegionParamNames,
 }
@@ -150,14 +150,14 @@ pub struct MethodRscope {
 impl MethodRscope {
     // `generics` here refers to the generics of the outer item (impl or
     // trait).
-    pub fn new(self_ty: ast::self_ty_,
+    pub fn new(explicit_self: ast::explicit_self_,
                variance: Option<ty::region_variance>,
                rcvr_generics: &ast::Generics)
             -> MethodRscope {
         let region_param_names =
             RegionParamNames::from_generics(rcvr_generics);
         MethodRscope {
-            self_ty: self_ty,
+            explicit_self: explicit_self,
             variance: variance,
             region_param_names: region_param_names
         }
@@ -227,7 +227,7 @@ impl region_scope for type_rscope {
             None => {
                 // if the self region is used, region parameterization should
                 // have inferred that this type is RP
-                fail!(~"region parameterization should have inferred that \
+                fail!("region parameterization should have inferred that \
                         this type is RP");
             }
             Some(ref region_parameterization) => {
@@ -267,10 +267,10 @@ pub struct binding_rscope {
 }
 
 pub fn in_binding_rscope<RS:region_scope + Copy + 'static>(
-        self: &RS,
+        this: &RS,
         region_param_names: RegionParamNames)
      -> binding_rscope {
-    let base = @copy *self;
+    let base = @copy *this;
     let base = base as @region_scope;
     binding_rscope {
         base: base,
diff --git a/src/librustc/util/enum_set.rs b/src/librustc/util/enum_set.rs
index c589ab52874..2e6c4ee3eaa 100644
--- a/src/librustc/util/enum_set.rs
+++ b/src/librustc/util/enum_set.rs
@@ -8,11 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[cfg(stage0)]
 use core;
 
 #[deriving(Eq, IterBytes)]
 pub struct EnumSet<E> {
-    bits: uint
+    // We must maintain the invariant that no bits are set
+    // for which no variant exists
+    priv bits: uint
 }
 
 pub trait CLike {
@@ -37,10 +40,18 @@ pub impl<E:CLike> EnumSet<E> {
         (self.bits & e.bits) != 0
     }
 
+    fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
+        EnumSet {bits: self.bits & e.bits}
+    }
+
     fn contains(&self, e: EnumSet<E>) -> bool {
         (self.bits & e.bits) == e.bits
     }
 
+    fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
+        EnumSet {bits: self.bits | e.bits}
+    }
+
     fn add(&mut self, e: E) {
         self.bits |= bit(e);
     }
@@ -82,19 +93,19 @@ pub impl<E:CLike> EnumSet<E> {
     }
 }
 
-impl<E:CLike> core::Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
+impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
     fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
         EnumSet {bits: self.bits & !e.bits}
     }
 }
 
-impl<E:CLike> core::BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
+impl<E:CLike> BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
     fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
         EnumSet {bits: self.bits | e.bits}
     }
 }
 
-impl<E:CLike> core::BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
+impl<E:CLike> BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
     fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
         EnumSet {bits: self.bits & e.bits}
     }
@@ -102,7 +113,6 @@ impl<E:CLike> core::BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
 
 #[cfg(test)]
 mod test {
-    use core;
     use core::iter;
     use util::enum_set::*;
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 804b23025f0..13a2f376c06 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -11,7 +11,7 @@
 use metadata::encoder;
 use middle::ty::{ReSkolemized, ReVar};
 use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
-use middle::ty::{br_fresh, ctxt, field, method};
+use middle::ty::{br_fresh, ctxt, field};
 use middle::ty::{mt, t, param_ty};
 use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region,
                  re_empty};
@@ -281,7 +281,7 @@ pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
 
 pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
     fmt!("fn%s -> %s",
-         tys_to_str(cx, typ.inputs.map(|a| a.ty)),
+         tys_to_str(cx, typ.inputs.map(|a| *a)),
          ty_to_str(cx, typ.output))
 }
 
@@ -290,8 +290,8 @@ pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
 }
 
 pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
-    fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str {
-        ty_to_str(cx, input.ty)
+    fn fn_input_to_str(cx: ctxt, input: ty::t) -> ~str {
+        ty_to_str(cx, input)
     }
     fn bare_fn_to_str(cx: ctxt,
                       purity: ast::purity,
@@ -375,7 +375,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
             }
         }
     }
-    fn method_to_str(cx: ctxt, m: method) -> ~str {
+    fn method_to_str(cx: ctxt, m: ty::Method) -> ~str {
         bare_fn_to_str(cx,
                        m.fty.purity,
                        m.fty.abis,
@@ -470,7 +470,7 @@ pub fn parameterized(cx: ctxt,
       }
     };
 
-    if vec::len(tps) > 0u {
+    if tps.len() > 0u {
         let strs = vec::map(tps, |t| ty_to_str(cx, *t));
         fmt!("%s%s<%s>", base, r_str, str::connect(strs, ","))
     } else {
@@ -633,15 +633,15 @@ impl Repr for ty::Generics {
     }
 }
 
-impl Repr for ty::method {
+impl Repr for ty::Method {
     fn repr(&self, tcx: ctxt) -> ~str {
         fmt!("method {ident: %s, generics: %s, transformed_self_ty: %s, \
-              fty: %s, self_ty: %s, vis: %s, def_id: %s}",
+              fty: %s, explicit_self: %s, vis: %s, def_id: %s}",
              self.ident.repr(tcx),
              self.generics.repr(tcx),
              self.transformed_self_ty.repr(tcx),
              self.fty.repr(tcx),
-             self.self_ty.repr(tcx),
+             self.explicit_self.repr(tcx),
              self.vis.repr(tcx),
              self.def_id.repr(tcx))
     }
@@ -653,7 +653,7 @@ impl Repr for ast::ident {
     }
 }
 
-impl Repr for ast::self_ty_ {
+impl Repr for ast::explicit_self_ {
     fn repr(&self, _tcx: ctxt) -> ~str {
         fmt!("%?", *self)
     }
@@ -685,18 +685,12 @@ impl Repr for typeck::method_map_entry {
         fmt!("method_map_entry {self_arg: %s, \
               explicit_self: %s, \
               origin: %s}",
-             self.self_arg.repr(tcx),
+             self.self_ty.repr(tcx),
              self.explicit_self.repr(tcx),
              self.origin.repr(tcx))
     }
 }
 
-impl Repr for ty::arg {
-    fn repr(&self, tcx: ctxt) -> ~str {
-        fmt!("(%s)", self.ty.repr(tcx))
-    }
-}
-
 impl Repr for typeck::method_origin {
     fn repr(&self, tcx: ctxt) -> ~str {
         match self {
diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs
index 204f3073e9c..35cbe394b86 100644
--- a/src/librustdoc/attr_pass.rs
+++ b/src/librustdoc/attr_pass.rs
@@ -103,10 +103,10 @@ fn parse_item_attrs<T:Owned>(
     id: doc::AstId,
     parse_attrs: ~fn(a: ~[ast::attribute]) -> T) -> T {
     do astsrv::exec(srv) |ctxt| {
-        let attrs = match *ctxt.ast_map.get(&id) {
+        let attrs = match ctxt.ast_map.get_copy(&id) {
             ast_map::node_item(item, _) => copy item.attrs,
             ast_map::node_foreign_item(item, _, _, _) => copy item.attrs,
-            _ => fail!(~"parse_item_attrs: not an item")
+            _ => fail!("parse_item_attrs: not an item")
         };
         parse_attrs(attrs)
     }
@@ -127,7 +127,7 @@ fn fold_enum(
             let desc = {
                 let variant = copy variant;
                 do astsrv::exec(srv.clone()) |ctxt| {
-                    match *ctxt.ast_map.get(&doc_id) {
+                    match ctxt.ast_map.get_copy(&doc_id) {
                         ast_map::node_item(@ast::item {
                             node: ast::item_enum(ref enum_definition, _), _
                         }, _) => {
@@ -140,9 +140,8 @@ fn fold_enum(
                                 copy ast_variant.node.attrs)
                         }
                         _ => {
-                            fail!(fmt!("Enum variant %s has id that's \
-                                        not bound to an enum item",
-                                       variant.name))
+                            fail!("Enum variant %s has id that's not bound to an enum item",
+                                  variant.name)
                         }
                     }
                 }
@@ -178,7 +177,7 @@ fn merge_method_attrs(
 
     // Create an assoc list from method name to attributes
     let attrs: ~[(~str, Option<~str>)] = do astsrv::exec(srv) |ctxt| {
-        match *ctxt.ast_map.get(&item_id) {
+        match ctxt.ast_map.get_copy(&item_id) {
             ast_map::node_item(@ast::item {
                 node: ast::item_trait(_, _, ref methods), _
             }, _) => {
@@ -202,7 +201,7 @@ fn merge_method_attrs(
                      attr_parser::parse_desc(copy method.attrs))
                 })
             }
-            _ => fail!(~"unexpected item")
+            _ => fail!("unexpected item")
         }
     };
 
diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs
index d9e24453652..24bfa62305a 100644
--- a/src/librustdoc/markdown_index_pass.rs
+++ b/src/librustdoc/markdown_index_pass.rs
@@ -253,20 +253,6 @@ mod test {
     }
 
     #[test]
-    fn should_index_foreign_mod_pages() {
-        let doc = mk_doc(
-            config::DocPerMod,
-            ~"extern mod a { }"
-        );
-        assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry {
-            kind: ~"Foreign module",
-            name: ~"a",
-            brief: None,
-            link: ~"a.html"
-        });
-    }
-
-    #[test]
     fn should_add_brief_desc_to_index() {
         let doc = mk_doc(
             config::DocPerMod,
@@ -280,7 +266,7 @@ mod test {
     fn should_index_foreign_mod_contents() {
         let doc = mk_doc(
             config::DocPerCrate,
-            ~"extern mod a { fn b(); }"
+            ~"extern { fn b(); }"
         );
         assert!((&doc.cratemod().nmods()[0].index).get().entries[0]
                 == doc::IndexEntry {
diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs
index e376e4afa5c..a42c4738b2d 100644
--- a/src/librustdoc/markdown_pass.rs
+++ b/src/librustdoc/markdown_pass.rs
@@ -401,7 +401,7 @@ fn write_sig(ctxt: &Ctxt, sig: Option<~str>) {
             ctxt.w.put_line(code_block_indent(sig));
             ctxt.w.put_line(~"");
         }
-        None => fail!(~"unimplemented")
+        None => fail!("unimplemented")
     }
 }
 
@@ -702,7 +702,7 @@ mod test {
 
     #[test]
     fn should_write_index_for_foreign_mods() {
-        let markdown = render(~"extern mod a { fn a(); }");
+        let markdown = render(~"extern { fn a(); }");
         assert!(str::contains(
             markdown,
             ~"\n\n* [Function `a`](#function-a)\n\n"
@@ -710,23 +710,16 @@ mod test {
     }
 
     #[test]
-    fn should_write_foreign_mods() {
-        let markdown = render(~"#[doc = \"test\"] extern mod a { }");
-        assert!(str::contains(markdown, ~"Foreign module `a`"));
-        assert!(str::contains(markdown, ~"test"));
-    }
-
-    #[test]
     fn should_write_foreign_fns() {
         let markdown = render(
-            ~"extern mod a { #[doc = \"test\"] fn a(); }");
+            ~"extern { #[doc = \"test\"] fn a(); }");
         assert!(str::contains(markdown, ~"test"));
     }
 
     #[test]
     fn should_write_foreign_fn_headers() {
         let markdown = render(
-            ~"extern mod a { #[doc = \"test\"] fn a(); }");
+            ~"extern { #[doc = \"test\"] fn a(); }");
         assert!(str::contains(markdown, ~"## Function `a`"));
     }
 
diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs
index e56b0fb60cd..456a5f09a88 100644
--- a/src/librustdoc/markdown_writer.rs
+++ b/src/librustdoc/markdown_writer.rs
@@ -135,7 +135,7 @@ fn pandoc_writer(
         if status != 0 {
             error!("pandoc-out: %s", stdout);
             error!("pandoc-err: %s", stderr);
-            fail!(~"pandoc failed");
+            fail!("pandoc failed");
         }
     }
 }
diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs
index a50f1f51765..c7fe29b3296 100644
--- a/src/librustdoc/prune_hidden_pass.rs
+++ b/src/librustdoc/prune_hidden_pass.rs
@@ -53,7 +53,7 @@ fn is_hidden(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool {
 
     let id = doc.id;
     do astsrv::exec(srv) |ctxt| {
-        let attrs = match *ctxt.ast_map.get(&id) {
+        let attrs = match ctxt.ast_map.get_copy(&id) {
           ast_map::node_item(item, _) => copy item.attrs,
           _ => ~[]
         };
diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs
index 210ca5cfe70..086b5f47601 100644
--- a/src/librustdoc/prune_private_pass.rs
+++ b/src/librustdoc/prune_private_pass.rs
@@ -55,7 +55,7 @@ fn fold_impl(
     let doc = fold::default_seq_fold_impl(fold, doc);
 
     do astsrv::exec(fold.ctxt.clone()) |ctxt| {
-        match *ctxt.ast_map.get(&doc.item.id) {
+        match ctxt.ast_map.get_copy(&doc.item.id) {
             ast_map::node_item(item, _) => {
                 match item.node {
                     ast::item_impl(_, None, _, ref methods) => {
@@ -134,7 +134,7 @@ fn is_visible(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool {
     let id = doc.id;
 
     do astsrv::exec(srv) |ctxt| {
-        match *ctxt.ast_map.get(&id) {
+        match ctxt.ast_map.get_copy(&id) {
             ast_map::node_item(item, _) => {
                 match &item.node {
                     &ast::item_impl(*) => {
diff --git a/src/librustdoc/sort_item_type_pass.rs b/src/librustdoc/sort_item_type_pass.rs
index d75565d4ec8..158d407fff6 100644
--- a/src/librustdoc/sort_item_type_pass.rs
+++ b/src/librustdoc/sort_item_type_pass.rs
@@ -43,8 +43,6 @@ fn test() {
 
     let source =
         ~"mod imod { } \
-         extern mod inmod {
-         } \
          static iconst: int = 0; \
          fn ifn() { } \
          enum ienum { ivar } \
@@ -63,6 +61,5 @@ fn test() {
         assert!(doc.cratemod().items[5].name() == ~"__extensions__");
         assert!(doc.cratemod().items[6].name() == ~"ifn");
         assert!(doc.cratemod().items[7].name() == ~"imod");
-        assert!(doc.cratemod().items[8].name() == ~"inmod");
     }
 }
diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs
index def32bdfd44..12689466c8c 100644
--- a/src/librustdoc/tystr_pass.rs
+++ b/src/librustdoc/tystr_pass.rs
@@ -63,7 +63,7 @@ fn fold_fn(
 
 fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> {
     do astsrv::exec(srv) |ctxt| {
-        match *ctxt.ast_map.get(&fn_id) {
+        match ctxt.ast_map.get_copy(&fn_id) {
             ast_map::node_item(@ast::item {
                 ident: ident,
                 node: ast::item_fn(ref decl, purity, _, ref tys, _), _
@@ -75,7 +75,7 @@ fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> {
                 Some(pprust::fun_to_str(decl, purity, ident, None, tys,
                                         extract::interner()))
             }
-            _ => fail!(~"get_fn_sig: fn_id not bound to a fn item")
+            _ => fail!("get_fn_sig: fn_id not bound to a fn item")
         }
     }
 }
@@ -90,13 +90,13 @@ fn fold_const(
         sig: Some({
             let doc = copy doc;
             do astsrv::exec(srv) |ctxt| {
-                match *ctxt.ast_map.get(&doc.id()) {
+                match ctxt.ast_map.get_copy(&doc.id()) {
                     ast_map::node_item(@ast::item {
                         node: ast::item_const(ty, _), _
                     }, _) => {
                         pprust::ty_to_str(ty, extract::interner())
                     }
-                    _ => fail!(~"fold_const: id not bound to a const item")
+                    _ => fail!("fold_const: id not bound to a const item")
                 }
             }}),
         .. doc
@@ -115,7 +115,7 @@ fn fold_enum(
             let sig = {
                 let variant = copy *variant;
                 do astsrv::exec(srv.clone()) |ctxt| {
-                    match *ctxt.ast_map.get(&doc_id) {
+                    match ctxt.ast_map.get_copy(&doc_id) {
                         ast_map::node_item(@ast::item {
                             node: ast::item_enum(ref enum_definition, _), _
                         }, _) => {
@@ -125,9 +125,9 @@ fn fold_enum(
                             }.get();
 
                             pprust::variant_to_str(
-                                ast_variant, extract::interner())
+                                &ast_variant, extract::interner())
                         }
-                        _ => fail!(~"enum variant not bound to an enum item")
+                        _ => fail!("enum variant not bound to an enum item")
                     }
                 }
             };
@@ -170,7 +170,7 @@ fn get_method_sig(
     method_name: ~str
 ) -> Option<~str> {
     do astsrv::exec(srv) |ctxt| {
-        match *ctxt.ast_map.get(&item_id) {
+        match ctxt.ast_map.get_copy(&item_id) {
             ast_map::node_item(@ast::item {
                 node: ast::item_trait(_, _, ref methods), _
             }, _) => {
@@ -187,7 +187,7 @@ fn get_method_sig(
                                     &ty_m.decl,
                                     ty_m.purity,
                                     ty_m.ident,
-                                    Some(ty_m.self_ty.node),
+                                    Some(ty_m.explicit_self.node),
                                     &ty_m.generics,
                                     extract::interner()
                                 ))
@@ -197,14 +197,14 @@ fn get_method_sig(
                                     &m.decl,
                                     m.purity,
                                     m.ident,
-                                    Some(m.self_ty.node),
+                                    Some(m.explicit_self.node),
                                     &m.generics,
                                     extract::interner()
                                 ))
                             }
                         }
                     }
-                    _ => fail!(~"method not found")
+                    _ => fail!("method not found")
                 }
             }
             ast_map::node_item(@ast::item {
@@ -218,15 +218,15 @@ fn get_method_sig(
                             &method.decl,
                             method.purity,
                             method.ident,
-                            Some(method.self_ty.node),
+                            Some(method.explicit_self.node),
                             &method.generics,
                             extract::interner()
                         ))
                     }
-                    None => fail!(~"method not found")
+                    None => fail!("method not found")
                 }
             }
-            _ => fail!(~"get_method_sig: item ID not bound to trait or impl")
+            _ => fail!("get_method_sig: item ID not bound to trait or impl")
         }
     }
 }
@@ -241,7 +241,7 @@ fn fold_impl(
     let (bounds, trait_types, self_ty) = {
         let doc = copy doc;
         do astsrv::exec(srv) |ctxt| {
-            match *ctxt.ast_map.get(&doc.id()) {
+            match ctxt.ast_map.get_copy(&doc.id()) {
                 ast_map::node_item(@ast::item {
                     node: ast::item_impl(ref generics, opt_trait_type, self_ty, _), _
                 }, _) => {
@@ -255,7 +255,7 @@ fn fold_impl(
                      Some(pprust::ty_to_str(
                          self_ty, extract::interner())))
                 }
-                _ => fail!(~"expected impl")
+                _ => fail!("expected impl")
             }
         }
     };
@@ -280,7 +280,7 @@ fn fold_type(
         sig: {
             let doc = copy doc;
             do astsrv::exec(srv) |ctxt| {
-                match *ctxt.ast_map.get(&doc.id()) {
+                match ctxt.ast_map.get_copy(&doc.id()) {
                     ast_map::node_item(@ast::item {
                         ident: ident,
                         node: ast::item_ty(ty, ref params), _
@@ -294,7 +294,7 @@ fn fold_type(
                                               extract::interner())
                         ))
                     }
-                    _ => fail!(~"expected type")
+                    _ => fail!("expected type")
                 }
             }
         },
@@ -312,13 +312,13 @@ fn fold_struct(
         sig: {
             let doc = copy doc;
             do astsrv::exec(srv) |ctxt| {
-                match *ctxt.ast_map.get(&doc.id()) {
+                match ctxt.ast_map.get_copy(&doc.id()) {
                     ast_map::node_item(item, _) => {
                         let item = strip_struct_extra_stuff(item);
                         Some(pprust::item_to_str(item,
                                                  extract::interner()))
                     }
-                    _ => fail!(~"not an item")
+                    _ => fail!("not an item")
                 }
             }
         },
@@ -333,7 +333,7 @@ fn fold_struct(
 fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item {
     let node = match copy item.node {
         ast::item_struct(def, tys) => ast::item_struct(def, tys),
-        _ => fail!(~"not a struct")
+        _ => fail!("not a struct")
     };
 
     @ast::item {
@@ -365,7 +365,7 @@ mod test {
 
     #[test]
     fn should_add_foreign_fn_sig() {
-        let doc = mk_doc(~"extern mod a { fn a<T>() -> int; }");
+        let doc = mk_doc(~"extern { fn a<T>() -> int; }");
         assert!(doc.cratemod().nmods()[0].fns[0].sig ==
                 Some(~"fn a<T>() -> int"));
     }
@@ -405,7 +405,7 @@ mod test {
     #[test]
     fn should_not_add_impl_trait_types_if_none() {
         let doc = mk_doc(~"impl int { fn a() { } }");
-        assert!(vec::len(doc.cratemod().impls()[0].trait_types) == 0);
+        assert!(doc.cratemod().impls()[0].trait_types.len() == 0);
     }
 
     #[test]
diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc
index 836ca1cfa45..4a03d31e5db 100644
--- a/src/librusti/rusti.rc
+++ b/src/librusti/rusti.rc
@@ -18,14 +18,12 @@
 #[license = "MIT/ASL2"];
 #[crate_type = "lib"];
 
-#[allow(vecs_implicitly_copyable,
-        non_implicitly_copyable_typarams)];
-
 extern mod std(vers = "0.7-pre");
 extern mod rustc(vers = "0.7-pre");
 extern mod syntax(vers = "0.7-pre");
 
 use core::*;
+use core::cell::Cell;
 use rustc::driver::{driver, session};
 use syntax::{ast, diagnostic};
 use syntax::ast_util::*;
@@ -37,7 +35,7 @@ use std::rl;
  * A structure shared across REPL instances for storing history
  * such as statements and view items. I wish the AST was sendable.
  */
-struct Repl {
+pub struct Repl {
     prompt: ~str,
     binary: ~str,
     running: bool,
@@ -71,8 +69,8 @@ fn with_pp(intr: @token::ident_interner,
  * because it has to parse the statements and view_items on each
  * input.
  */
-fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
-    let view_items = if blk.node.view_items.len() > 0 {
+fn record(mut repl: Repl, blk: &ast::blk, intr: @token::ident_interner) -> Repl {
+    if blk.node.view_items.len() > 0 {
         let new_view_items = do with_pp(intr) |pp, writer| {
             for blk.node.view_items.each |view_item| {
                 pprust::print_view_item(pp, *view_item);
@@ -82,9 +80,9 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
 
         debug!("new view items %s", new_view_items);
 
-        repl.view_items + "\n" + new_view_items
-    } else { repl.view_items };
-    let stmts = if blk.node.stmts.len() > 0 {
+        repl.view_items = repl.view_items + "\n" + new_view_items
+    }
+    if blk.node.stmts.len() > 0 {
         let new_stmts = do with_pp(intr) |pp, writer| {
             for blk.node.stmts.each |stmt| {
                 match stmt.node {
@@ -105,29 +103,26 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
 
         debug!("new stmts %s", new_stmts);
 
-        repl.stmts + "\n" + new_stmts
-    } else { repl.stmts };
-
-    Repl{
-        view_items: view_items,
-        stmts: stmts,
-        .. repl
+        repl.stmts = repl.stmts + "\n" + new_stmts
     }
+
+    return repl;
 }
 
 /// Run an input string in a Repl, returning the new Repl.
 fn run(repl: Repl, input: ~str) -> Repl {
+    let binary = @copy repl.binary;
     let options = @session::options {
         crate_type: session::unknown_crate,
-        binary: @repl.binary,
+        binary: binary,
         addl_lib_search_paths: repl.lib_search_paths.map(|p| Path(*p)),
         jit: true,
-        .. *session::basic_options()
+        .. copy *session::basic_options()
     };
 
     debug!("building driver input");
     let head = include_str!("wrapper.rs").to_owned();
-    let foot = fmt!("%s\nfn main() {\n%s\n\nprint({\n%s\n})\n}",
+    let foot = fmt!("fn main() {\n%s\n%s\n\nprint({\n%s\n})\n}",
                     repl.view_items, repl.stmts, input);
     let wrapped = driver::str_input(head + foot);
 
@@ -138,7 +133,7 @@ fn run(repl: Repl, input: ~str) -> Repl {
 
     debug!("building driver configuration");
     let cfg = driver::build_configuration(sess,
-                                          @repl.binary,
+                                          binary,
                                           &wrapped);
 
     let outputs = driver::build_output_filenames(&wrapped, &None, &None, sess);
@@ -151,7 +146,7 @@ fn run(repl: Repl, input: ~str) -> Repl {
 
     for crate.node.module.items.each |item| {
         match item.node {
-            ast::item_fn(_, _, _, _, blk) => {
+            ast::item_fn(_, _, _, _, ref blk) => {
                 if item.ident == sess.ident_of("main") {
                     opt = blk.node.expr;
                 }
@@ -160,10 +155,11 @@ fn run(repl: Repl, input: ~str) -> Repl {
         }
     }
 
-    let blk = match opt.get().node {
-        ast::expr_call(_, exprs, _) => {
+    let e = opt.unwrap();
+    let blk = match e.node {
+        ast::expr_call(_, ref exprs, _) => {
             match exprs[0].node {
-                ast::expr_block(blk) => @blk,
+                ast::expr_block(ref blk) => blk,
                 _ => fail!()
             }
         }
@@ -182,15 +178,16 @@ fn run(repl: Repl, input: ~str) -> Repl {
 fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
     match do task::try {
         let src_path = Path(src_filename);
+        let binary = @copy binary;
         let options = @session::options {
-            binary: @binary,
+            binary: binary,
             addl_lib_search_paths: ~[os::getcwd()],
-            .. *session::basic_options()
+            .. copy *session::basic_options()
         };
-        let input = driver::file_input(src_path);
+        let input = driver::file_input(copy src_path);
         let sess = driver::build_session(options, diagnostic::emit);
         *sess.building_library = true;
-        let cfg = driver::build_configuration(sess, @binary, &input);
+        let cfg = driver::build_configuration(sess, binary, &input);
         let outputs = driver::build_output_filenames(
             &input, &None, &None, sess);
         // If the library already exists and is newer than the source
@@ -233,7 +230,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
 
 /// Tries to get a line from rl after outputting a prompt. Returns
 /// None if no input was read (e.g. EOF was reached).
-fn get_line(use_rl: bool, prompt: ~str) -> Option<~str> {
+fn get_line(use_rl: bool, prompt: &str) -> Option<~str> {
     if use_rl {
         let result = unsafe { rl::read(prompt) };
 
@@ -280,11 +277,11 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
             for args.each |arg| {
                 let (crate, filename) =
                     if arg.ends_with(".rs") || arg.ends_with(".rc") {
-                    (arg.substr(0, arg.len() - 3).to_owned(), *arg)
+                    (arg.substr(0, arg.len() - 3).to_owned(), copy *arg)
                 } else {
-                    (*arg, arg + ~".rs")
+                    (copy *arg, arg + ".rs")
                 };
-                match compile_crate(filename, repl.binary) {
+                match compile_crate(filename, copy repl.binary) {
                     Some(_) => loaded_crates.push(crate),
                     None => { }
                 }
@@ -311,8 +308,8 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
             let mut multiline_cmd = ~"";
             let mut end_multiline = false;
             while (!end_multiline) {
-                match get_line(use_rl, ~"rusti| ") {
-                    None => fail!(~"unterminated multiline command :{ .. :}"),
+                match get_line(use_rl, "rusti| ") {
+                    None => fail!("unterminated multiline command :{ .. :}"),
                     Some(line) => {
                         if str::trim(line) == ~":}" {
                             end_multiline = true;
@@ -331,17 +328,17 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
 
 /// Executes a line of input, which may either be rust code or a
 /// :command. Returns a new Repl if it has changed.
-fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
-            use_rl: bool)
+pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
+                use_rl: bool)
     -> Option<Repl> {
-    if line.starts_with(~":") {
+    if line.starts_with(":") {
         let full = line.substr(1, line.len() - 1);
         let mut split = ~[];
         for str::each_word(full) |word| { split.push(word.to_owned()) }
         let len = split.len();
 
         if len > 0 {
-            let cmd = split[0];
+            let cmd = copy split[0];
 
             if !cmd.is_empty() {
                 let args = if len > 1 {
@@ -361,9 +358,10 @@ fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
         }
     }
 
-    let r = *repl;
+    let line = Cell(line);
+    let r = Cell(copy *repl);
     let result = do task::try {
-        run(r, line)
+        run(r.take(), line.take())
     };
 
     if result.is_ok() {
@@ -378,7 +376,7 @@ pub fn main() {
     let out = io::stdout();
     let mut repl = Repl {
         prompt: ~"rusti> ",
-        binary: args[0],
+        binary: copy args[0],
         running: true,
         view_items: ~"",
         lib_search_paths: ~[],
@@ -423,3 +421,52 @@ pub fn main() {
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn repl() -> Repl {
+        Repl {
+            prompt: ~"rusti> ",
+            binary: ~"rusti",
+            running: true,
+            view_items: ~"",
+            lib_search_paths: ~[],
+            stmts: ~""
+        }
+    }
+
+    fn run_cmds(cmds: &[&str]) {
+        let mut r = repl();
+        for cmds.each |&cmd| {
+            let result = run_line(&mut r, io::stdin(), io::stdout(),
+                                  cmd.to_owned(), false);
+            r = result.expect(fmt!("the command '%s' failed", cmd));
+        }
+    }
+
+    #[test] #[ignore]
+    fn run_all() {
+        // By default, unit tests are run in parallel. Rusti, on the other hand,
+        // does not enjoy doing this. I suspect that it is because the LLVM
+        // bindings are not thread-safe (when running parallel tests, some tests
+        // were triggering assertions in LLVM (or segfaults). Hence, this
+        // function exists to run everything serially (sadface).
+        //
+        // To get some interesting output, run with RUST_LOG=rusti::tests
+
+        debug!("hopefully this runs");
+        run_cmds([""]);
+
+        debug!("regression test for #5937");
+        run_cmds(["use core;", ""]);
+
+        debug!("regression test for #5784");
+        run_cmds(["let a = 1;"]);
+
+        debug!("regression test for #5803");
+        run_cmds(["spawn( || println(\"Please don't segfault\") );",
+                  "do spawn { println(\"Please?\"); }"]);
+    }
+}
diff --git a/src/librusti/wrapper.rs b/src/librusti/wrapper.rs
index 7766602dd89..9c3026f0915 100644
--- a/src/librusti/wrapper.rs
+++ b/src/librusti/wrapper.rs
@@ -13,13 +13,15 @@
 #[allow(implicit_copies)];
 #[allow(managed_heap_memory)];
 #[allow(non_camel_case_types)];
-#[allow(non_implicitly_copyable_typarams)];
 #[allow(owned_heap_memory)];
 #[allow(path_statement)];
 #[allow(unrecognized_lint)];
 #[allow(unused_imports)];
-#[allow(vecs_implicitly_copyable)];
 #[allow(while_true)];
+#[allow(unused_variable)];
+#[allow(dead_assignment)];
+#[allow(unused_unsafe)];
+#[allow(unused_mut)];
 
 extern mod std;
 
diff --git a/src/librustpkg/conditions.rs b/src/librustpkg/conditions.rs
index 5b19a3bd660..680e0924d79 100644
--- a/src/librustpkg/conditions.rs
+++ b/src/librustpkg/conditions.rs
@@ -28,3 +28,7 @@ condition! {
 condition! {
     missing_pkg_files: (super::PkgId) -> ();
 }
+
+condition! {
+    bad_pkg_id: (super::Path, ~str) -> ::util::PkgId;
+}
diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs
index d21fdcda7f7..bbd8d092354 100644
--- a/src/librustpkg/path_util.rs
+++ b/src/librustpkg/path_util.rs
@@ -10,12 +10,10 @@
 
 // rustpkg utilities having to do with paths and directories
 
-use util::PkgId;
+pub use util::{PkgId, RemotePath, LocalPath};
 use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
 use core::os::mkdir_recursive;
-
-#[deriving(Eq)]
-pub enum OutputType { Main, Lib, Bench, Test }
+pub use util::{normalize, OutputType, Main, Lib, Bench, Test};
 
 /// Returns the value of RUST_PATH, as a list
 /// of Paths. In general this should be read from the
@@ -31,67 +29,73 @@ pub static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
 /// succeeded.
 pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, u_rwx) }
 
-/// Replace all occurrences of '-' in the stem part of path with '_'
-/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
-/// as the same name
-pub fn normalize(p: ~Path) -> ~Path {
-    match p.filestem() {
-        None => p,
-        Some(st) => {
-            let replaced = str::replace(st, "-", "_");
-            if replaced != st {
-                ~p.with_filestem(replaced)
-            }
-            else {
-                p
-            }
-        }
-    }
-}
-
 // n.b. So far this only handles local workspaces
 // n.b. The next three functions ignore the package version right
 // now. Should fix that.
 
 /// True if there's a directory in <workspace> with
 /// pkgid's short name
-pub fn workspace_contains_package_id(pkgid: PkgId, workspace: &Path) -> bool {
-    let pkgpath = workspace.push("src").push(pkgid.path.to_str());
+pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
+    let pkgpath = workspace.push("src").push(pkgid.local_path.to_str());
     os::path_is_dir(&pkgpath)
 }
 
 /// Return the directory for <pkgid>'s source files in <workspace>.
 /// Doesn't check that it exists.
-pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     let result = workspace.push("src");
-    result.push(pkgid.path.to_str())
+    result.push(pkgid.local_path.to_str())
 }
 
 /// Figure out what the executable name for <pkgid> in <workspace>'s build
 /// directory is, and if the file exists, return it.
-pub fn built_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path> {
+pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
     let mut result = workspace.push("build");
-    result = result.push_rel(&pkgid.path);
     // should use a target-specific subdirectory
-    result = mk_output_path(Main, fmt!("%s-%s", pkgid.path.to_str(), pkgid.version.to_str()),
-                                       result);
+    result = mk_output_path(Main, pkgid, &result);
     debug!("built_executable_in_workspace: checking whether %s exists",
            result.to_str());
     if os::path_exists(&result) {
         Some(result)
     }
     else {
+        // This is not an error, but it's worth logging it
+        error!(fmt!("built_executable_in_workspace: %s does not exist", result.to_str()));
         None
     }
 }
 
-/// Figure out what the library name for <pkgid> in <workspace>'s build
+/// Figure out what the test name for <pkgid> in <workspace>'s build
+/// directory is, and if the file exists, return it.
+pub fn built_test_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
+    output_in_workspace(pkgid, workspace, Test)
+}
+
+/// Figure out what the test name for <pkgid> in <workspace>'s build
 /// directory is, and if the file exists, return it.
-pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path> {
+pub fn built_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
+    output_in_workspace(pkgid, workspace, Bench)
+}
+
+fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Option<Path> {
     let mut result = workspace.push("build");
-    result = result.push_rel(&pkgid.path);
     // should use a target-specific subdirectory
-    result = mk_output_path(Lib, pkgid.path.to_str(), result);
+    result = mk_output_path(what, pkgid, &result);
+    debug!("output_in_workspace: checking whether %s exists",
+           result.to_str());
+    if os::path_exists(&result) {
+        Some(result)
+    }
+    else {
+        error!(fmt!("output_in_workspace: %s does not exist", result.to_str()));
+        None
+    }
+}
+
+/// Figure out what the library name for <pkgid> in <workspace>'s build
+/// directory is, and if the file exists, return it.
+pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
+    let result = mk_output_path(Lib, pkgid, &workspace.push("build"));
     debug!("built_library_in_workspace: checking whether %s exists",
            result.to_str());
 
@@ -100,8 +104,7 @@ pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path
     let dir_contents = os::list_dir(&result.pop());
     debug!("dir has %? entries", dir_contents.len());
 
-    // n.b. This code assumes the pkgid's path only has one element
-    let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, pkgid.path.to_str());
+    let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, pkgid.short_name);
     let lib_filetype = fmt!("%s%s", pkgid.version.to_str(), os::consts::DLL_SUFFIX);
 
     debug!("lib_prefix = %s and lib_filetype = %s", lib_prefix, lib_filetype);
@@ -159,7 +162,7 @@ pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option<Path
 /// Returns the executable that would be installed for <pkgid>
 /// in <workspace>
 /// As a side effect, creates the bin-dir if it doesn't exist
-pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     target_file_in_workspace(pkgid, workspace, Main)
 }
 
@@ -167,48 +170,47 @@ pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
 /// Returns the executable that would be installed for <pkgid>
 /// in <workspace>
 /// As a side effect, creates the bin-dir if it doesn't exist
-pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     target_file_in_workspace(pkgid, workspace, Lib)
 }
 
 /// Returns the test executable that would be installed for <pkgid>
 /// in <workspace>
-pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+/// note that we *don't* install test executables, so this is just for unit testing
+pub fn target_test_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     target_file_in_workspace(pkgid, workspace, Test)
 }
 
 /// Returns the bench executable that would be installed for <pkgid>
 /// in <workspace>
-pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+/// note that we *don't* install bench executables, so this is just for unit testing
+pub fn target_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     target_file_in_workspace(pkgid, workspace, Bench)
 }
 
-fn target_file_in_workspace(pkgid: PkgId, workspace: &Path,
+fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
                             what: OutputType) -> Path {
     use conditions::bad_path::cond;
 
-    let (subdir, create_dir) = match what {
-        Main => ("bin", true), Lib => ("lib", true), Test | Bench => ("build", false)
+    let subdir = match what {
+        Lib => "lib", Main | Test | Bench => "bin"
     };
     let result = workspace.push(subdir);
-    if create_dir {
-        if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
-            cond.raise((result, fmt!("I couldn't create the %s dir", subdir)));
-        }
+    if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
+        cond.raise((copy result, fmt!("I couldn't create the %s dir", subdir)));
     }
-    mk_output_path(what, pkgid.path.to_str(), result)
-
+    mk_output_path(what, pkgid, &result)
 }
 
 /// Return the directory for <pkgid>'s build artifacts in <workspace>.
 /// Creates it if it doesn't exist.
-pub fn build_pkg_id_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
     use conditions::bad_path::cond;
 
     let mut result = workspace.push("build");
     // n.b. Should actually use a target-specific
     // subdirectory of build/
-    result = result.push(normalize(~pkgid.path).to_str());
+    result = result.push_rel(&*pkgid.local_path);
     if os::path_exists(&result) || os::mkdir_recursive(&result, u_rwx) {
         result
     }
@@ -219,15 +221,26 @@ pub fn build_pkg_id_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
 
 /// Return the output file for a given directory name,
 /// given whether we're building a library and whether we're building tests
-pub fn mk_output_path(what: OutputType, short_name: ~str, dir: Path) -> Path {
-    match what {
-        Lib => dir.push(os::dll_filename(short_name)),
-        _ => dir.push(fmt!("%s%s%s", short_name,
+pub fn mk_output_path(what: OutputType, pkg_id: &PkgId, workspace: &Path) -> Path {
+    let short_name_with_version = pkg_id.short_name_with_version();
+    // Not local_path.dir_path()! For package foo/bar/blat/, we want
+    // the executable blat-0.5 to live under blat/
+    let dir = workspace.push_rel(&*pkg_id.local_path);
+    debug!("mk_output_path: short_name = %s, path = %s",
+           if what == Lib { copy short_name_with_version } else { copy pkg_id.short_name },
+           dir.to_str());
+    let output_path = match what {
+        // this code is duplicated from elsewhere; fix this
+        Lib => dir.push(os::dll_filename(short_name_with_version)),
+        // executable names *aren't* versioned
+        _ => dir.push(fmt!("%s%s%s", copy pkg_id.short_name,
                            match what {
                                Test => "test",
                                Bench => "bench",
                                _     => ""
                            }
                            os::EXE_SUFFIX))
-    }
+    };
+    debug!("mk_output_path: returning %s", output_path.to_str());
+    output_path
 }
diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc
index 502f34a4d9e..a69613776ef 100644
--- a/src/librustpkg/rustpkg.rc
+++ b/src/librustpkg/rustpkg.rc
@@ -17,8 +17,6 @@
 
 #[license = "MIT/ASL2"];
 #[crate_type = "lib"];
-#[allow(vecs_implicitly_copyable,
-        non_implicitly_copyable_typarams)];
 
 extern mod std(vers = "0.7-pre");
 extern mod rustc(vers = "0.7-pre");
@@ -32,17 +30,16 @@ use rustc::metadata::filesearch;
 use std::{getopts};
 use syntax::{ast, diagnostic};
 use util::*;
-use path_util::normalize;
-use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace};
+use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, u_rwx};
 use path_util::{built_executable_in_workspace, built_library_in_workspace};
 use path_util::{target_executable_in_workspace, target_library_in_workspace};
 use workspace::pkg_parent_workspaces;
-use rustc::driver::session::{lib_crate, bin_crate, crate_type};
 use context::Ctx;
 
 mod conditions;
 mod context;
 mod path_util;
+#[cfg(test)]
 mod tests;
 mod util;
 mod workspace;
@@ -52,9 +49,9 @@ pub mod usage;
 /// A PkgScript represents user-supplied custom logic for
 /// special build hooks. This only exists for packages with
 /// an explicit package script.
-struct PkgScript {
+struct PkgScript<'self> {
     /// Uniquely identifies this package
-    id: PkgId,
+    id: &'self PkgId,
     // Used to have this field:    deps: ~[(~str, Option<~str>)]
     // but I think it shouldn't be stored here
     /// The contents of the package script: either a file path,
@@ -71,24 +68,24 @@ struct PkgScript {
     build_dir: Path
 }
 
-impl PkgScript {
+impl<'self> PkgScript<'self> {
     /// Given the path name for a package script
     /// and a package ID, parse the package script into
     /// a PkgScript that we can then execute
-    fn parse(script: Path, workspace: &Path, id: PkgId) -> PkgScript {
+    fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> {
         // Get the executable name that was invoked
-        let binary = os::args()[0];
+        let binary = @copy os::args()[0];
         // Build the rustc session data structures to pass
         // to the compiler
         let options = @session::options {
-            binary: @binary,
+            binary: binary,
             crate_type: session::bin_crate,
-            .. *session::basic_options()
+            .. copy *session::basic_options()
         };
         let input = driver::file_input(script);
         let sess = driver::build_session(options, diagnostic::emit);
-        let cfg = driver::build_configuration(sess, @binary, &input);
-        let (crate, _) = driver::compile_upto(sess, cfg, &input,
+        let cfg = driver::build_configuration(sess, binary, &input);
+        let (crate, _) = driver::compile_upto(sess, copy cfg, &input,
                                               driver::cu_parse, None);
         let work_dir = build_pkg_id_in_workspace(id, workspace);
 
@@ -123,10 +120,10 @@ impl PkgScript {
                 let root = r.pop().pop().pop().pop(); // :-\
                 debug!("Root is %s, calling compile_rest", root.to_str());
                 let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
-                util::compile_crate_from_input(self.input, self.id,
-                                               Some(self.build_dir),
+                util::compile_crate_from_input(&self.input, self.id,
+                                               Some(copy self.build_dir),
                                                sess, Some(crate),
-                                               exe, os::args()[0],
+                                               &exe, @copy os::args()[0],
                                                driver::cu_everything);
                 debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what);
                 let status = run::run_program(exe.to_str(), ~[root.to_str(), what]);
@@ -146,8 +143,7 @@ impl PkgScript {
                 }
             }
             Err(e) => {
-                fail!(fmt!("Running package script, couldn't find rustpkg sysroot (%s)",
-                           e))
+                fail!("Running package script, couldn't find rustpkg sysroot (%s)", e)
             }
         }
     }
@@ -161,27 +157,6 @@ impl PkgScript {
 impl Ctx {
 
     fn run(&self, cmd: ~str, args: ~[~str]) {
-        let root = util::root();
-
-        util::need_dir(&root);
-        util::need_dir(&root.push(~"work"));
-        util::need_dir(&root.push(~"lib"));
-        util::need_dir(&root.push(~"bin"));
-        util::need_dir(&root.push(~"tmp"));
-
-        fn sep_name_vers(in: ~str) -> (Option<~str>, Option<~str>) {
-            let mut name = None;
-            let mut vers = None;
-
-            for str::each_split_char(in, '@') |s| {
-                if      name.is_none() { name = Some(s.to_owned()); }
-                else if vers.is_none() { vers = Some(s.to_owned()); }
-                else                   { break;               }
-            }
-
-            (name, vers)
-        }
-
         match cmd {
             ~"build" => {
                 if args.len() < 1 {
@@ -189,9 +164,9 @@ impl Ctx {
                 }
                 // The package id is presumed to be the first command-line
                 // argument
-                let pkgid = PkgId::new(args[0]);
-                for pkg_parent_workspaces(pkgid) |workspace| {
-                    self.build(workspace, pkgid);
+                let pkgid = PkgId::new(copy args[0]);
+                for pkg_parent_workspaces(&pkgid) |workspace| {
+                    self.build(workspace, &pkgid);
                 }
             }
             ~"clean" => {
@@ -200,16 +175,16 @@ impl Ctx {
                 }
                 // The package id is presumed to be the first command-line
                 // argument
-                let pkgid = PkgId::new(args[0]);
+                let pkgid = PkgId::new(copy args[0]);
                 let cwd = os::getcwd();
-                self.clean(&cwd, pkgid); // tjc: should use workspace, not cwd
+                self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
             }
             ~"do" => {
                 if args.len() < 2 {
                     return usage::do_cmd();
                 }
 
-                self.do_cmd(args[0], args[1]);
+                self.do_cmd(copy args[0], copy args[1]);
             }
             ~"info" => {
                 self.info();
@@ -222,8 +197,8 @@ impl Ctx {
                 // The package id is presumed to be the first command-line
                 // argument
                 let pkgid = PkgId::new(args[0]);
-                for pkg_parent_workspaces(pkgid) |workspace| {
-                    self.install(workspace, pkgid);
+                for pkg_parent_workspaces(&pkgid) |workspace| {
+                    self.install(workspace, &pkgid);
                 }
             }
             ~"prefer" => {
@@ -231,9 +206,7 @@ impl Ctx {
                     return usage::uninstall();
                 }
 
-                let (name, vers) = sep_name_vers(args[0]);
-
-                self.prefer(name.get(), vers);
+                self.prefer(args[0], None);
             }
             ~"test" => {
                 self.test();
@@ -243,35 +216,31 @@ impl Ctx {
                     return usage::uninstall();
                 }
 
-                let (name, vers) = sep_name_vers(args[0]);
-
-                self.uninstall(name.get(), vers);
+                self.uninstall(args[0], None);
             }
             ~"unprefer" => {
                 if args.len() < 1 {
                     return usage::uninstall();
                 }
 
-                let (name, vers) = sep_name_vers(args[0]);
-
-                self.unprefer(name.get(), vers);
+                self.unprefer(args[0], None);
             }
-            _ => fail!(~"reached an unhandled command")
+            _ => fail!(fmt!("I don't know the command `%s`", cmd))
         }
     }
 
-    fn do_cmd(&self, _cmd: ~str, _pkgname: ~str)  {
+    fn do_cmd(&self, _cmd: &str, _pkgname: &str)  {
         // stub
-        fail!(~"`do` not yet implemented");
+        fail!("`do` not yet implemented");
     }
 
-    fn build(&self, workspace: &Path, pkgid: PkgId) {
+    fn build(&self, workspace: &Path, pkgid: &PkgId) {
         let src_dir   = pkgid_src_in_workspace(pkgid, workspace);
         let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
         debug!("Destination dir = %s", build_dir.to_str());
 
         // Create the package source
-        let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid);
+        let mut src = PkgSrc::new(workspace, &build_dir, pkgid);
         debug!("Package src = %?", src);
 
         // Is there custom build logic? If so, use it
@@ -289,7 +258,7 @@ impl Ctx {
                 let (cfgs, hook_result) = pscript.run_custom(~"post_build");
                 debug!("Command return code = %?", hook_result);
                 if hook_result != 0 {
-                    fail!(fmt!("Error running custom build command"))
+                    fail!("Error running custom build command")
                 }
                 custom = true;
                 // otherwise, the package script succeeded
@@ -309,10 +278,9 @@ impl Ctx {
             // Build it!
             src.build(&build_dir, cfgs, self.sysroot_opt);
         }
-
     }
 
-    fn clean(&self, workspace: &Path, id: PkgId)  {
+    fn clean(&self, workspace: &Path, id: &PkgId)  {
         // Could also support a custom build hook in the pkg
         // script for cleaning files rustpkg doesn't know about.
         // Do something reasonable for now
@@ -321,7 +289,7 @@ impl Ctx {
         util::note(fmt!("Cleaning package %s (removing directory %s)",
                         id.to_str(), dir.to_str()));
         if os::path_exists(&dir) {
-            util::remove_dir_r(&dir);
+            os::remove_dir_recursive(&dir);
             util::note(fmt!("Removed directory %s", dir.to_str()));
         }
 
@@ -330,15 +298,17 @@ impl Ctx {
 
     fn info(&self) {
         // stub
-        fail!(~"info not yet implemented");
+        fail!("info not yet implemented");
     }
 
-    fn install(&self, workspace: &Path, id: PkgId)  {
+    fn install(&self, workspace: &Path, id: &PkgId)  {
         use conditions::copy_failed::cond;
 
         // Should use RUST_PATH in the future.
         // Also should use workcache to not build if not necessary.
         self.build(workspace, id);
+        debug!("install: workspace = %s, id = %s", workspace.to_str(),
+               id.to_str());
 
         // Now copy stuff into the install dirs
         let maybe_executable = built_executable_in_workspace(id, workspace);
@@ -346,120 +316,46 @@ impl Ctx {
         let target_exec = target_executable_in_workspace(id, workspace);
         let target_lib = target_library_in_workspace(id, workspace);
 
+        debug!("target_exec = %s target_lib = %s \
+                maybe_executable = %? maybe_library = %?",
+               target_exec.to_str(), target_lib.to_str(),
+               maybe_executable, maybe_library);
+
         for maybe_executable.each |exec| {
             debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str());
-            if !os::copy_file(exec, &target_exec) {
-                cond.raise((*exec, target_exec));
+            if !(os::mkdir_recursive(&target_exec.dir_path(), u_rwx) &&
+                 os::copy_file(exec, &target_exec)) {
+                cond.raise((copy *exec, copy target_exec));
             }
         }
         for maybe_library.each |lib| {
             debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str());
-            if !os::copy_file(lib, &target_lib) {
-                cond.raise((*lib, target_lib));
-            }
-        }
-    }
-
-    fn fetch(&self, _dir: &Path, _url: ~str, _target: Option<~str>)  {
-        // stub
-        fail!(~"fetch not yet implemented");
-    }
-
-    fn fetch_curl(&self, dir: &Path, url: ~str)  {
-        util::note(fmt!("fetching from %s using curl", url));
-
-        let tar = dir.dir_path().push(&dir.file_path().to_str() + ~".tar");
-
-        if run::program_output(~"curl", ~[~"-f", ~"-s",
-                                          ~"-o", tar.to_str(),
-                                          url]).status != 0 {
-            util::error(~"fetching failed: downloading using curl failed");
-
-            fail!();
-        }
-
-        if run::program_output(~"tar", ~[~"-x", ~"--strip-components=1",
-                                         ~"-C", dir.to_str(), ~"-f",
-                                         tar.to_str()]).status != 0 {
-            util::error(~"fetching failed: extracting using tar failed" +
-                        ~"(is it a valid tar archive?)");
-
-           fail!();
-        }
-    }
-
-    fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>)  {
-        util::note(fmt!("fetching from %s using git", url));
-
-        // Git can't clone into a non-empty directory
-        util::remove_dir_r(dir);
-
-        if run::program_output(~"git", ~[~"clone", url,
-                                         dir.to_str()]).status != 0 {
-            util::error(~"fetching failed: can't clone repository");
-            fail!();
-        }
-
-        if !target.is_none() {
-            let mut success = true;
-
-            do util::temp_change_dir(dir) {
-                success = run::program_output(~"git",
-                                              ~[~"checkout",
-                                                target.get()]).status != 0
-            }
-
-            if !success {
-                util::error(~"fetching failed: can't checkout target");
-                fail!();
+            if !(os::mkdir_recursive(&target_lib.dir_path(), u_rwx) &&
+                 os::copy_file(lib, &target_lib)) {
+                cond.raise((copy *lib, copy target_lib));
             }
         }
     }
 
-    fn prefer(&self, id: ~str, vers: Option<~str>)  {
-        let package = match util::get_pkg(id, vers) {
-            result::Ok(package) => package,
-            result::Err(err) => {
-                util::error(err);
-                fail!(); // Condition?
-            }
-        };
-        let name = package.id.path.to_str(); // ???
-
-        util::note(fmt!("preferring %s v%s", name, package.id.version.to_str()));
-
-        let bin_dir = util::root().push(~"bin");
-
-        for package.bins.each |&bin| {
-            let path = Path(bin);
-            let mut name = None;
-            for str::each_split_char(path.file_path().to_str(), '-') |s| {
-                name = Some(s.to_owned());
-                break;
-            }
-            let out = bin_dir.push(name.unwrap());
-
-            util::link_exe(&path, &out);
-            util::note(fmt!("linked %s", out.to_str()));
-        }
-
-        util::note(fmt!("preferred %s v%s", name, package.id.version.to_str()));
+    fn prefer(&self, _id: &str, _vers: Option<~str>)  {
+        fail!(~"prefer not yet implemented");
     }
 
     fn test(&self)  {
         // stub
-        fail!(~"test not yet implemented");
+        fail!("test not yet implemented");
     }
 
-    fn uninstall(&self, _id: ~str, _vers: Option<~str>)  {
-        fail!(~"uninstall not yet implemented");
+    fn uninstall(&self, _id: &str, _vers: Option<~str>)  {
+        fail!("uninstall not yet implemented");
     }
 
-    fn unprefer(&self, _id: ~str, _vers: Option<~str>)  {
-        fail!(~"unprefer not yet implemented");
+    fn unprefer(&self, _id: &str, _vers: Option<~str>)  {
+        fail!("unprefer not yet implemented");
     }
 }
 
+
 pub fn main() {
     io::println("WARNING: The Rust package manager is experimental and may be unstable");
 
@@ -520,32 +416,6 @@ pub struct Crate {
     cfgs: ~[~str]
 }
 
-pub struct Listener {
-    cmds: ~[~str],
-    cb: ~fn()
-}
-
-pub fn run(listeners: ~[Listener]) {
-    let rcmd = os::args()[2];
-    let mut found = false;
-
-    for listeners.each |listener| {
-        for listener.cmds.each |&cmd| {
-            if cmd == rcmd {
-                (listener.cb)();
-
-                found = true;
-
-                break;
-            }
-        }
-    }
-
-    if !found {
-        os::set_exit_status(42);
-    }
-}
-
 pub impl Crate {
 
     fn new(p: &Path) -> Crate {
@@ -604,10 +474,6 @@ pub fn src_dir() -> Path {
     os::getcwd()
 }
 
-condition! {
-    bad_pkg_id: (super::Path, ~str) -> ::util::PkgId;
-}
-
 // An enumeration of the unpacked source of a package workspace.
 // This contains a list of files found in the source workspace.
 pub struct PkgSrc {
@@ -643,27 +509,51 @@ impl PkgSrc {
     fn check_dir(&self) -> Path {
         use conditions::nonexistent_package::cond;
 
-        debug!("Pushing onto root: %s | %s", self.id.path.to_str(),
+        debug!("Pushing onto root: %s | %s", self.id.to_str(),
                self.root.to_str());
 
-        let dir = self.root.push_rel(&self.id.path).normalize();
+        let mut dir = self.root.push("src");
+        dir = dir.push(self.id.to_str()); // ?? Should this use the version number?
 
         debug!("Checking dir: %s", dir.to_str());
 
-        // tjc: Rather than erroring out, need to try downloading the
-        // contents of the path to a local directory (#5679)
         if !os::path_exists(&dir) {
-            cond.raise((self.id, ~"missing package dir"));
+            if !self.fetch_git() {
+                cond.raise((copy self.id, ~"supplied path for package dir does not \
+                    exist, and couldn't interpret it as a URL fragment"));
+            }
         }
 
         if !os::path_is_dir(&dir) {
-            cond.raise((self.id, ~"supplied path for package dir is a \
-                                   non-directory"));
+            cond.raise((copy self.id, ~"supplied path for package dir is a \
+                                        non-directory"));
         }
 
         dir
     }
 
+    /// Try interpreting self's package id as a remote package, and try
+    /// fetching it and caching it in a local directory. If that didn't
+    /// work, return false.
+    /// (right now we only support git)
+    fn fetch_git(&self) -> bool {
+
+        let mut local = self.root.push("src");
+        local = local.push(self.id.to_str());
+        // Git can't clone into a non-empty directory
+        os::remove_dir_recursive(&local);
+
+        let url = fmt!("https://%s", self.id.remote_path.to_str());
+        util::note(fmt!("git clone %s %s", url, local.to_str()));
+
+        if run::program_output(~"git", ~[~"clone", copy url, local.to_str()]).status != 0 {
+            util::note(fmt!("fetching %s failed: can't clone repository", url));
+            return false;
+        }
+        true
+    }
+
+
     // If a file named "pkg.rs" in the current directory exists,
     // return the path for it. Otherwise, None
     fn package_script_option(&self, cwd: &Path) -> Option<Path> {
@@ -682,7 +572,7 @@ impl PkgSrc {
     /// Requires that dashes in p have already been normalized to
     /// underscores
     fn stem_matches(&self, p: &Path) -> bool {
-        let self_id = normalize(~self.id.path).filestem();
+        let self_id = self.id.local_path.filestem();
         if self_id == p.filestem() {
             return true;
         }
@@ -717,7 +607,7 @@ impl PkgSrc {
 
         let dir = self.check_dir();
         let prefix = dir.components.len();
-        debug!("Matching against %?", self.id.path.filestem());
+        debug!("Matching against %?", self.id.local_path.filestem());
         for os::walk_dir(&dir) |pth| {
             match pth.filename() {
                 Some(~"lib.rs") => push_crate(&mut self.libs,
@@ -738,7 +628,7 @@ impl PkgSrc {
             util::note(~"Couldn't infer any crates to build.\n\
                          Try naming a crate `main.rs`, `lib.rs`, \
                          `test.rs`, or `bench.rs`.");
-            cond.raise(self.id);
+            cond.raise(copy self.id);
         }
 
         debug!("found %u libs, %u mains, %u tests, %u benchs",
@@ -753,19 +643,18 @@ impl PkgSrc {
                     dst_dir: &Path,
                     src_dir: &Path,
                     crates: &[Crate],
-                    cfgs: ~[~str],
-                    test: bool, crate_type: crate_type) {
-
+                    cfgs: &[~str],
+                    what: OutputType) {
         for crates.each |&crate| {
             let path = &src_dir.push_rel(&crate.file).normalize();
             util::note(fmt!("build_crates: compiling %s", path.to_str()));
             util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));
 
-            let result = util::compile_crate(maybe_sysroot, self.id, path,
+            let result = util::compile_crate(maybe_sysroot, &self.id, path,
                                      dst_dir,
                                      crate.flags,
                                      crate.cfgs + cfgs,
-                                     false, test, crate_type);
+                                     false, what);
             if !result {
                 build_err::cond.raise(fmt!("build failure on %s",
                                            path.to_str()));
@@ -778,12 +667,13 @@ impl PkgSrc {
     fn build(&self, dst_dir: &Path, cfgs: ~[~str], maybe_sysroot: Option<@Path>) {
         let dir = self.check_dir();
         debug!("Building libs");
-        self.build_crates(maybe_sysroot, dst_dir, &dir, self.libs, cfgs, false, lib_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.libs, cfgs, Lib);
         debug!("Building mains");
-        self.build_crates(maybe_sysroot, dst_dir, &dir, self.mains, cfgs, false, bin_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.mains, cfgs, Main);
         debug!("Building tests");
-        self.build_crates(maybe_sysroot, dst_dir, &dir, self.tests, cfgs, true, bin_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.tests, cfgs, Test);
         debug!("Building benches");
-        self.build_crates(maybe_sysroot, dst_dir, &dir, self.benchs, cfgs, true, bin_crate);
+        self.build_crates(maybe_sysroot, dst_dir, &dir, self.benchs, cfgs, Bench);
     }
 }
+
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index 486e2959e9e..8eba3f06de3 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -17,8 +17,8 @@ use std::tempfile::mkdtemp;
 use util::{PkgId, default_version};
 use path_util::{target_executable_in_workspace, target_library_in_workspace,
                target_test_in_workspace, target_bench_in_workspace,
-               make_dir_rwx, u_rwx};
-use core::os::mkdir_recursive;
+               make_dir_rwx, u_rwx, RemotePath, LocalPath, normalize,
+               built_bench_in_workspace, built_test_in_workspace};
 
 fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
     Ctx {
@@ -29,15 +29,22 @@ fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
 }
 
 fn fake_pkg() -> PkgId {
+    let sn = ~"bogus";
+    let remote = RemotePath(Path(sn));
     PkgId {
-        path: Path(~"bogus"),
+        local_path: normalize(copy remote),
+        remote_path: remote,
+        short_name: sn,
         version: default_version()
     }
 }
 
 fn remote_pkg() -> PkgId {
+    let remote = RemotePath(Path(~"github.com/catamorphism/test-pkg"));
     PkgId {
-        path: Path(~"github.com/catamorphism/test-pkg"),
+        local_path: normalize(copy remote),
+        remote_path: remote,
+        short_name: ~"test_pkg",
         version: default_version()
     }
 }
@@ -49,10 +56,11 @@ fn writeFile(file_path: &Path, contents: ~str) {
     out.write_line(contents);
 }
 
-fn mk_temp_workspace(short_name: &Path) -> Path {
+fn mk_temp_workspace(short_name: &LocalPath) -> Path {
     let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
-    let package_dir = workspace.push(~"src").push_rel(short_name);
-    assert!(mkdir_recursive(&package_dir, u_rwx));
+    // include version number in directory name
+    let package_dir = workspace.push(~"src").push(fmt!("%s-0.1", short_name.to_str()));
+    assert!(os::mkdir_recursive(&package_dir, u_rwx));
     // Create main, lib, test, and bench files
     writeFile(&package_dir.push(~"main.rs"),
               ~"fn main() { let _x = (); }");
@@ -77,16 +85,17 @@ fn is_rwx(p: &Path) -> bool {
     }
 }
 
-#[cfg(test)]
 fn test_sysroot() -> Path {
     // Totally gross hack but it's just for test cases.
-    // Infer the sysroot from the exe name and tack "stage2"
-    // onto it. (Did I mention it was a gross hack?)
+    // Infer the sysroot from the exe name and pray that it's right.
+    // (Did I mention it was a gross hack?)
     let self_path = os::self_exe_path().expect("Couldn't get self_exe path");
-    self_path.pop().push("stage2")
+    self_path.pop()
 }
 
+// Ignored on i686 -- see #6517
 #[test]
+#[ignore(cfg(target_arch = "x86"))]
 fn test_make_dir_rwx() {
     let temp = &os::tmpdir();
     let dir = temp.push(~"quux");
@@ -100,31 +109,33 @@ fn test_make_dir_rwx() {
 }
 
 #[test]
+#[ignore(cfg(target_arch = "x86"))]
 fn test_install_valid() {
     let sysroot = test_sysroot();
     debug!("sysroot = %s", sysroot.to_str());
     let ctxt = fake_ctxt(Some(@sysroot));
     let temp_pkg_id = fake_pkg();
-    let temp_workspace = mk_temp_workspace(&temp_pkg_id.path);
+    let temp_workspace = mk_temp_workspace(&temp_pkg_id.local_path);
     // should have test, bench, lib, and main
-    ctxt.install(&temp_workspace, temp_pkg_id);
+    ctxt.install(&temp_workspace, &temp_pkg_id);
     // Check that all files exist
-    let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace);
+    let exec = target_executable_in_workspace(&temp_pkg_id, &temp_workspace);
     debug!("exec = %s", exec.to_str());
     assert!(os::path_exists(&exec));
     assert!(is_rwx(&exec));
-    let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace);
+    let lib = target_library_in_workspace(&temp_pkg_id, &temp_workspace);
     debug!("lib = %s", lib.to_str());
     assert!(os::path_exists(&lib));
     assert!(is_rwx(&lib));
     // And that the test and bench executables aren't installed
-    assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace)));
-    let bench = target_bench_in_workspace(temp_pkg_id, &temp_workspace);
+    assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, &temp_workspace)));
+    let bench = target_bench_in_workspace(&temp_pkg_id, &temp_workspace);
     debug!("bench = %s", bench.to_str());
     assert!(!os::path_exists(&bench));
 }
 
 #[test]
+#[ignore(cfg(target_arch = "x86"))]
 fn test_install_invalid() {
     use conditions::nonexistent_package::cond;
     use cond1 = conditions::missing_pkg_files::cond;
@@ -140,34 +151,87 @@ fn test_install_invalid() {
         do cond.trap(|_| {
             error_occurred = true;
         }).in {
-            ctxt.install(&temp_workspace, pkgid);
+            ctxt.install(&temp_workspace, &pkgid);
         }
     }
     assert!(error_occurred && error1_occurred);
 }
 
 #[test]
-#[ignore(reason = "install from URL-fragment not yet implemented")]
+#[ignore(cfg(target_arch = "x86"))]
 fn test_install_url() {
+    let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir");
     let sysroot = test_sysroot();
     debug!("sysroot = %s", sysroot.to_str());
     let ctxt = fake_ctxt(Some(@sysroot));
     let temp_pkg_id = remote_pkg();
-    let temp_workspace = mk_temp_workspace(&temp_pkg_id.path);
     // should have test, bench, lib, and main
-    ctxt.install(&temp_workspace, temp_pkg_id);
+    ctxt.install(&workspace, &temp_pkg_id);
     // Check that all files exist
-    let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace);
+    let exec = target_executable_in_workspace(&temp_pkg_id, &workspace);
     debug!("exec = %s", exec.to_str());
     assert!(os::path_exists(&exec));
     assert!(is_rwx(&exec));
-    let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace);
+    let lib = target_library_in_workspace(&temp_pkg_id, &workspace);
     debug!("lib = %s", lib.to_str());
     assert!(os::path_exists(&lib));
     assert!(is_rwx(&lib));
+    let built_test = built_test_in_workspace(&temp_pkg_id, &workspace).expect(~"test_install_url");
+    assert!(os::path_exists(&built_test));
+    let built_bench = built_bench_in_workspace(&temp_pkg_id,
+                                               &workspace).expect(~"test_install_url");
+    assert!(os::path_exists(&built_bench));
     // And that the test and bench executables aren't installed
-    assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace)));
-    let bench = target_bench_in_workspace(temp_pkg_id, &temp_workspace);
+    let test = target_test_in_workspace(&temp_pkg_id, &workspace);
+    assert!(!os::path_exists(&test));
+    debug!("test = %s", test.to_str());
+    let bench = target_bench_in_workspace(&temp_pkg_id, &workspace);
     debug!("bench = %s", bench.to_str());
     assert!(!os::path_exists(&bench));
-}
\ No newline at end of file
+}
+
+#[test]
+fn test_package_ids_must_be_relative_path_like() {
+    use conditions::bad_pkg_id::cond;
+
+    /*
+    Okay:
+    - One identifier, with no slashes
+    - Several slash-delimited things, with no / at the root
+
+    Not okay:
+    - Empty string
+    - Absolute path (as per os::is_absolute)
+
+    */
+
+    let default_version_str = "0.1";
+    let addversion = |s| {
+        fmt!("%s-%s", s, default_version_str)
+    };
+
+    let whatever = PkgId::new("foo");
+
+    assert!(addversion("foo") == whatever.to_str());
+    assert!(addversion("github.com/mozilla/rust") ==
+            PkgId::new("github.com/mozilla/rust").to_str());
+
+    do cond.trap(|(p, e)| {
+        assert!("" == p.to_str());
+        assert!("0-length pkgid" == e);
+        copy whatever
+    }).in {
+        let x = PkgId::new("");
+        assert!(addversion("foo") == x.to_str());
+    }
+
+    do cond.trap(|(p, e)| {
+        assert!(p.to_str() == os::make_absolute(&Path("foo/bar/quux")).to_str());
+        assert!("absolute pkgid" == e);
+        copy whatever
+    }).in {
+        let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str());
+        assert!(addversion("foo") == z.to_str());
+    }
+
+}
diff --git a/src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/src/main.rs b/src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/main.rs
index 62785c06db3..62785c06db3 100644
--- a/src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/src/main.rs
+++ b/src/librustpkg/testsuite/pass/src/deeply/nested/path/foo/main.rs
diff --git a/src/librustpkg/testsuite/pass/src/external-crate/src/main.rs b/src/librustpkg/testsuite/pass/src/external-crate/main.rs
index d094bcd6bba..d094bcd6bba 100644
--- a/src/librustpkg/testsuite/pass/src/external-crate/src/main.rs
+++ b/src/librustpkg/testsuite/pass/src/external-crate/main.rs
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 5e43cb43960..4a9c276948a 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -13,20 +13,23 @@ use core::cmp::Ord;
 use core::hash::Streaming;
 use core::rt::io::Writer;
 use rustc::driver::{driver, session};
-use rustc::driver::session::{lib_crate, unknown_crate};
 use rustc::metadata::filesearch;
 use std::getopts::groups::getopts;
 use std::semver;
-use std::{json, term, getopts};
+use std::{term, getopts};
 use syntax::ast_util::*;
 use syntax::codemap::{dummy_sp, spanned, dummy_spanned};
 use syntax::ext::base::{mk_ctxt, ext_ctxt};
-use syntax::ext::build;
 use syntax::{ast, attr, codemap, diagnostic, fold};
-use syntax::ast::{meta_name_value, meta_list, attribute, crate_};
+use syntax::ast::{meta_name_value, meta_list};
 use syntax::attr::{mk_attr};
 use rustc::back::link::output_type_exe;
-use rustc::driver::session::{lib_crate, unknown_crate, crate_type};
+use rustc::driver::session::{lib_crate, bin_crate};
+
+static Commands: &'static [&'static str] =
+    &["build", "clean", "do", "info", "install", "prefer", "test", "uninstall",
+      "unprefer"];
+
 
 pub type ExitCode = int; // For now
 
@@ -41,28 +44,28 @@ impl Ord for Version {
     fn lt(&self, other: &Version) -> bool {
         match (self, other) {
             (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2,
-            (&SemVersion(v1), &SemVersion(v2)) => v1 < v2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2,
             _ => false // incomparable, really
         }
     }
     fn le(&self, other: &Version) -> bool {
         match (self, other) {
             (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2,
-            (&SemVersion(v1), &SemVersion(v2)) => v1 <= v2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2,
             _ => false // incomparable, really
         }
     }
     fn ge(&self, other: &Version) -> bool {
         match (self, other) {
             (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2,
-            (&SemVersion(v1), &SemVersion(v2)) => v1 > v2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2,
             _ => false // incomparable, really
         }
     }
     fn gt(&self, other: &Version) -> bool {
         match (self, other) {
             (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2,
-            (&SemVersion(v1), &SemVersion(v2)) => v1 >= v2,
+            (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2,
             _ => false // incomparable, really
         }
     }
@@ -72,26 +75,40 @@ impl Ord for Version {
 impl ToStr for Version {
     fn to_str(&self) -> ~str {
         match *self {
-            ExactRevision(n) => n.to_str(),
-            SemVersion(v) => v.to_str()
+            ExactRevision(ref n) => n.to_str(),
+            SemVersion(ref v) => v.to_str()
         }
     }
 }
 
+#[deriving(Eq)]
+pub enum OutputType { Main, Lib, Bench, Test }
+
 /// Placeholder
 pub fn default_version() -> Version { ExactRevision(0.1) }
 
-// Path-fragment identifier of a package such as
-// 'github.com/graydon/test'; path must be a relative
-// path with >=1 component.
+/// Path-fragment identifier of a package such as
+/// 'github.com/graydon/test'; path must be a relative
+/// path with >=1 component.
 pub struct PkgId {
-    path: Path,
+    /// Remote path: for example, github.com/mozilla/quux-whatever
+    remote_path: RemotePath,
+    /// Local path: for example, /home/quux/github.com/mozilla/quux_whatever
+    /// Note that '-' normalizes to '_' when mapping a remote path
+    /// onto a local path
+    /// Also, this will change when we implement #6407, though we'll still
+    /// need to keep track of separate local and remote paths
+    local_path: LocalPath,
+    /// Short name. This is the local path's filestem, but we store it
+    /// redundantly so as to not call get() everywhere (filestem() returns an
+    /// option)
+    short_name: ~str,
     version: Version
 }
 
 pub impl PkgId {
     fn new(s: &str) -> PkgId {
-        use bad_pkg_id::cond;
+        use conditions::bad_pkg_id::cond;
 
         let p = Path(s);
         if p.is_absolute {
@@ -100,31 +117,32 @@ pub impl PkgId {
         if p.components.len() < 1 {
             return cond.raise((p, ~"0-length pkgid"));
         }
+        let remote_path = RemotePath(p);
+        let local_path = normalize(copy remote_path);
+        let short_name = (copy local_path).filestem().expect(fmt!("Strange path! %s", s));
         PkgId {
-            path: p,
+            local_path: local_path,
+            remote_path: remote_path,
+            short_name: short_name,
             version: default_version()
         }
     }
 
     fn hash(&self) -> ~str {
-        fmt!("%s-%s-%s", self.path.to_str(),
-             hash(self.path.to_str() + self.version.to_str()),
+        fmt!("%s-%s-%s", self.remote_path.to_str(),
+             hash(self.remote_path.to_str() + self.version.to_str()),
              self.version.to_str())
     }
 
+    fn short_name_with_version(&self) -> ~str {
+        fmt!("%s-%s", self.short_name, self.version.to_str())
+    }
 }
 
 impl ToStr for PkgId {
     fn to_str(&self) -> ~str {
         // should probably use the filestem and not the whole path
-        fmt!("%s-%s", self.path.to_str(),
-             // Replace dots with -s in the version
-             // this is because otherwise rustc will think
-             // that foo-0.1 has .1 as its extension
-             // (Temporary hack until I figure out how to
-             // get rustc to not name the object file
-             // foo-0.o if I pass in foo-0.1 to build_output_filenames)
-             str::replace(self.version.to_str(), ".", "-"))
+        fmt!("%s-%s", self.local_path.to_str(), self.version.to_str())
     }
 }
 
@@ -147,31 +165,8 @@ pub fn root() -> Path {
     }
 }
 
-pub fn is_cmd(cmd: ~str) -> bool {
-    let cmds = &[~"build", ~"clean", ~"do", ~"info", ~"install", ~"prefer",
-                 ~"test", ~"uninstall", ~"unprefer"];
-
-    vec::contains(cmds, &cmd)
-}
-
-pub fn parse_name(id: ~str) -> result::Result<~str, ~str> {
-    let mut last_part = None;
-
-    for str::each_split_char(id, '.') |part| {
-        for str::each_char(part) |char| {
-            if char::is_whitespace(char) {
-                return result::Err(
-                    ~"could not parse id: contains whitespace");
-            } else if char::is_uppercase(char) {
-                return result::Err(
-                    ~"could not parse id: should be all lowercase");
-            }
-        }
-        last_part = Some(part.to_owned());
-    }
-    if last_part.is_none() { return result::Err(~"could not parse id: is empty"); }
-
-    result::Ok(last_part.unwrap())
+pub fn is_cmd(cmd: &str) -> bool {
+    Commands.any(|&c| c == cmd)
 }
 
 struct ListenerFn {
@@ -220,7 +215,7 @@ fn fold_item(ctx: @mut ReadyCtx,
 
         for attrs.each |attr| {
             match attr.node.value.node {
-                ast::meta_list(_, mis) => {
+                ast::meta_list(_, ref mis) => {
                     for mis.each |mi| {
                         match mi.node {
                             ast::meta_word(cmd) => cmds.push(copy *cmd),
@@ -246,53 +241,6 @@ fn fold_item(ctx: @mut ReadyCtx,
     res
 }
 
-fn add_pkg_module(ctx: @mut ReadyCtx, m: ast::_mod) -> ast::_mod {
-    let listeners = mk_listener_vec(ctx);
-    let ext_cx = ctx.ext_cx;
-    let item = quote_item! (
-        mod __pkg {
-            extern mod rustpkg (vers="0.7-pre");
-            static listeners : &[rustpkg::Listener] = $listeners;
-            #[main]
-            fn main() {
-                rustpkg::run(listeners);
-            }
-        }
-    );
-    ast::_mod {
-        items: vec::append_one(/*bad*/copy m.items, item.get()),
-        .. m
-    }
-}
-
-fn mk_listener_vec(ctx: @mut ReadyCtx) -> @ast::expr {
-    let fns = ctx.fns;
-    let descs = do fns.map |listener| {
-        mk_listener_rec(ctx, *listener)
-    };
-    let ext_cx = ctx.ext_cx;
-    build::mk_slice_vec_e(ext_cx, dummy_sp(), descs)
-}
-
-fn mk_listener_rec(ctx: @mut ReadyCtx, listener: ListenerFn) -> @ast::expr {
-    let span = listener.span;
-    let cmds = do listener.cmds.map |&cmd| {
-        let ext_cx = ctx.ext_cx;
-        build::mk_base_str(ext_cx, span, cmd)
-    };
-
-    let ext_cx = ctx.ext_cx;
-    let cmds_expr = build::mk_slice_vec_e(ext_cx, span, cmds);
-    let cb_expr = build::mk_path(ext_cx, span, copy listener.path);
-
-    quote_expr!(
-        Listener {
-            cmds: $cmds_expr,
-            cb: $cb_expr
-        }
-    )
-}
-
 /// Generate/filter main function, add the list of commands, etc.
 pub fn ready_crate(sess: session::Session,
                    crate: @ast::crate) -> @ast::crate {
@@ -324,7 +272,7 @@ pub fn parse_vers(vers: ~str) -> result::Result<semver::Version, ~str> {
 
 pub fn need_dir(s: &Path) {
     if !os::path_is_dir(s) && !os::make_dir(s, 493_i32) {
-        fail!(fmt!("can't create dir: %s", s.to_str()));
+        fail!("can't create dir: %s", s.to_str());
     }
 }
 
@@ -374,100 +322,32 @@ pub fn hash(data: ~str) -> ~str {
     hasher.result_str()
 }
 
-pub fn temp_change_dir<T>(dir: &Path, cb: &fn() -> T) {
-    let cwd = os::getcwd();
-
-    os::change_dir(dir);
-    cb();
-    os::change_dir(&cwd);
-}
-
-pub fn touch(path: &Path) {
-    match io::mk_file_writer(path, ~[io::Create]) {
-        result::Ok(writer) => writer.write_line(~""),
-        _ => {}
-    }
-}
-
-pub fn remove_dir_r(path: &Path) {
-    for os::walk_dir(path) |&file| {
-        let mut cdir = file;
-
-        loop {
-            if os::path_is_dir(&cdir) {
-                os::remove_dir(&cdir);
-            } else {
-                os::remove_file(&cdir);
-            }
-
-            cdir = cdir.dir_path();
-
-            if cdir == *path { break; }
-        }
-    }
-
-    os::remove_dir(path);
-}
-
-pub fn wait_for_lock(path: &Path) {
-    if os::path_exists(path) {
-        warn(fmt!("the database appears locked, please wait (or rm %s)",
-                        path.to_str()));
-
-        loop {
-            if !os::path_exists(path) { break; }
-        }
-    }
-}
-
-pub fn load_pkgs() -> result::Result<~[json::Json], ~str> {
-    fail!(~"load_pkg not implemented");
-}
-
-pub fn get_pkg(_id: ~str,
-               _vers: Option<~str>) -> result::Result<Pkg, ~str> {
-    fail!(~"get_pkg not implemented");
-}
-
-pub fn add_pkg(pkg: &Pkg) -> bool {
-    note(fmt!("Would be adding package, but add_pkg is not yet implemented %s",
-         pkg.to_str()));
-    false
-}
-
 // FIXME (#4432): Use workcache to only compile when needed
 pub fn compile_input(sysroot: Option<@Path>,
-                     pkg_id: PkgId,
+                     pkg_id: &PkgId,
                      in_file: &Path,
                      out_dir: &Path,
-                     flags: ~[~str],
-                     cfgs: ~[~str],
+                     flags: &[~str],
+                     cfgs: &[~str],
                      opt: bool,
-                     test: bool,
-                     crate_type: session::crate_type) -> bool {
-
-    // Want just the directory component here
-    let pkg_filename = pkg_id.path.filename().expect(~"Weird pkg id");
-    let short_name = fmt!("%s-%s", pkg_filename, pkg_id.version.to_str());
+                     what: OutputType) -> bool {
 
     assert!(in_file.components.len() > 1);
     let input = driver::file_input(copy *in_file);
-    debug!("compile_input: %s / %?", in_file.to_str(), crate_type);
+    debug!("compile_input: %s / %?", in_file.to_str(), what);
     // tjc: by default, use the package ID name as the link name
     // not sure if we should support anything else
 
-    let binary = os::args()[0];
-    let building_library = match crate_type {
-        lib_crate | unknown_crate => true,
-        _ => false
-    };
+    let binary = @(copy os::args()[0]);
+    let building_library = what == Lib;
 
     let out_file = if building_library {
-        out_dir.push(os::dll_filename(short_name))
+        out_dir.push(os::dll_filename(pkg_id.short_name))
     }
     else {
-        out_dir.push(short_name + if test { ~"test" } else { ~"" }
-                     + os::EXE_SUFFIX)
+        out_dir.push(pkg_id.short_name + match what {
+            Test => ~"test", Bench => ~"bench", Main | Lib => ~""
+        } + os::EXE_SUFFIX)
     };
 
     debug!("compiling %s into %s",
@@ -477,40 +357,41 @@ pub fn compile_input(sysroot: Option<@Path>,
     debug!("cfgs: %s", str::connect(cfgs, ~" "));
     debug!("compile_input's sysroot = %?", sysroot);
 
+    let crate_type = match what {
+        Lib => lib_crate,
+        Test | Bench | Main => bin_crate
+    };
     let matches = getopts(~[~"-Z", ~"time-passes"]
-                          + if building_library { ~[~"--lib"] }
-                            else if test { ~[~"--test"] }
-                            // bench?
-                            else { ~[] }
+                          + match what {
+                              Lib => ~[~"--lib"],
+                              // --test compiles both #[test] and #[bench] fns
+                              Test | Bench => ~[~"--test"],
+                              Main => ~[]
+                          }
                           + flags
                           + cfgs.flat_map(|&c| { ~[~"--cfg", c] }),
                           driver::optgroups()).get();
-    let options = @session::options {
+    let mut options = session::options {
         crate_type: crate_type,
         optimize: if opt { session::Aggressive } else { session::No },
-        test: test,
+        test: what == Test || what == Bench,
         maybe_sysroot: sysroot,
         addl_lib_search_paths: ~[copy *out_dir],
-        .. *driver::build_session_options(@binary, &matches, diagnostic::emit)
+        // output_type should be conditional
+        output_type: output_type_exe, // Use this to get a library? That's weird
+        .. copy *driver::build_session_options(binary, &matches, diagnostic::emit)
     };
-    let mut crate_cfg = options.cfg;
 
     for cfgs.each |&cfg| {
-        crate_cfg.push(attr::mk_word_item(@cfg));
+        options.cfg.push(attr::mk_word_item(@cfg));
     }
 
-    let options = @session::options {
-        cfg: vec::append(options.cfg, crate_cfg),
-        // output_type should be conditional
-        output_type: output_type_exe, // Use this to get a library? That's weird
-        .. *options
-    };
-    let sess = driver::build_session(options, diagnostic::emit);
+    let sess = driver::build_session(@options, diagnostic::emit);
 
     debug!("calling compile_crate_from_input, out_dir = %s,
            building_library = %?", out_dir.to_str(), sess.building_library);
-    let _ = compile_crate_from_input(input, pkg_id, Some(*out_dir), sess, None,
-                                     out_file, binary,
+    let _ = compile_crate_from_input(&input, pkg_id, Some(copy *out_dir), sess,
+                                     None, &out_file, binary,
                                      driver::cu_everything);
     true
 }
@@ -520,18 +401,19 @@ pub fn compile_input(sysroot: Option<@Path>,
 // If crate_opt is present, then finish compilation. If it's None, then
 // call compile_upto and return the crate
 // also, too many arguments
-pub fn compile_crate_from_input(input: driver::input,
-                                pkg_id: PkgId,
+pub fn compile_crate_from_input(input: &driver::input,
+                                pkg_id: &PkgId,
                                 build_dir_opt: Option<Path>,
                                 sess: session::Session,
                                 crate_opt: Option<@ast::crate>,
-                                out_file: Path,
-                                binary: ~str,
+                                out_file: &Path,
+                                binary: @~str,
                                 what: driver::compile_upto) -> @ast::crate {
     debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str());
-    let outputs = driver::build_output_filenames(&input, &build_dir_opt, &Some(out_file), sess);
+    let outputs = driver::build_output_filenames(input, &build_dir_opt,
+                                                 &Some(copy *out_file), sess);
     debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
-    let cfg = driver::build_configuration(sess, @binary, &input);
+    let cfg = driver::build_configuration(sess, binary, input);
     match crate_opt {
         Some(c) => {
             debug!("Calling compile_rest, outputs = %?", outputs);
@@ -541,27 +423,29 @@ pub fn compile_crate_from_input(input: driver::input,
         }
         None => {
             debug!("Calling compile_upto, outputs = %?", outputs);
-            let (crate, _) = driver::compile_upto(sess, cfg, &input,
+            let (crate, _) = driver::compile_upto(sess, copy cfg, input,
                                                   driver::cu_parse, Some(outputs));
+            let mut crate = crate;
 
             debug!("About to inject link_meta info...");
             // Inject the inferred link_meta info if it's not already there
             // (assumes that name and vers are the only linkage metas)
-            let mut crate_to_use = crate;
 
             debug!("How many attrs? %?", attr::find_linkage_metas(crate.node.attrs).len());
 
             if attr::find_linkage_metas(crate.node.attrs).is_empty() {
-                crate_to_use = add_attrs(*crate, ~[mk_attr(@dummy_spanned(meta_list(@~"link",
-                                                  // change PkgId to have a <shortname> field?
-                    ~[@dummy_spanned(meta_name_value(@~"name",
-                                                    mk_string_lit(@pkg_id.path.filestem().get()))),
-                      @dummy_spanned(meta_name_value(@~"vers",
-                                                    mk_string_lit(@pkg_id.version.to_str())))])))]);
+                crate = @codemap::respan(crate.span, ast::crate_ {
+                    attrs: ~[mk_attr(@dummy_spanned(
+                        meta_list(@~"link",
+                                  ~[@dummy_spanned(meta_name_value(@~"name",
+                                        mk_string_lit(@(copy pkg_id.short_name)))),
+                                    @dummy_spanned(meta_name_value(@~"vers",
+                                        mk_string_lit(@(copy pkg_id.version.to_str()))))])))],
+                    ..copy crate.node});
             }
 
-            driver::compile_rest(sess, cfg, what, Some(outputs), Some(crate_to_use));
-            crate_to_use
+            driver::compile_rest(sess, cfg, what, Some(outputs), Some(crate));
+            crate
         }
     }
 }
@@ -575,34 +459,41 @@ pub fn exe_suffix() -> ~str { ~".exe" }
 #[cfg(target_os = "macos")]
 pub fn exe_suffix() -> ~str { ~"" }
 
-
-/// Returns a copy of crate `c` with attributes `attrs` added to its
-/// attributes
-fn add_attrs(c: ast::crate, new_attrs: ~[attribute]) -> @ast::crate {
-    @spanned {
-        node: crate_ {
-            attrs: c.node.attrs + new_attrs, ..c.node
-        },
-        span: c.span
-    }
-}
-
 // Called by build_crates
 // FIXME (#4432): Use workcache to only compile when needed
-pub fn compile_crate(sysroot: Option<@Path>, pkg_id: PkgId,
+pub fn compile_crate(sysroot: Option<@Path>, pkg_id: &PkgId,
                      crate: &Path, dir: &Path,
-                     flags: ~[~str], cfgs: ~[~str], opt: bool,
-                     test: bool, crate_type: crate_type) -> bool {
+                     flags: &[~str], cfgs: &[~str], opt: bool,
+                     what: OutputType) -> bool {
     debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str());
     debug!("compile_crate: short_name = %s, flags =...", pkg_id.to_str());
     for flags.each |&fl| {
         debug!("+++ %s", fl);
     }
-    compile_input(sysroot, pkg_id,
-                  crate, dir, flags, cfgs, opt, test, crate_type)
+    compile_input(sysroot, pkg_id, crate, dir, flags, cfgs, opt, what)
+}
+
+// normalize should be the only way to construct a LocalPath
+// (though this isn't enforced)
+/// Replace all occurrences of '-' in the stem part of path with '_'
+/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
+/// as the same name
+pub fn normalize(p_: RemotePath) -> LocalPath {
+    let RemotePath(p) = p_;
+    match p.filestem() {
+        None => LocalPath(p),
+        Some(st) => {
+            let replaced = str::replace(st, "-", "_");
+            if replaced != st {
+                LocalPath(p.with_filestem(replaced))
+            }
+            else {
+                LocalPath(p)
+            }
+        }
+    }
 }
 
-
 #[cfg(windows)]
 pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
     /* FIXME (#1768): Investigate how to do this on win32
@@ -634,9 +525,13 @@ pub fn mk_string_lit(s: @~str) -> ast::lit {
     }
 }
 
+/// Wrappers to prevent local and remote paths from getting confused
+pub struct RemotePath (Path);
+pub struct LocalPath (Path);
+
 #[cfg(test)]
 mod test {
-    use super::{is_cmd, parse_name};
+    use super::is_cmd;
 
     #[test]
     fn test_is_cmd() {
@@ -651,9 +546,4 @@ mod test {
         assert!(is_cmd(~"unprefer"));
     }
 
-    #[test]
-    fn test_parse_name() {
-        assert!(parse_name(~"org.mozilla.servo").get() == ~"servo");
-        assert!(parse_name(~"org. mozilla.servo 2131").is_err());
-    }
 }
diff --git a/src/librustpkg/workspace.rs b/src/librustpkg/workspace.rs
index 94b94d373e6..cb9f735bce8 100644
--- a/src/librustpkg/workspace.rs
+++ b/src/librustpkg/workspace.rs
@@ -14,17 +14,17 @@ use path_util::{rust_path, workspace_contains_package_id};
 use util::PkgId;
 use core::path::Path;
 
-pub fn pkg_parent_workspaces(pkgid: PkgId, action: &fn(&Path) -> bool) -> bool {
+pub fn pkg_parent_workspaces(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
     // Using the RUST_PATH, find workspaces that contain
     // this package ID
     let workspaces = rust_path().filtered(|ws|
         workspace_contains_package_id(pkgid, ws));
     if workspaces.is_empty() {
         // tjc: make this a condition
-        fail!(fmt!("Package %s not found in any of \
+        fail!("Package %s not found in any of \
                     the following workspaces: %s",
-                   pkgid.path.to_str(),
-                   rust_path().to_str()));
+                   pkgid.remote_path.to_str(),
+                   rust_path().to_str());
     }
     for workspaces.each |ws| {
         if action(ws) {
diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs
index 7af68f3321d..df49771258e 100644
--- a/src/libstd/arc.rs
+++ b/src/libstd/arc.rs
@@ -17,9 +17,7 @@ use sync;
 use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars};
 
 use core::cast;
-use core::unstable::{SharedMutableState, shared_mutable_state};
-use core::unstable::{clone_shared_mutable_state};
-use core::unstable::{get_shared_mutable_state, get_shared_immutable_state};
+use core::unstable::sync::UnsafeAtomicRcBox;
 use core::ptr;
 use core::task;
 
@@ -83,11 +81,11 @@ pub impl<'self> Condvar<'self> {
  ****************************************************************************/
 
 /// An atomically reference counted wrapper for shared immutable state.
-struct ARC<T> { x: SharedMutableState<T> }
+struct ARC<T> { x: UnsafeAtomicRcBox<T> }
 
 /// Create an atomically reference counted wrapper.
 pub fn ARC<T:Const + Owned>(data: T) -> ARC<T> {
-    ARC { x: unsafe { shared_mutable_state(data) } }
+    ARC { x: UnsafeAtomicRcBox::new(data) }
 }
 
 /**
@@ -95,7 +93,7 @@ pub fn ARC<T:Const + Owned>(data: T) -> ARC<T> {
  * wrapper.
  */
 pub fn get<'a, T:Const + Owned>(rc: &'a ARC<T>) -> &'a T {
-    unsafe { get_shared_immutable_state(&rc.x) }
+    unsafe { &*rc.x.get_immut() }
 }
 
 /**
@@ -106,7 +104,7 @@ pub fn get<'a, T:Const + Owned>(rc: &'a ARC<T>) -> &'a T {
  * allowing them to share the underlying data.
  */
 pub fn clone<T:Const + Owned>(rc: &ARC<T>) -> ARC<T> {
-    ARC { x: unsafe { clone_shared_mutable_state(&rc.x) } }
+    ARC { x: rc.x.clone() }
 }
 
 impl<T:Const + Owned> Clone for ARC<T> {
@@ -122,7 +120,7 @@ impl<T:Const + Owned> Clone for ARC<T> {
 #[doc(hidden)]
 struct MutexARCInner<T> { lock: Mutex, failed: bool, data: T }
 /// An ARC with mutable data protected by a blocking mutex.
-struct MutexARC<T> { x: SharedMutableState<MutexARCInner<T>> }
+struct MutexARC<T> { x: UnsafeAtomicRcBox<MutexARCInner<T>> }
 
 /// Create a mutex-protected ARC with the supplied data.
 pub fn MutexARC<T:Owned>(user_data: T) -> MutexARC<T> {
@@ -137,7 +135,7 @@ pub fn mutex_arc_with_condvars<T:Owned>(user_data: T,
     let data =
         MutexARCInner { lock: mutex_with_condvars(num_condvars),
                           failed: false, data: user_data };
-    MutexARC { x: unsafe { shared_mutable_state(data) } }
+    MutexARC { x: UnsafeAtomicRcBox::new(data) }
 }
 
 impl<T:Owned> Clone for MutexARC<T> {
@@ -145,7 +143,7 @@ impl<T:Owned> Clone for MutexARC<T> {
     fn clone(&self) -> MutexARC<T> {
         // NB: Cloning the underlying mutex is not necessary. Its reference
         // count would be exactly the same as the shared state's.
-        MutexARC { x: unsafe { clone_shared_mutable_state(&self.x) } }
+        MutexARC { x: self.x.clone() }
     }
 }
 
@@ -176,7 +174,7 @@ pub impl<T:Owned> MutexARC<T> {
      */
     #[inline(always)]
     unsafe fn access<U>(&self, blk: &fn(x: &mut T) -> U) -> U {
-        let state = get_shared_mutable_state(&self.x);
+        let state = self.x.get();
         // Borrowck would complain about this if the function were
         // not already unsafe. See borrow_rwlock, far below.
         do (&(*state).lock).lock {
@@ -192,7 +190,7 @@ pub impl<T:Owned> MutexARC<T> {
         &self,
         blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) -> U
     {
-        let state = get_shared_mutable_state(&self.x);
+        let state = self.x.get();
         do (&(*state).lock).lock_cond |cond| {
             check_poison(true, (*state).failed);
             let _z = PoisonOnFail(&mut (*state).failed);
@@ -210,9 +208,9 @@ pub impl<T:Owned> MutexARC<T> {
 fn check_poison(is_mutex: bool, failed: bool) {
     if failed {
         if is_mutex {
-            fail!(~"Poisoned MutexARC - another task failed inside!");
+            fail!("Poisoned MutexARC - another task failed inside!");
         } else {
-            fail!(~"Poisoned rw_arc - another task failed inside!");
+            fail!("Poisoned rw_arc - another task failed inside!");
         }
     }
 }
@@ -254,7 +252,7 @@ struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
  */
 #[mutable]
 struct RWARC<T> {
-    x: SharedMutableState<RWARCInner<T>>,
+    x: UnsafeAtomicRcBox<RWARCInner<T>>,
     cant_nest: ()
 }
 
@@ -273,13 +271,13 @@ pub fn rw_arc_with_condvars<T:Const + Owned>(
     let data =
         RWARCInner { lock: rwlock_with_condvars(num_condvars),
                      failed: false, data: user_data };
-    RWARC { x: unsafe { shared_mutable_state(data) }, cant_nest: () }
+    RWARC { x: UnsafeAtomicRcBox::new(data), cant_nest: () }
 }
 
 pub impl<T:Const + Owned> RWARC<T> {
     /// Duplicate a rwlock-protected ARC, as arc::clone.
     fn clone(&self) -> RWARC<T> {
-        RWARC { x: unsafe { clone_shared_mutable_state(&self.x) },
+        RWARC { x: self.x.clone(),
                 cant_nest: () }
     }
 
@@ -299,7 +297,7 @@ pub impl<T:Const + Owned> RWARC<T> {
     #[inline(always)]
     fn write<U>(&self, blk: &fn(x: &mut T) -> U) -> U {
         unsafe {
-            let state = get_shared_mutable_state(&self.x);
+            let state = self.x.get();
             do (*borrow_rwlock(state)).write {
                 check_poison(false, (*state).failed);
                 let _z = PoisonOnFail(&mut (*state).failed);
@@ -313,7 +311,7 @@ pub impl<T:Const + Owned> RWARC<T> {
                              blk: &fn(x: &'x mut T, c: &'c Condvar) -> U)
                           -> U {
         unsafe {
-            let state = get_shared_mutable_state(&self.x);
+            let state = self.x.get();
             do (*borrow_rwlock(state)).write_cond |cond| {
                 check_poison(false, (*state).failed);
                 let _z = PoisonOnFail(&mut (*state).failed);
@@ -334,10 +332,12 @@ pub impl<T:Const + Owned> RWARC<T> {
      * access modes, this will not poison the ARC.
      */
     fn read<U>(&self, blk: &fn(x: &T) -> U) -> U {
-        let state = unsafe { get_shared_immutable_state(&self.x) };
-        do (&state.lock).read {
-            check_poison(false, state.failed);
-            blk(&state.data)
+        let state = self.x.get();
+        unsafe {
+            do (*state).lock.read {
+                check_poison(false, (*state).failed);
+                blk(&(*state).data)
+            }
         }
     }
 
@@ -360,7 +360,7 @@ pub impl<T:Const + Owned> RWARC<T> {
      */
     fn write_downgrade<U>(&self, blk: &fn(v: RWWriteMode<T>) -> U) -> U {
         unsafe {
-            let state = get_shared_mutable_state(&self.x);
+            let state = self.x.get();
             do (*borrow_rwlock(state)).write_downgrade |write_mode| {
                 check_poison(false, (*state).failed);
                 blk(RWWriteMode {
@@ -374,25 +374,27 @@ pub impl<T:Const + Owned> RWARC<T> {
 
     /// To be called inside of the write_downgrade block.
     fn downgrade<'a>(&self, token: RWWriteMode<'a, T>) -> RWReadMode<'a, T> {
-        // The rwlock should assert that the token belongs to us for us.
-        let state = unsafe { get_shared_immutable_state(&self.x) };
-        let RWWriteMode {
-            data: data,
-            token: t,
-            poison: _poison
-        } = token;
-        // Let readers in
-        let new_token = (&state.lock).downgrade(t);
-        // Whatever region the input reference had, it will be safe to use
-        // the same region for the output reference. (The only 'unsafe' part
-        // of this cast is removing the mutability.)
-        let new_data = unsafe { cast::transmute_immut(data) };
-        // Downgrade ensured the token belonged to us. Just a sanity check.
-        assert!(ptr::ref_eq(&state.data, new_data));
-        // Produce new token
-        RWReadMode {
-            data: new_data,
-            token: new_token,
+        unsafe {
+            // The rwlock should assert that the token belongs to us for us.
+            let state = self.x.get();
+            let RWWriteMode {
+                data: data,
+                token: t,
+                poison: _poison
+            } = token;
+            // Let readers in
+            let new_token = (*state).lock.downgrade(t);
+            // Whatever region the input reference had, it will be safe to use
+            // the same region for the output reference. (The only 'unsafe' part
+            // of this cast is removing the mutability.)
+            let new_data = cast::transmute_immut(data);
+            // Downgrade ensured the token belonged to us. Just a sanity check.
+            assert!(ptr::ref_eq(&(*state).data, new_data));
+            // Produce new token
+            RWReadMode {
+                data: new_data,
+                token: new_token,
+            }
         }
     }
 }
diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs
index 85ba2707863..68242f88fae 100644
--- a/src/libstd/base64.rs
+++ b/src/libstd/base64.rs
@@ -82,7 +82,7 @@ impl<'self> ToBase64 for &'self [u8] {
             str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
             str::push_char(&mut s, '=');
           }
-          _ => fail!(~"Algebra is broken, please alert the math police")
+          _ => fail!("Algebra is broken, please alert the math police")
         }
         s
     }
@@ -136,7 +136,7 @@ impl FromBase64 for ~[u8] {
      * ~~~~
      */
     fn from_base64(&self) -> ~[u8] {
-        if self.len() % 4u != 0u { fail!(~"invalid base64 length"); }
+        if self.len() % 4u != 0u { fail!("invalid base64 length"); }
 
         let len = self.len();
         let mut padding = 0u;
@@ -173,10 +173,10 @@ impl FromBase64 for ~[u8] {
                                 r.push(((n >> 10u) & 0xFFu) as u8);
                                 return copy r;
                             }
-                            _ => fail!(~"invalid base64 padding")
+                            _ => fail!("invalid base64 padding")
                         }
                     }
-                    _ => fail!(~"invalid base64 character")
+                    _ => fail!("invalid base64 character")
                 }
 
                 i += 1u;
diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs
index 09f86f30d32..e31818ecc1c 100644
--- a/src/libstd/bitv.rs
+++ b/src/libstd/bitv.rs
@@ -236,7 +236,7 @@ pub struct Bitv {
 }
 
 fn die() -> ! {
-    fail!(~"Tried to do operation on bit vectors with different sizes");
+    fail!("Tried to do operation on bit vectors with different sizes");
 }
 
 priv impl Bitv {
@@ -1308,7 +1308,7 @@ mod tests {
         let mut b = Bitv::new(14, true);
         b.clear();
         for b.ones |i| {
-            fail!(fmt!("found 1 at %?", i));
+            fail!("found 1 at %?", i);
         }
     }
 
@@ -1317,7 +1317,7 @@ mod tests {
         let mut b = Bitv::new(140, true);
         b.clear();
         for b.ones |i| {
-            fail!(fmt!("found 1 at %?", i));
+            fail!("found 1 at %?", i);
         }
     }
 
diff --git a/src/libstd/dlist.rs b/src/libstd/dlist.rs
index 741bd629680..84bd803afe7 100644
--- a/src/libstd/dlist.rs
+++ b/src/libstd/dlist.rs
@@ -40,18 +40,18 @@ priv impl<T> DListNode<T> {
         match self.next {
             Some(neighbour) => match neighbour.prev {
               Some(me) => if !managed::mut_ptr_eq(self, me) {
-                  fail!(~"Asymmetric next-link in dlist node.")
+                  fail!("Asymmetric next-link in dlist node.")
               },
-              None => fail!(~"One-way next-link in dlist node.")
+              None => fail!("One-way next-link in dlist node.")
             },
             None => ()
         }
         match self.prev {
             Some(neighbour) => match neighbour.next {
               Some(me) => if !managed::mut_ptr_eq(me, self) {
-                  fail!(~"Asymmetric prev-link in dlist node.")
+                  fail!("Asymmetric prev-link in dlist node.")
               },
-              None => fail!(~"One-way prev-link in dlist node.")
+              None => fail!("One-way prev-link in dlist node.")
             },
             None => ()
         }
@@ -68,7 +68,7 @@ pub impl<T> DListNode<T> {
     fn next_node(@mut self) -> @mut DListNode<T> {
         match self.next_link() {
             Some(nobe) => nobe,
-            None       => fail!(~"This dlist node has no next neighbour.")
+            None       => fail!("This dlist node has no next neighbour.")
         }
     }
     /// Get the previous node in the list, if there is one.
@@ -80,7 +80,7 @@ pub impl<T> DListNode<T> {
     fn prev_node(@mut self) -> @mut DListNode<T> {
         match self.prev_link() {
             Some(nobe) => nobe,
-            None       => fail!(~"This dlist node has no previous neighbour.")
+            None       => fail!("This dlist node has no previous neighbour.")
         }
     }
 }
@@ -132,21 +132,21 @@ priv impl<T> DList<T> {
         // These asserts could be stronger if we had node-root back-pointers,
         // but those wouldn't allow for O(1) append.
         if self.size == 0 {
-            fail!(~"This dlist is empty; that node can't be on it.")
+            fail!("This dlist is empty; that node can't be on it.")
         }
-        if !nobe.linked { fail!(~"That node isn't linked to any dlist.") }
+        if !nobe.linked { fail!("That node isn't linked to any dlist.") }
         if !((nobe.prev.is_some()
               || managed::mut_ptr_eq(self.hd.expect(~"headless dlist?"),
                                  nobe)) &&
              (nobe.next.is_some()
               || managed::mut_ptr_eq(self.tl.expect(~"tailless dlist?"),
                                  nobe))) {
-            fail!(~"That node isn't on this dlist.")
+            fail!("That node isn't on this dlist.")
         }
     }
     fn make_mine(&self, nobe: @mut DListNode<T>) {
         if nobe.prev.is_some() || nobe.next.is_some() || nobe.linked {
-            fail!(~"Cannot insert node that's already on a dlist!")
+            fail!("Cannot insert node that's already on a dlist!")
         }
         nobe.linked = true;
     }
@@ -318,16 +318,14 @@ pub impl<T> DList<T> {
     fn head_n(@mut self) -> @mut DListNode<T> {
         match self.hd {
             Some(nobe) => nobe,
-            None       => fail!(
-                ~"Attempted to get the head of an empty dlist.")
+            None       => fail!("Attempted to get the head of an empty dlist.")
         }
     }
     /// Get the node at the list's tail, failing if empty. O(1).
     fn tail_n(@mut self) -> @mut DListNode<T> {
         match self.tl {
             Some(nobe) => nobe,
-            None       => fail!(
-                ~"Attempted to get the tail of an empty dlist.")
+            None       => fail!("Attempted to get the tail of an empty dlist.")
         }
     }
 
@@ -340,7 +338,7 @@ pub impl<T> DList<T> {
      */
     fn append(@mut self, them: @mut DList<T>) {
         if managed::mut_ptr_eq(self, them) {
-            fail!(~"Cannot append a dlist to itself!")
+            fail!("Cannot append a dlist to itself!")
         }
         if them.len() > 0 {
             self.link(self.tl, them.hd);
@@ -357,7 +355,7 @@ pub impl<T> DList<T> {
      */
     fn prepend(@mut self, them: @mut DList<T>) {
         if managed::mut_ptr_eq(self, them) {
-            fail!(~"Cannot prepend a dlist to itself!")
+            fail!("Cannot prepend a dlist to itself!")
         }
         if them.len() > 0 {
             self.link(them.tl, self.hd);
@@ -524,7 +522,7 @@ impl<T> BaseIter<T> for @mut DList<T> {
 
             // Check (weakly) that the user didn't do a remove.
             if self.size == 0 {
-                fail!(~"The dlist became empty during iteration??")
+                fail!("The dlist became empty during iteration??")
             }
             if !nobe.linked ||
                 (!((nobe.prev.is_some()
@@ -533,7 +531,7 @@ impl<T> BaseIter<T> for @mut DList<T> {
                    && (nobe.next.is_some()
                     || managed::mut_ptr_eq(self.tl.expect(~"tailless dlist?"),
                                            nobe)))) {
-                fail!(~"Removing a dlist node during iteration is forbidden!")
+                fail!("Removing a dlist node during iteration is forbidden!")
             }
             link = nobe.next_link();
         }
diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs
index 98618e4928b..07c1c226d1f 100644
--- a/src/libstd/ebml.rs
+++ b/src/libstd/ebml.rs
@@ -116,7 +116,7 @@ pub mod reader {
                         (data[start + 3u] as uint),
                     next: start + 4u};
         }
-        fail!(~"vint too big");
+        fail!("vint too big");
     }
 
     #[cfg(target_arch = "x86")]
@@ -319,9 +319,7 @@ pub mod reader {
                     self.pos = r_doc.end;
                     let str = doc_as_str(r_doc);
                     if lbl != str {
-                        fail!(fmt!("Expected label %s but found %s",
-                                   lbl,
-                                   str));
+                        fail!("Expected label %s but found %s", lbl, str);
                     }
                 }
             }
@@ -330,7 +328,7 @@ pub mod reader {
         fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc {
             debug!(". next_doc(exp_tag=%?)", exp_tag);
             if self.pos >= self.parent.end {
-                fail!(~"no more documents in current node!");
+                fail!("no more documents in current node!");
             }
             let TaggedDoc { tag: r_tag, doc: r_doc } =
                 doc_at(self.parent.data, self.pos);
@@ -338,12 +336,11 @@ pub mod reader {
                    copy self.parent.start, copy self.parent.end,
                    copy self.pos, r_tag, r_doc.start, r_doc.end);
             if r_tag != (exp_tag as uint) {
-                fail!(fmt!("expected EBML doc with tag %? but found tag %?",
-                          exp_tag, r_tag));
+                fail!("expected EBML doc with tag %? but found tag %?", exp_tag, r_tag);
             }
             if r_doc.end > self.parent.end {
-                fail!(fmt!("invalid EBML, child extends to 0x%x, \
-                           parent to 0x%x", r_doc.end, self.parent.end));
+                fail!("invalid EBML, child extends to 0x%x, parent to 0x%x",
+                      r_doc.end, self.parent.end);
             }
             self.pos = r_doc.end;
             r_doc
@@ -393,7 +390,7 @@ pub mod reader {
         fn read_uint(&mut self) -> uint {
             let v = doc_as_u64(self.next_doc(EsUint));
             if v > (::core::uint::max_value as u64) {
-                fail!(fmt!("uint %? too large for this architecture", v));
+                fail!("uint %? too large for this architecture", v);
             }
             v as uint
         }
@@ -414,7 +411,7 @@ pub mod reader {
             let v = doc_as_u64(self.next_doc(EsInt)) as i64;
             if v > (int::max_value as i64) || v < (int::min_value as i64) {
                 debug!("FIXME #6122: Removing this makes this function miscompile");
-                fail!(fmt!("int %? out of range for this architecture", v));
+                fail!("int %? out of range for this architecture", v);
             }
             v as int
         }
@@ -423,10 +420,10 @@ pub mod reader {
             doc_as_u8(self.next_doc(EsBool)) as bool
         }
 
-        fn read_f64(&mut self) -> f64 { fail!(~"read_f64()"); }
-        fn read_f32(&mut self) -> f32 { fail!(~"read_f32()"); }
-        fn read_float(&mut self) -> float { fail!(~"read_float()"); }
-        fn read_char(&mut self) -> char { fail!(~"read_char()"); }
+        fn read_f64(&mut self) -> f64 { fail!("read_f64()"); }
+        fn read_f32(&mut self) -> f32 { fail!("read_f32()"); }
+        fn read_float(&mut self) -> float { fail!("read_float()"); }
+        fn read_char(&mut self) -> char { fail!("read_char()"); }
         fn read_str(&mut self) -> ~str { doc_as_str(self.next_doc(EsStr)) }
 
         // Compound types:
@@ -602,7 +599,7 @@ pub mod reader {
 
         fn read_map<T>(&mut self, _: &fn(&mut Decoder, uint) -> T) -> T {
             debug!("read_map()");
-            fail!(~"read_map is unimplemented");
+            fail!("read_map is unimplemented");
         }
 
         fn read_map_elt_key<T>(&mut self,
@@ -610,7 +607,7 @@ pub mod reader {
                                _: &fn(&mut Decoder) -> T)
                                -> T {
             debug!("read_map_elt_key(idx=%u)", idx);
-            fail!(~"read_map_elt_val is unimplemented");
+            fail!("read_map_elt_val is unimplemented");
         }
 
         fn read_map_elt_val<T>(&mut self,
@@ -618,7 +615,7 @@ pub mod reader {
                                _: &fn(&mut Decoder) -> T)
                                -> T {
             debug!("read_map_elt_val(idx=%u)", idx);
-            fail!(~"read_map_elt_val is unimplemented");
+            fail!("read_map_elt_val is unimplemented");
         }
     }
 }
@@ -631,7 +628,6 @@ pub mod writer {
 
     use core::io;
     use core::str;
-    use core::vec;
 
     // ebml writing
     pub struct Encoder {
@@ -647,7 +643,7 @@ pub mod writer {
                             n as u8]),
             4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
                             (n >> 8_u) as u8, n as u8]),
-            _ => fail!(fmt!("vint to write too big: %?", n))
+            _ => fail!("vint to write too big: %?", n)
         };
     }
 
@@ -656,7 +652,7 @@ pub mod writer {
         if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
         if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
         if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
-        fail!(fmt!("vint to write too big: %?", n));
+        fail!("vint to write too big: %?", n);
     }
 
     #[cfg(stage0)]
@@ -710,7 +706,7 @@ pub mod writer {
 
         fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
             write_vuint(self.writer, tag_id);
-            write_vuint(self.writer, vec::len(b));
+            write_vuint(self.writer, b.len());
             self.writer.write(b);
         }
 
@@ -763,7 +759,7 @@ pub mod writer {
         }
 
         fn wr_bytes(&mut self, b: &[u8]) {
-            debug!("Write %u bytes", vec::len(b));
+            debug!("Write %u bytes", b.len());
             self.writer.write(b);
         }
 
@@ -847,17 +843,17 @@ pub mod writer {
 
         // FIXME (#2742): implement these
         fn emit_f64(&mut self, _v: f64) {
-            fail!(~"Unimplemented: serializing an f64");
+            fail!("Unimplemented: serializing an f64");
         }
         fn emit_f32(&mut self, _v: f32) {
-            fail!(~"Unimplemented: serializing an f32");
+            fail!("Unimplemented: serializing an f32");
         }
         fn emit_float(&mut self, _v: float) {
-            fail!(~"Unimplemented: serializing a float");
+            fail!("Unimplemented: serializing a float");
         }
 
         fn emit_char(&mut self, _v: char) {
-            fail!(~"Unimplemented: serializing a char");
+            fail!("Unimplemented: serializing a char");
         }
 
         fn emit_str(&mut self, v: &str) {
@@ -954,15 +950,15 @@ pub mod writer {
         }
 
         fn emit_map(&mut self, _len: uint, _f: &fn(&mut Encoder)) {
-            fail!(~"emit_map is unimplemented");
+            fail!("emit_map is unimplemented");
         }
 
         fn emit_map_elt_key(&mut self, _idx: uint, _f: &fn(&mut Encoder)) {
-            fail!(~"emit_map_elt_key is unimplemented");
+            fail!("emit_map_elt_key is unimplemented");
         }
 
         fn emit_map_elt_val(&mut self, _idx: uint, _f: &fn(&mut Encoder)) {
-            fail!(~"emit_map_elt_val is unimplemented");
+            fail!("emit_map_elt_val is unimplemented");
         }
     }
 }
diff --git a/src/libstd/fileinput.rs b/src/libstd/fileinput.rs
index c3622fad53b..a31827f95d1 100644
--- a/src/libstd/fileinput.rs
+++ b/src/libstd/fileinput.rs
@@ -598,7 +598,7 @@ mod test {
             let expected_path = match line {
                 "1" | "2" => copy filenames[0],
                 "3" | "4" => copy filenames[2],
-                _ => fail!(~"unexpected line")
+                _ => fail!("unexpected line")
             };
             assert_eq!(copy state.current_path, expected_path);
             count += 1;
diff --git a/src/libstd/flatpipes.rs b/src/libstd/flatpipes.rs
index 6547ff8eefb..f4b581f84fc 100644
--- a/src/libstd/flatpipes.rs
+++ b/src/libstd/flatpipes.rs
@@ -258,7 +258,7 @@ impl<T,U:Unflattener<T>,P:BytePort> GenericPort<T> for FlatPort<T, U, P> {
     fn recv(&self) -> T {
         match self.try_recv() {
             Some(val) => val,
-            None => fail!(~"port is closed")
+            None => fail!("port is closed")
         }
     }
     fn try_recv(&self) -> Option<T> {
@@ -294,7 +294,7 @@ impl<T,U:Unflattener<T>,P:BytePort> GenericPort<T> for FlatPort<T, U, P> {
             }
         }
         else {
-            fail!(~"flatpipe: unrecognized command");
+            fail!("flatpipe: unrecognized command");
         }
     }
 }
@@ -473,7 +473,7 @@ pub mod flatteners {
                 Ok(json) => {
                     json::Decoder(json)
                 }
-                Err(e) => fail!(fmt!("flatpipe: can't parse json: %?", e))
+                Err(e) => fail!("flatpipe: can't parse json: %?", e)
             }
         }
     }
@@ -639,6 +639,7 @@ mod test {
     use core::io::BytesWriter;
 
     #[test]
+    #[ignore(reason = "ebml failure")]
     fn test_serializing_memory_stream() {
         let writer = BytesWriter();
         let chan = serial::writer_chan(writer);
@@ -671,6 +672,7 @@ mod test {
     }
 
     #[test]
+    #[ignore(reason = "ebml failure")]
     fn test_serializing_boxes() {
         let (port, chan) = serial::pipe_stream();
 
diff --git a/src/libstd/fun_treemap.rs b/src/libstd/fun_treemap.rs
index 3bffeddbe09..6b051fa21b1 100644
--- a/src/libstd/fun_treemap.rs
+++ b/src/libstd/fun_treemap.rs
@@ -33,45 +33,40 @@ enum TreeNode<K, V> {
 pub fn init<K, V>() -> Treemap<K, V> { @Empty }
 
 /// Insert a value into the map
-pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V)
-  -> Treemap<K, V> {
+pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
     @match m {
-       @Empty => Node(@k, @v, @Empty, @Empty),
-       @Node(@copy kk, vv, left, right) => {
-         if k < kk {
-             Node(@kk, vv, insert(left, k, v), right)
-         } else if k == kk {
-             Node(@kk, @v, left, right)
-         } else { Node(@kk, vv, left, insert(right, k, v)) }
-       }
-     }
+        @Empty => Node(@k, @v, @Empty, @Empty),
+        @Node(@copy kk, vv, left, right) => cond!(
+            (k <  kk) { Node(@kk, vv, insert(left, k, v), right) }
+            (k == kk) { Node(@kk, @v, left, right)               }
+            _         { Node(@kk, vv, left, insert(right, k, v)) }
+        )
+    }
 }
 
 /// Find a value based on the key
 pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
     match *m {
-      Empty => None,
-      Node(@ref kk, @copy v, left, right) => {
-        if k == *kk {
-            Some(v)
-        } else if k < *kk { find(left, k) } else { find(right, k) }
-      }
+        Empty => None,
+        Node(@ref kk, @copy v, left, right) => cond!(
+            (k == *kk) { Some(v)        }
+            (k <  *kk) { find(left, k)  }
+            _          { find(right, k) }
+        )
     }
 }
 
 /// Visit all pairs in the map in order.
 pub fn traverse<K, V: Copy>(m: Treemap<K, V>, f: &fn(&K, &V)) {
     match *m {
-      Empty => (),
-      /*
-        Previously, this had what looked like redundant
-        matches to me, so I changed it. but that may be a
-        de-optimization -- tjc
-       */
-      Node(@ref k, @ref v, left, right) => {
-        traverse(left, f);
-        f(k, v);
-        traverse(right, f);
-      }
+        Empty => (),
+        // Previously, this had what looked like redundant
+        // matches to me, so I changed it. but that may be a
+        // de-optimization -- tjc
+        Node(@ref k, @ref v, left, right) => {
+            traverse(left, f);
+            f(k, v);
+            traverse(right, f);
+        }
     }
 }
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
index 9906be13cb9..be33c0f4663 100644
--- a/src/libstd/future.rs
+++ b/src/libstd/future.rs
@@ -67,14 +67,14 @@ pub impl<A> Future<A> {
             {
                 match self.state {
                     Forced(ref mut v) => { return cast::transmute(v); }
-                    Evaluating => fail!(~"Recursive forcing of future!"),
+                    Evaluating => fail!("Recursive forcing of future!"),
                     Pending(_) => {}
                 }
             }
             {
                 let state = replace(&mut self.state, Evaluating);
                 match state {
-                    Forced(_) | Evaluating => fail!(~"Logic error."),
+                    Forced(_) | Evaluating => fail!("Logic error."),
                     Pending(f) => {
                         self.state = Forced(f());
                         cast::transmute(self.get_ref())
diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs
index f66b56381f0..1cb63124456 100644
--- a/src/libstd/getopts.rs
+++ b/src/libstd/getopts.rs
@@ -554,7 +554,7 @@ pub mod groups {
                      _} = copy *lopt;
 
         match (short_name.len(), long_name.len()) {
-           (0,0) => fail!(~"this long-format option was given no name"),
+           (0,0) => fail!("this long-format option was given no name"),
 
            (0,_) => ~[Opt {name: Long((long_name)),
                            hasarg: hasarg,
@@ -571,7 +571,7 @@ pub mod groups {
                            hasarg: hasarg,
                            occur:  occur}],
 
-           (_,_) => fail!(~"something is wrong with the long-form opt")
+           (_,_) => fail!("something is wrong with the long-form opt")
         }
     }
 
@@ -603,7 +603,7 @@ pub mod groups {
             row += match short_name.len() {
                 0 => ~"",
                 1 => ~"-" + short_name + " ",
-                _ => fail!(~"the short name should only be 1 ascii char long"),
+                _ => fail!("the short name should only be 1 ascii char long"),
             };
 
             // long option
@@ -686,7 +686,7 @@ mod tests {
             assert!((opt_present(m, ~"test")));
             assert!((opt_str(m, ~"test") == ~"20"));
           }
-          _ => { fail!(~"test_reqopt_long failed"); }
+          _ => { fail!("test_reqopt_long failed"); }
         }
     }
 
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
index 2acbcf5c7ec..270cf675c87 100644
--- a/src/libstd/json.rs
+++ b/src/libstd/json.rs
@@ -853,7 +853,7 @@ impl serialize::Decoder for Decoder {
         debug!("read_nil");
         match self.stack.pop() {
             Null => (),
-            value => fail!(fmt!("not a null: %?", value))
+            value => fail!("not a null: %?", value)
         }
     }
 
@@ -873,7 +873,7 @@ impl serialize::Decoder for Decoder {
         debug!("read_bool");
         match self.stack.pop() {
             Boolean(b) => b,
-            value => fail!(fmt!("not a boolean: %?", value))
+            value => fail!("not a boolean: %?", value)
         }
     }
 
@@ -883,14 +883,14 @@ impl serialize::Decoder for Decoder {
         debug!("read_float");
         match self.stack.pop() {
             Number(f) => f,
-            value => fail!(fmt!("not a number: %?", value))
+            value => fail!("not a number: %?", value)
         }
     }
 
     fn read_char(&mut self) -> char {
         let mut v = ~[];
         for str::each_char(self.read_str()) |c| { v.push(c) }
-        if v.len() != 1 { fail!(~"string must have one character") }
+        if v.len() != 1 { fail!("string must have one character") }
         v[0]
     }
 
@@ -898,7 +898,7 @@ impl serialize::Decoder for Decoder {
         debug!("read_str");
         match self.stack.pop() {
             String(s) => s,
-            json => fail!(fmt!("not a string: %?", json))
+            json => fail!("not a string: %?", json)
         }
     }
 
@@ -920,14 +920,14 @@ impl serialize::Decoder for Decoder {
                 }
                 match self.stack.pop() {
                     String(s) => s,
-                    value => fail!(fmt!("invalid variant name: %?", value)),
+                    value => fail!("invalid variant name: %?", value),
                 }
             }
-            ref json => fail!(fmt!("invalid variant: %?", *json)),
+            ref json => fail!("invalid variant: %?", *json),
         };
         let idx = match vec::position(names, |n| str::eq_slice(*n, name)) {
             Some(idx) => idx,
-            None => fail!(fmt!("Unknown variant name: %?", name)),
+            None => fail!("Unknown variant name: %?", name),
         };
         f(self, idx)
     }
@@ -979,7 +979,7 @@ impl serialize::Decoder for Decoder {
             Object(obj) => {
                 let mut obj = obj;
                 let value = match obj.pop(&name.to_owned()) {
-                    None => fail!(fmt!("no such field: %s", name)),
+                    None => fail!("no such field: %s", name),
                     Some(json) => {
                         self.stack.push(json);
                         f(self)
@@ -988,7 +988,7 @@ impl serialize::Decoder for Decoder {
                 self.stack.push(Object(obj));
                 value
             }
-            value => fail!(fmt!("not an object: %?", value))
+            value => fail!("not an object: %?", value)
         }
     }
 
@@ -1038,7 +1038,7 @@ impl serialize::Decoder for Decoder {
                 }
                 len
             }
-            _ => fail!(~"not a list"),
+            _ => fail!("not a list"),
         };
         f(self, len)
     }
@@ -1060,7 +1060,7 @@ impl serialize::Decoder for Decoder {
                 }
                 len
             }
-            json => fail!(fmt!("not an object: %?", json)),
+            json => fail!("not an object: %?", json),
         };
         f(self, len)
     }
@@ -1331,26 +1331,20 @@ mod tests {
 
     use std::serialize::Decodable;
 
-    #[auto_encode]
-    #[auto_decode]
-    #[deriving(Eq)]
+    #[deriving(Eq, Encodable, Decodable)]
     enum Animal {
         Dog,
         Frog(~str, int)
     }
 
-    #[auto_encode]
-    #[auto_decode]
-    #[deriving(Eq)]
+    #[deriving(Eq, Encodable, Decodable)]
     struct Inner {
         a: (),
         b: uint,
         c: ~[~str],
     }
 
-    #[auto_encode]
-    #[auto_decode]
-    #[deriving(Eq)]
+    #[deriving(Eq, Encodable, Decodable)]
     struct Outer {
         inner: ~[Inner],
     }
diff --git a/src/libstd/list.rs b/src/libstd/list.rs
index 13ef377fabe..aa4abbac9d3 100644
--- a/src/libstd/list.rs
+++ b/src/libstd/list.rs
@@ -93,7 +93,7 @@ pub fn len<T>(ls: @List<T>) -> uint {
 pub fn tail<T:Copy>(ls: @List<T>) -> @List<T> {
     match *ls {
         Cons(_, tl) => return tl,
-        Nil => fail!(~"list empty")
+        Nil => fail!("list empty")
     }
 }
 
@@ -102,7 +102,7 @@ pub fn head<T:Copy>(ls: @List<T>) -> T {
     match *ls {
       Cons(copy hd, _) => hd,
       // makes me sad
-      _ => fail!(~"head invoked on empty list")
+      _ => fail!("head invoked on empty list")
     }
 }
 
diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs
index 71b62ca36a5..84561256cd1 100644
--- a/src/libstd/md4.rs
+++ b/src/libstd/md4.rs
@@ -23,7 +23,7 @@ pub fn md4(msg: &[u8]) -> Quad {
     // subtle: if orig_len is merely uint, then the code below
     // which performs shifts by 32 bits or more has undefined
     // results.
-    let orig_len: u64 = (vec::len(msg) * 8u) as u64;
+    let orig_len: u64 = (msg.len() * 8u) as u64;
 
     // pad message
     let mut msg = vec::append(vec::to_owned(msg), ~[0x80u8]);
@@ -51,7 +51,7 @@ pub fn md4(msg: &[u8]) -> Quad {
     }
 
     let mut i = 0u;
-    let e = vec::len(msg);
+    let e = msg.len();
     let mut x = vec::from_elem(16u, 0u32);
     while i < e {
         let aa = a, bb = b, cc = c, dd = d;
diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs
index 58775c5f2e4..cc4e7ee0204 100644
--- a/src/libstd/net_ip.rs
+++ b/src/libstd/net_ip.rs
@@ -15,7 +15,6 @@ use core::comm::{stream, SharedChan};
 use core::ptr;
 use core::result;
 use core::str;
-use core::vec;
 
 use iotask = uv::iotask::IoTask;
 use interact = uv::iotask::interact;
@@ -59,14 +58,14 @@ pub fn format_addr(ip: &IpAddr) -> ~str {
       Ipv4(ref addr) =>  unsafe {
         let result = uv_ip4_name(addr);
         if result == ~"" {
-            fail!(~"failed to convert inner sockaddr_in address to str")
+            fail!("failed to convert inner sockaddr_in address to str")
         }
         result
       },
       Ipv6(ref addr) => unsafe {
         let result = uv_ip6_name(addr);
         if result == ~"" {
-            fail!(~"failed to convert inner sockaddr_in address to str")
+            fail!("failed to convert inner sockaddr_in address to str")
         }
         result
       }
@@ -340,7 +339,7 @@ extern fn get_addr_cb(handle: *uv_getaddrinfo_t,
                     }
                 }
                 debug!("successful process addrinfo result, len: %?",
-                                vec::len(out_vec));
+                                out_vec.len());
                 output_ch.send(result::Ok(out_vec));
             }
             else {
@@ -394,7 +393,7 @@ mod test {
             assert!(true);
           }
           result::Ok(ref addr) => {
-            fail!(fmt!("Expected failure, but got addr %?", addr));
+            fail!("Expected failure, but got addr %?", addr);
           }
         }
     }
@@ -407,7 +406,7 @@ mod test {
             assert!(true);
           }
           result::Ok(ref addr) => {
-            fail!(fmt!("Expected failure, but got addr %?", addr));
+            fail!("Expected failure, but got addr %?", addr);
           }
         }
     }
@@ -418,13 +417,13 @@ mod test {
         let iotask = &uv::global_loop::get();
         let ga_result = get_addr(localhost_name, iotask);
         if result::is_err(&ga_result) {
-            fail!(~"got err result from net::ip::get_addr();")
+            fail!("got err result from net::ip::get_addr();")
         }
         // note really sure how to reliably test/assert
         // this.. mostly just wanting to see it work, atm.
         let results = result::unwrap(ga_result);
         debug!("test_get_addr: Number of results for %s: %?",
-                        localhost_name, vec::len(results));
+                        localhost_name, results.len());
         for results.each |r| {
             let ipv_prefix = match *r {
               Ipv4(_) => ~"IPv4",
diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs
index 20e1a272910..37578e42baf 100644
--- a/src/libstd/net_tcp.rs
+++ b/src/libstd/net_tcp.rs
@@ -1646,7 +1646,7 @@ mod test {
             hl_loop);
         match actual_resp_result.get_err() {
           ConnectionRefused => (),
-          _ => fail!(~"unknown error.. expected connection_refused")
+          _ => fail!("unknown error.. expected connection_refused")
         }
     }
     pub fn impl_gl_tcp_ipv4_server_address_in_use() {
@@ -1687,8 +1687,8 @@ mod test {
             assert!(true);
           }
           _ => {
-            fail!(~"expected address_in_use listen error,"+
-                ~"but got a different error varient. check logs.");
+            fail!("expected address_in_use listen error, \
+                   but got a different error varient. check logs.");
           }
         }
     }
@@ -1706,8 +1706,8 @@ mod test {
             assert!(true);
           }
           _ => {
-            fail!(~"expected address_in_use listen error,"+
-                      ~"but got a different error varient. check logs.");
+            fail!("expected address_in_use listen error, \
+                   but got a different error varient. check logs.");
           }
         }
     }
@@ -1802,7 +1802,7 @@ mod test {
         debug!("BUF_WRITE: val len %?", str::len(val));
         do str::byte_slice(val) |b_slice| {
             debug!("BUF_WRITE: b_slice len %?",
-                            vec::len(b_slice));
+                            b_slice.len());
             w.write(b_slice)
         }
     }
@@ -1810,7 +1810,7 @@ mod test {
     fn buf_read<R:io::Reader>(r: &R, len: uint) -> ~str {
         let new_bytes = (*r).read_bytes(len);
         debug!("in buf_read.. new_bytes len: %?",
-                        vec::len(new_bytes));
+                        new_bytes.len());
         str::from_bytes(new_bytes)
     }
 
@@ -1863,7 +1863,7 @@ mod test {
                           result::Ok(data) => {
                             debug!("SERVER: got REQ str::from_bytes..");
                             debug!("SERVER: REQ data len: %?",
-                                            vec::len(data));
+                                            data.len());
                             server_ch.send(
                                 str::from_bytes(data));
                             debug!("SERVER: before write");
@@ -1888,14 +1888,13 @@ mod test {
         if result::is_err(&listen_result) {
             match result::get_err(&listen_result) {
               GenericListenErr(ref name, ref msg) => {
-                fail!(fmt!("SERVER: exited abnormally name %s msg %s",
-                                *name, *msg));
+                fail!("SERVER: exited abnormally name %s msg %s", *name, *msg);
               }
               AccessDenied => {
-                fail!(~"SERVER: exited abnormally, got access denied..");
+                fail!("SERVER: exited abnormally, got access denied..");
               }
               AddressInUse => {
-                fail!(~"SERVER: exited abnormally, got address in use...");
+                fail!("SERVER: exited abnormally, got address in use...");
               }
             }
         }
@@ -1914,15 +1913,14 @@ mod test {
                 debug!("establish_cb %?", kill_ch);
             },
             |new_conn, kill_ch| {
-                fail!(fmt!("SERVER: shouldn't be called.. %? %?",
-                           new_conn, kill_ch));
+                fail!("SERVER: shouldn't be called.. %? %?", new_conn, kill_ch);
         });
         // err check on listen_result
         if result::is_err(&listen_result) {
             result::get_err(&listen_result)
         }
         else {
-            fail!(~"SERVER: did not fail as expected")
+            fail!("SERVER: did not fail as expected")
         }
     }
 
@@ -1966,7 +1964,7 @@ mod test {
             debug!("tcp_write_single err name: %s msg: %s",
                 err_data.err_name, err_data.err_msg);
             // meh. torn on what to do here.
-            fail!(~"tcp_write_single failed");
+            fail!("tcp_write_single failed");
         }
     }
 }
diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs
index 498c86dd8e1..c35415c5331 100644
--- a/src/libstd/num/bigint.rs
+++ b/src/libstd/num/bigint.rs
@@ -17,7 +17,7 @@ A BigInt is a combination of BigUint and Sign.
 */
 
 use core::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
-use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix};
+use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
 
 /**
 A BigDigit is a BigUint's composing element.
@@ -144,6 +144,26 @@ impl FromStr for BigUint {
     }
 }
 
+impl Num for BigUint {}
+
+impl Orderable for BigUint {
+    #[inline(always)]
+    fn min(&self, other: &BigUint) -> BigUint {
+        if self < other { self.clone() } else { other.clone() }
+    }
+
+    #[inline(always)]
+    fn max(&self, other: &BigUint) -> BigUint {
+        if self > other { self.clone() } else { other.clone() }
+    }
+
+    #[inline(always)]
+    fn clamp(&self, mn: &BigUint, mx: &BigUint) -> BigUint {
+        if self > mx { mx.clone() } else
+        if self < mn { mn.clone() } else { self.clone() }
+    }
+}
+
 impl Shl<uint, BigUint> for BigUint {
     #[inline(always)]
     fn shl(&self, rhs: &uint) -> BigUint {
@@ -788,6 +808,26 @@ impl FromStr for BigInt {
     }
 }
 
+impl Num for BigInt {}
+
+impl Orderable for BigInt {
+    #[inline(always)]
+    fn min(&self, other: &BigInt) -> BigInt {
+        if self < other { self.clone() } else { other.clone() }
+    }
+
+    #[inline(always)]
+    fn max(&self, other: &BigInt) -> BigInt {
+        if self > other { self.clone() } else { other.clone() }
+    }
+
+    #[inline(always)]
+    fn clamp(&self, mn: &BigInt, mx: &BigInt) -> BigInt {
+        if self > mx { mx.clone() } else
+        if self < mn { mn.clone() } else { self.clone() }
+    }
+}
+
 impl Shl<uint, BigInt> for BigInt {
     #[inline(always)]
     fn shl(&self, rhs: &uint) -> BigInt {
diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs
index 9b92b7241b9..d57c642c5a2 100644
--- a/src/libstd/num/rational.rs
+++ b/src/libstd/num/rational.rs
@@ -30,7 +30,7 @@ pub type Rational64 = Ratio<i64>;
 /// Alias for arbitrary precision rationals.
 pub type BigRational = Ratio<BigInt>;
 
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Ratio<T> {
     /// Create a ratio representing the integer `t`.
     #[inline(always)]
@@ -48,7 +48,7 @@ impl<T: Copy + Num + Ord>
     #[inline(always)]
     pub fn new(numer: T, denom: T) -> Ratio<T> {
         if denom == Zero::zero() {
-            fail!(~"denominator == 0");
+            fail!("denominator == 0");
         }
         let mut ret = Ratio::new_raw(numer, denom);
         ret.reduce();
@@ -57,10 +57,14 @@ impl<T: Copy + Num + Ord>
 
     /// Put self into lowest terms, with denom > 0.
     fn reduce(&mut self) {
-        let g : T = gcd(self.numer, self.denom);
+        let g : T = self.numer.gcd(&self.denom);
 
-        self.numer /= g;
-        self.denom /= g;
+        // FIXME(#6050): overloaded operators force moves with generic types
+        // self.numer /= g;
+        self.numer = self.numer / g;
+        // FIXME(#6050): overloaded operators force moves with generic types
+        // self.denom /= g;
+        self.denom = self.denom / g;
 
         // keep denom positive!
         if self.denom < Zero::zero() {
@@ -68,42 +72,15 @@ impl<T: Copy + Num + Ord>
             self.denom = -self.denom;
         }
     }
+
     /// Return a `reduce`d copy of self.
     fn reduced(&self) -> Ratio<T> {
-        let mut ret = copy *self;
+        let mut ret = self.clone();
         ret.reduce();
         ret
     }
 }
 
-/**
-Compute the greatest common divisor of two numbers, via Euclid's algorithm.
-
-The result can be negative.
-*/
-#[inline]
-pub fn gcd_raw<T: Num>(n: T, m: T) -> T {
-    let mut m = m, n = n;
-    while m != Zero::zero() {
-        let temp = m;
-        m = n % temp;
-        n = temp;
-    }
-    n
-}
-
-/**
-Compute the greatest common divisor of two numbers, via Euclid's algorithm.
-
-The result is always positive.
-*/
-#[inline]
-pub fn gcd<T: Num + Ord>(n: T, m: T) -> T {
-    let g = gcd_raw(n, m);
-    if g < Zero::zero() { -g }
-    else { g }
-}
-
 /* Comparisons */
 
 // comparing a/b and c/d is the same as comparing a*d and b*c, so we
@@ -133,7 +110,7 @@ cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
 
 /* Arithmetic */
 // a/b * c/d = (a*c)/(b*d)
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Mul<Ratio<T>,Ratio<T>> for Ratio<T> {
     #[inline]
     fn mul(&self, rhs: &Ratio<T>) -> Ratio<T> {
@@ -142,7 +119,7 @@ impl<T: Copy + Num + Ord>
 }
 
 // (a/b) / (c/d) = (a*d)/(b*c)
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Div<Ratio<T>,Ratio<T>> for Ratio<T> {
     #[inline]
     fn div(&self, rhs: &Ratio<T>) -> Ratio<T> {
@@ -153,7 +130,7 @@ impl<T: Copy + Num + Ord>
 // Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
 macro_rules! arith_impl {
     (impl $imp:ident, $method:ident) => {
-        impl<T: Copy + Num + Ord>
+        impl<T: Clone + Integer + Ord>
             $imp<Ratio<T>,Ratio<T>> for Ratio<T> {
             #[inline]
             fn $method(&self, rhs: &Ratio<T>) -> Ratio<T> {
@@ -173,16 +150,16 @@ arith_impl!(impl Sub, sub)
 // a/b % c/d = (a*d % b*c)/(b*d)
 arith_impl!(impl Rem, rem)
 
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Neg<Ratio<T>> for Ratio<T> {
     #[inline]
     fn neg(&self) -> Ratio<T> {
-        Ratio::new_raw(-self.numer, self.denom)
+        Ratio::new_raw(-self.numer, self.denom.clone())
     }
 }
 
 /* Constants */
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Zero for Ratio<T> {
     #[inline]
     fn zero() -> Ratio<T> {
@@ -195,7 +172,7 @@ impl<T: Copy + Num + Ord>
     }
 }
 
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     One for Ratio<T> {
     #[inline]
     fn one() -> Ratio<T> {
@@ -203,11 +180,11 @@ impl<T: Copy + Num + Ord>
     }
 }
 
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Num for Ratio<T> {}
 
 /* Utils */
-impl<T: Copy + Num + Ord>
+impl<T: Clone + Integer + Ord>
     Round for Ratio<T> {
 
     fn floor(&self) -> Ratio<T> {
@@ -241,14 +218,14 @@ impl<T: Copy + Num + Ord>
     }
 
     fn fract(&self) -> Ratio<T> {
-        Ratio::new_raw(self.numer % self.denom, self.denom)
+        Ratio::new_raw(self.numer % self.denom, self.denom.clone())
     }
 }
 
-impl<T: Copy + Num + Ord> Fractional for Ratio<T> {
+impl<T: Clone + Integer + Ord> Fractional for Ratio<T> {
     #[inline]
     fn recip(&self) -> Ratio<T> {
-        Ratio::new_raw(self.denom, self.numer)
+        Ratio::new_raw(self.denom.clone(), self.numer.clone())
     }
 }
 
@@ -266,7 +243,7 @@ impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
     }
 }
 
-impl<T: FromStr + Copy + Num + Ord>
+impl<T: FromStr + Clone + Integer + Ord>
     FromStr for Ratio<T> {
     /// Parses `numer/denom`.
     fn from_str(s: &str) -> Option<Ratio<T>> {
@@ -276,14 +253,14 @@ impl<T: FromStr + Copy + Num + Ord>
             }
         });
         if split.len() < 2 { return None; }
-        do FromStr::from_str(split[0]).chain |a| {
-            do FromStr::from_str(split[1]).chain |b| {
-                Some(Ratio::new(a,b))
+        do FromStr::from_str::<T>(split[0]).chain |a| {
+            do FromStr::from_str::<T>(split[1]).chain |b| {
+                Some(Ratio::new(a.clone(), b.clone()))
             }
         }
     }
 }
-impl<T: FromStrRadix + Copy + Num + Ord>
+impl<T: FromStrRadix + Clone + Integer + Ord>
     FromStrRadix for Ratio<T> {
     /// Parses `numer/denom` where the numbers are in base `radix`.
     fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
@@ -294,9 +271,9 @@ impl<T: FromStrRadix + Copy + Num + Ord>
         });
         if split.len() < 2 { None }
         else {
-            do FromStrRadix::from_str_radix(split[0], radix).chain |a| {
-                do FromStrRadix::from_str_radix(split[1], radix).chain |b| {
-                    Some(Ratio::new(a,b))
+            do FromStrRadix::from_str_radix::<T>(split[0], radix).chain |a| {
+                do FromStrRadix::from_str_radix::<T>(split[1], radix).chain |b| {
+                    Some(Ratio::new(a.clone(), b.clone()))
                 }
             }
         }
@@ -306,7 +283,7 @@ impl<T: FromStrRadix + Copy + Num + Ord>
 #[cfg(test)]
 mod test {
     use super::*;
-    use core::num::{Zero,One,FromStrRadix};
+    use core::num::{Zero,One,FromStrRadix,IntConvertible};
     use core::from_str::FromStr;
 
     pub static _0 : Rational = Ratio { numer: 0, denom: 1};
@@ -316,16 +293,11 @@ mod test {
     pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
     pub static _neg1_2: Rational =  Ratio { numer: -1, denom: 2};
 
-    #[test]
-    fn test_gcd() {
-        assert_eq!(gcd(10,2),2);
-        assert_eq!(gcd(10,3),1);
-        assert_eq!(gcd(0,3),3);
-        assert_eq!(gcd(3,3),3);
-
-        assert_eq!(gcd(3,-3), 3);
-        assert_eq!(gcd(-6,3), 3);
-        assert_eq!(gcd(-4,-2), 2);
+    pub fn to_big(n: Rational) -> BigRational {
+        Ratio::new(
+            IntConvertible::from_int(n.numer),
+            IntConvertible::from_int(n.denom)
+        )
     }
 
     #[test]
@@ -374,45 +346,75 @@ mod test {
 
         #[test]
         fn test_add() {
-            assert_eq!(_1 + _1_2, _3_2);
-            assert_eq!(_1 + _1, _2);
-            assert_eq!(_1_2 + _3_2, _2);
-            assert_eq!(_1_2 + _neg1_2, _0);
+            fn test(a: Rational, b: Rational, c: Rational) {
+                assert_eq!(a + b, c);
+                assert_eq!(to_big(a) + to_big(b), to_big(c));
+            }
+
+            test(_1, _1_2, _3_2);
+            test(_1, _1, _2);
+            test(_1_2, _3_2, _2);
+            test(_1_2, _neg1_2, _0);
         }
 
         #[test]
         fn test_sub() {
-            assert_eq!(_1 - _1_2, _1_2);
-            assert_eq!(_3_2 - _1_2, _1);
-            assert_eq!(_1 - _neg1_2, _3_2);
+            fn test(a: Rational, b: Rational, c: Rational) {
+                assert_eq!(a - b, c);
+                assert_eq!(to_big(a) - to_big(b), to_big(c))
+            }
+
+            test(_1, _1_2, _1_2);
+            test(_3_2, _1_2, _1);
+            test(_1, _neg1_2, _3_2);
         }
 
         #[test]
         fn test_mul() {
-            assert_eq!(_1 * _1_2, _1_2);
-            assert_eq!(_1_2 * _3_2, Ratio::new(3,4));
-            assert_eq!(_1_2 * _neg1_2, Ratio::new(-1, 4));
+            fn test(a: Rational, b: Rational, c: Rational) {
+                assert_eq!(a * b, c);
+                assert_eq!(to_big(a) * to_big(b), to_big(c))
+            }
+
+            test(_1, _1_2, _1_2);
+            test(_1_2, _3_2, Ratio::new(3,4));
+            test(_1_2, _neg1_2, Ratio::new(-1, 4));
         }
 
         #[test]
         fn test_div() {
-            assert_eq!(_1 / _1_2, _2);
-            assert_eq!(_3_2 / _1_2, _1 + _2);
-            assert_eq!(_1 / _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2);
+            fn test(a: Rational, b: Rational, c: Rational) {
+                assert_eq!(a / b, c);
+                assert_eq!(to_big(a) / to_big(b), to_big(c))
+            }
+
+            test(_1, _1_2, _2);
+            test(_3_2, _1_2, _1 + _2);
+            test(_1, _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2);
         }
 
         #[test]
         fn test_rem() {
-            assert_eq!(_3_2 % _1, _1_2);
-            assert_eq!(_2 % _neg1_2, _0);
-            assert_eq!(_1_2 % _2,  _1_2);
+            fn test(a: Rational, b: Rational, c: Rational) {
+                assert_eq!(a % b, c);
+                assert_eq!(to_big(a) % to_big(b), to_big(c))
+            }
+
+            test(_3_2, _1, _1_2);
+            test(_2, _neg1_2, _0);
+            test(_1_2, _2,  _1_2);
         }
 
         #[test]
         fn test_neg() {
-            assert_eq!(-_0, _0);
-            assert_eq!(-_1_2, _neg1_2);
-            assert_eq!(-(-_1), _1);
+            fn test(a: Rational, b: Rational) {
+                assert_eq!(-a, b);
+                assert_eq!(-to_big(a), to_big(b))
+            }
+
+            test(_0, _0);
+            test(_1_2, _neg1_2);
+            test(-_1, _1);
         }
         #[test]
         fn test_zero() {
diff --git a/src/libstd/par.rs b/src/libstd/par.rs
index cf0eba9d30c..d1af484cb22 100644
--- a/src/libstd/par.rs
+++ b/src/libstd/par.rs
@@ -58,9 +58,8 @@ fn map_slices<A:Copy + Owned,B:Copy + Owned>(
                         info!("pre-slice: %?", (base, slice));
                         let slice : &[A] =
                             cast::transmute(slice);
-                        info!("slice: %?",
-                                       (base, vec::len(slice), end - base));
-                        assert!((vec::len(slice) == end - base));
+                        info!("slice: %?", (base, slice.len(), end - base));
+                        assert!(slice.len() == end - base);
                         f(base, slice)
                     }
                 };
diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs
index ded632b29d9..3c96a8e145d 100644
--- a/src/libstd/priority_queue.rs
+++ b/src/libstd/priority_queue.rs
@@ -12,14 +12,7 @@
 
 use core::old_iter::BaseIter;
 use core::util::{replace, swap};
-
-#[abi = "rust-intrinsic"]
-extern "rust-intrinsic" mod rusti {
-    fn move_val_init<T>(dst: &mut T, src: T);
-    fn init<T>() -> T;
-    #[cfg(not(stage0))]
-    fn uninit<T>() -> T;
-}
+use core::unstable::intrinsics::{init, move_val_init};
 
 pub struct PriorityQueue<T> {
     priv data: ~[T],
@@ -141,77 +134,32 @@ pub impl <T:Ord> PriorityQueue<T> {
 
     // The implementations of siftup and siftdown use unsafe blocks in
     // order to move an element out of the vector (leaving behind a
-    // junk element), shift along the others and move it back into the
+    // zeroed element), shift along the others and move it back into the
     // vector over the junk element.  This reduces the constant factor
     // compared to using swaps, which involves twice as many moves.
 
-    #[cfg(not(stage0))]
-    priv fn siftup(&mut self, start: uint, mut pos: uint) {
-        unsafe {
-            let new = *ptr::to_unsafe_ptr(&self.data[pos]);
-
-            while pos > start {
-                let parent = (pos - 1) >> 1;
-                if new > self.data[parent] {
-                    let x = replace(&mut self.data[parent], rusti::uninit());
-                    rusti::move_val_init(&mut self.data[pos], x);
-                    pos = parent;
-                    loop
-                }
-                break
-            }
-            rusti::move_val_init(&mut self.data[pos], new);
-        }
-    }
-
-    #[cfg(stage0)]
     priv fn siftup(&mut self, start: uint, mut pos: uint) {
         unsafe {
-            let new = *ptr::to_unsafe_ptr(&self.data[pos]);
+            let new = replace(&mut self.data[pos], init());
 
             while pos > start {
                 let parent = (pos - 1) >> 1;
                 if new > self.data[parent] {
-                    let x = replace(&mut self.data[parent], rusti::init());
-                    rusti::move_val_init(&mut self.data[pos], x);
+                    let x = replace(&mut self.data[parent], init());
+                    move_val_init(&mut self.data[pos], x);
                     pos = parent;
                     loop
                 }
                 break
             }
-            rusti::move_val_init(&mut self.data[pos], new);
-        }
-    }
-
-
-    #[cfg(not(stage0))]
-    priv fn siftdown_range(&mut self, mut pos: uint, end: uint) {
-        unsafe {
-            let start = pos;
-            let new = *ptr::to_unsafe_ptr(&self.data[pos]);
-
-            let mut child = 2 * pos + 1;
-            while child < end {
-                let right = child + 1;
-                if right < end && !(self.data[child] > self.data[right]) {
-                    child = right;
-                }
-                let x = replace(&mut self.data[child], rusti::uninit());
-                rusti::move_val_init(&mut self.data[pos], x);
-                pos = child;
-                child = 2 * pos + 1;
-            }
-
-            rusti::move_val_init(&mut self.data[pos], new);
-            self.siftup(start, pos);
+            move_val_init(&mut self.data[pos], new);
         }
     }
 
-    #[cfg(stage0)]
     priv fn siftdown_range(&mut self, mut pos: uint, end: uint) {
         unsafe {
             let start = pos;
-            let new = *ptr::to_unsafe_ptr(&self.data[pos]);
+            let new = replace(&mut self.data[pos], init());
 
             let mut child = 2 * pos + 1;
             while child < end {
@@ -219,13 +167,13 @@ pub impl <T:Ord> PriorityQueue<T> {
                 if right < end && !(self.data[child] > self.data[right]) {
                     child = right;
                 }
-                let x = replace(&mut self.data[child], rusti::init());
-                rusti::move_val_init(&mut self.data[pos], x);
+                let x = replace(&mut self.data[child], init());
+                move_val_init(&mut self.data[pos], x);
                 pos = child;
                 child = 2 * pos + 1;
             }
 
-            rusti::move_val_init(&mut self.data[pos], new);
+            move_val_init(&mut self.data[pos], new);
             self.siftup(start, pos);
         }
     }
diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs
index 0c0f11fc9f0..46f50eafec1 100644
--- a/src/libstd/rc.rs
+++ b/src/libstd/rc.rs
@@ -11,7 +11,11 @@
 /** Task-local reference counted smart pointers
 
 Task-local reference counted smart pointers are an alternative to managed boxes with deterministic
-destruction. They are restricted to containing `Owned` types in order to prevent cycles.
+destruction. They are restricted to containing types that are either `Owned` or `Const` (or both) to
+prevent cycles.
+
+Neither `Rc<T>` or `RcMut<T>` is ever `Owned` and `RcMut<T>` is never `Const`. If `T` is `Const`, a
+cycle cannot be created with `Rc<T>` because there is no way to modify it after creation.
 
 */
 
@@ -30,16 +34,26 @@ pub struct Rc<T> {
     priv ptr: *mut RcBox<T>,
 }
 
-pub impl<T: Owned> Rc<T> {
-    fn new(value: T) -> Rc<T> {
-        unsafe {
-            let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
-            assert!(!ptr::is_null(ptr));
-            intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
-            Rc{ptr: ptr}
-        }
+priv impl<T> Rc<T> {
+    unsafe fn new(value: T) -> Rc<T> {
+        let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
+        assert!(!ptr::is_null(ptr));
+        intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
+        Rc{ptr: ptr}
     }
+}
 
+// FIXME: #6516: should be a static method
+pub fn rc_from_owned<T: Owned>(value: T) -> Rc<T> {
+    unsafe { Rc::new(value) }
+}
+
+// FIXME: #6516: should be a static method
+pub fn rc_from_const<T: Const>(value: T) -> Rc<T> {
+    unsafe { Rc::new(value) }
+}
+
+pub impl<T> Rc<T> {
     #[inline(always)]
     fn borrow<'r>(&'r self) -> &'r T {
         unsafe { cast::copy_lifetime(self, &(*self.ptr).value) }
@@ -48,7 +62,7 @@ pub impl<T: Owned> Rc<T> {
 
 #[unsafe_destructor]
 #[cfg(not(stage0))]
-impl<T: Owned> Drop for Rc<T> {
+impl<T> Drop for Rc<T> {
     fn finalize(&self) {
         unsafe {
             (*self.ptr).count -= 1;
@@ -62,7 +76,7 @@ impl<T: Owned> Drop for Rc<T> {
 
 #[unsafe_destructor]
 #[cfg(stage0)]
-impl<T: Owned> Drop for Rc<T> {
+impl<T> Drop for Rc<T> {
     fn finalize(&self) {
         unsafe {
             (*self.ptr).count -= 1;
@@ -75,7 +89,8 @@ impl<T: Owned> Drop for Rc<T> {
 }
 
 
-impl<T: Owned> Clone for Rc<T> {
+impl<T> Clone for Rc<T> {
+    /// Return a shallow copy of the reference counted pointer.
     #[inline]
     fn clone(&self) -> Rc<T> {
         unsafe {
@@ -85,19 +100,48 @@ impl<T: Owned> Clone for Rc<T> {
     }
 }
 
+impl<T: DeepClone> DeepClone for Rc<T> {
+    /// Return a deep copy of the reference counted pointer.
+    #[inline]
+    fn deep_clone(&self) -> Rc<T> {
+        unsafe { Rc::new(self.borrow().deep_clone()) }
+    }
+}
+
 #[cfg(test)]
 mod test_rc {
     use super::*;
+    use core::cell::Cell;
+
+    #[test]
+    fn test_clone() {
+        let x = rc_from_owned(Cell(5));
+        let y = x.clone();
+        do x.borrow().with_mut_ref |inner| {
+            *inner = 20;
+        }
+        assert_eq!(y.borrow().take(), 20);
+    }
+
+    #[test]
+    fn test_deep_clone() {
+        let x = rc_from_owned(Cell(5));
+        let y = x.deep_clone();
+        do x.borrow().with_mut_ref |inner| {
+            *inner = 20;
+        }
+        assert_eq!(y.borrow().take(), 5);
+    }
 
     #[test]
     fn test_simple() {
-        let x = Rc::new(5);
+        let x = rc_from_const(5);
         assert_eq!(*x.borrow(), 5);
     }
 
     #[test]
-    fn test_clone() {
-        let x = Rc::new(5);
+    fn test_simple_clone() {
+        let x = rc_from_const(5);
         let y = x.clone();
         assert_eq!(*x.borrow(), 5);
         assert_eq!(*y.borrow(), 5);
@@ -105,11 +149,18 @@ mod test_rc {
 
     #[test]
     fn test_destructor() {
-        let x = Rc::new(~5);
+        let x = rc_from_owned(~5);
         assert_eq!(**x.borrow(), 5);
     }
 }
 
+#[abi = "rust-intrinsic"]
+extern "rust-intrinsic" {
+    fn init<T>() -> T;
+    #[cfg(not(stage0))]
+    fn uninit<T>() -> T;
+}
+
 #[deriving(Eq)]
 enum Borrow {
     Mutable,
@@ -130,48 +181,60 @@ pub struct RcMut<T> {
     priv ptr: *mut RcMutBox<T>,
 }
 
-pub impl<T: Owned> RcMut<T> {
-    fn new(value: T) -> RcMut<T> {
-        unsafe {
-            let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
-            assert!(!ptr::is_null(ptr));
-            intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
-            RcMut{ptr: ptr}
-        }
+priv impl<T> RcMut<T> {
+    unsafe fn new(value: T) -> RcMut<T> {
+        let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
+        assert!(!ptr::is_null(ptr));
+        intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
+        RcMut{ptr: ptr}
     }
+}
+
+// FIXME: #6516: should be a static method
+pub fn rc_mut_from_owned<T: Owned>(value: T) -> RcMut<T> {
+    unsafe { RcMut::new(value) }
+}
 
+// FIXME: #6516: should be a static method
+pub fn rc_mut_from_const<T: Const>(value: T) -> RcMut<T> {
+    unsafe { RcMut::new(value) }
+}
+
+pub impl<T> RcMut<T> {
     /// Fails if there is already a mutable borrow of the box
     #[inline]
-    fn with_borrow(&self, f: &fn(&T)) {
+    fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
         unsafe {
             assert!((*self.ptr).borrow != Mutable);
             let previous = (*self.ptr).borrow;
             (*self.ptr).borrow = Immutable;
-            f(&(*self.ptr).value);
+            let res = f(&(*self.ptr).value);
             (*self.ptr).borrow = previous;
+            res
         }
     }
 
     /// Fails if there is already a mutable or immutable borrow of the box
     #[inline]
-    fn with_mut_borrow(&self, f: &fn(&mut T)) {
+    fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
         unsafe {
             assert!((*self.ptr).borrow == Nothing);
             (*self.ptr).borrow = Mutable;
-            f(&mut (*self.ptr).value);
+            let res = f(&mut (*self.ptr).value);
             (*self.ptr).borrow = Nothing;
+            res
         }
     }
 }
 
 #[unsafe_destructor]
 #[cfg(not(stage0))]
-impl<T: Owned> Drop for RcMut<T> {
+impl<T> Drop for RcMut<T> {
     fn finalize(&self) {
         unsafe {
             (*self.ptr).count -= 1;
             if (*self.ptr).count == 0 {
-                util::replace_ptr(self.ptr, intrinsics::uninit());
+                util::replace_ptr(self.ptr, uninit());
                 free(self.ptr as *c_void)
             }
         }
@@ -180,19 +243,20 @@ impl<T: Owned> Drop for RcMut<T> {
 
 #[unsafe_destructor]
 #[cfg(stage0)]
-impl<T: Owned> Drop for RcMut<T> {
+impl<T> Drop for RcMut<T> {
     fn finalize(&self) {
         unsafe {
             (*self.ptr).count -= 1;
             if (*self.ptr).count == 0 {
-                util::replace_ptr(self.ptr, intrinsics::init());
+                util::replace_ptr(self.ptr, init());
                 free(self.ptr as *c_void)
             }
         }
     }
 }
 
-impl<T: Owned> Clone for RcMut<T> {
+impl<T> Clone for RcMut<T> {
+    /// Return a shallow copy of the reference counted pointer.
     #[inline]
     fn clone(&self) -> RcMut<T> {
         unsafe {
@@ -202,13 +266,48 @@ impl<T: Owned> Clone for RcMut<T> {
     }
 }
 
+impl<T: DeepClone> DeepClone for RcMut<T> {
+    /// Return a deep copy of the reference counted pointer.
+    #[inline]
+    fn deep_clone(&self) -> RcMut<T> {
+        do self.with_borrow |x| {
+            // FIXME: #6497: should avoid freeze (slow)
+            unsafe { RcMut::new(x.deep_clone()) }
+        }
+    }
+}
+
 #[cfg(test)]
 mod test_rc_mut {
     use super::*;
 
     #[test]
+    fn test_clone() {
+        let x = rc_mut_from_owned(5);
+        let y = x.clone();
+        do x.with_mut_borrow |value| {
+            *value = 20;
+        }
+        do y.with_borrow |value| {
+            assert_eq!(*value, 20);
+        }
+    }
+
+    #[test]
+    fn test_deep_clone() {
+        let x = rc_mut_from_const(5);
+        let y = x.deep_clone();
+        do x.with_mut_borrow |value| {
+            *value = 20;
+        }
+        do y.with_borrow |value| {
+            assert_eq!(*value, 5);
+        }
+    }
+
+    #[test]
     fn borrow_many() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_owned(5);
         let y = x.clone();
 
         do x.with_borrow |a| {
@@ -224,7 +323,7 @@ mod test_rc_mut {
 
     #[test]
     fn modify() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_const(5);
         let y = x.clone();
 
         do y.with_mut_borrow |a| {
@@ -239,14 +338,14 @@ mod test_rc_mut {
 
     #[test]
     fn release_immutable() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_owned(5);
         do x.with_borrow |_| {}
         do x.with_mut_borrow |_| {}
     }
 
     #[test]
     fn release_mutable() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_const(5);
         do x.with_mut_borrow |_| {}
         do x.with_borrow |_| {}
     }
@@ -254,7 +353,7 @@ mod test_rc_mut {
     #[test]
     #[should_fail]
     fn frozen() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_owned(5);
         let y = x.clone();
 
         do x.with_borrow |_| {
@@ -266,7 +365,7 @@ mod test_rc_mut {
     #[test]
     #[should_fail]
     fn mutable_dupe() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_const(5);
         let y = x.clone();
 
         do x.with_mut_borrow |_| {
@@ -278,7 +377,7 @@ mod test_rc_mut {
     #[test]
     #[should_fail]
     fn mutable_freeze() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_owned(5);
         let y = x.clone();
 
         do x.with_mut_borrow |_| {
@@ -290,7 +389,7 @@ mod test_rc_mut {
     #[test]
     #[should_fail]
     fn restore_freeze() {
-        let x = RcMut::new(5);
+        let x = rc_mut_from_const(5);
         let y = x.clone();
 
         do x.with_borrow |_| {
diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs
index 81152430e78..d15a8fc0136 100644
--- a/src/libstd/rl.rs
+++ b/src/libstd/rl.rs
@@ -28,7 +28,7 @@ pub mod rustrt {
 }
 
 /// Add a line to history
-pub unsafe fn add_history(line: ~str) -> bool {
+pub unsafe fn add_history(line: &str) -> bool {
     do str::as_c_str(line) |buf| {
         rustrt::linenoiseHistoryAdd(buf) == 1 as c_int
     }
@@ -40,21 +40,21 @@ pub unsafe fn set_history_max_len(len: int) -> bool {
 }
 
 /// Save line history to a file
-pub unsafe fn save_history(file: ~str) -> bool {
+pub unsafe fn save_history(file: &str) -> bool {
     do str::as_c_str(file) |buf| {
         rustrt::linenoiseHistorySave(buf) == 1 as c_int
     }
 }
 
 /// Load line history from a file
-pub unsafe fn load_history(file: ~str) -> bool {
+pub unsafe fn load_history(file: &str) -> bool {
     do str::as_c_str(file) |buf| {
         rustrt::linenoiseHistoryLoad(buf) == 1 as c_int
     }
 }
 
 /// Print out a prompt and then wait for input and return it
-pub unsafe fn read(prompt: ~str) -> Option<~str> {
+pub unsafe fn read(prompt: &str) -> Option<~str> {
     do str::as_c_str(prompt) |buf| {
         let line = rustrt::linenoise(buf);
 
diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs
index 2fa12809db6..9afa7262ce4 100644
--- a/src/libstd/rope.rs
+++ b/src/libstd/rope.rs
@@ -164,7 +164,7 @@ pub fn append_rope(left: Rope, right: Rope) -> Rope {
  */
 pub fn concat(v: ~[Rope]) -> Rope {
     //Copy `v` into a mut vector
-    let mut len = vec::len(v);
+    let mut len = v.len();
     if len == 0u { return node::Empty; }
     let mut ropes = vec::from_elem(len, v[0]);
     for uint::range(1u, len) |i| {
@@ -770,7 +770,7 @@ pub mod node {
      */
     pub fn tree_from_forest_destructive(forest: &mut [@Node]) -> @Node {
         let mut i;
-        let mut len = vec::len(forest);
+        let mut len = forest.len();
         while len > 1u {
             i = 0u;
             while i < len - 1u {//Concat nodes 0 with 1, 2 with 3 etc.
diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs
index 4b410ebfdd2..6d8bf20d837 100644
--- a/src/libstd/sha1.rs
+++ b/src/libstd/sha1.rs
@@ -90,8 +90,8 @@ pub fn sha1() -> @Sha1 {
         }
     }
     fn process_msg_block(st: &mut Sha1State) {
-        assert!((vec::len(st.h) == digest_buf_len));
-        assert!((vec::uniq_len(st.work_buf) == work_buf_len));
+        assert!(st.h.len() == digest_buf_len);
+        assert!(vec::uniq_len(st.work_buf) == work_buf_len);
         let mut t: int; // Loop counter
         let w = st.work_buf;
 
@@ -230,7 +230,7 @@ pub fn sha1() -> @Sha1 {
 
     impl Sha1 for Sha1State {
         fn reset(&mut self) {
-            assert!((vec::len(self.h) == digest_buf_len));
+            assert!(self.h.len() == digest_buf_len);
             self.len_low = 0u32;
             self.len_high = 0u32;
             self.msg_block_idx = 0u;
diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs
index 876eb716a38..0d94a1830a6 100644
--- a/src/libstd/sort.rs
+++ b/src/libstd/sort.rs
@@ -581,7 +581,7 @@ impl<T:Copy + Ord> MergeState<T> {
             shift_vec(array, dest, c2, len2);
             swap(&mut array[dest+len2], &mut tmp[c1]);
         } else if len1 == 0 {
-            fail!(~"Comparison violates its contract!");
+            fail!("Comparison violates its contract!");
         } else {
             assert!(len2 == 0);
             assert!(len1 > 1);
@@ -703,7 +703,7 @@ impl<T:Copy + Ord> MergeState<T> {
             shift_vec(array, dest+1, c1+1, len1);
             swap(&mut array[dest], &mut tmp[c2]);
         } else if len2 == 0 {
-            fail!(~"Comparison violates its contract!");
+            fail!("Comparison violates its contract!");
         } else {
             assert!(len1 == 0);
             assert!(len2 != 0);
@@ -949,7 +949,7 @@ mod test_tim_sort {
         fn lt(&self, other: &CVal) -> bool {
             let mut rng = rand::rng();
             if rng.gen::<float>() > 0.995 {
-                fail!(~"It's happening!!!");
+                fail!("It's happening!!!");
             }
             (*self).val < other.val
         }
@@ -1004,7 +1004,7 @@ mod test_tim_sort {
         };
 
         tim_sort(arr);
-        fail!(~"Guarantee the fail");
+        fail!("Guarantee the fail");
     }
 
     struct DVal { val: uint }
@@ -1065,7 +1065,7 @@ mod big_tests {
         fn isSorted<T:Ord>(arr: &[T]) {
             for uint::range(0, arr.len()-1) |i| {
                 if arr[i] > arr[i+1] {
-                    fail!(~"Array not sorted");
+                    fail!("Array not sorted");
                 }
             }
         }
@@ -1136,7 +1136,7 @@ mod big_tests {
         fn isSorted<T:Ord>(arr: &[@T]) {
             for uint::range(0, arr.len()-1) |i| {
                 if arr[i] > arr[i+1] {
-                    fail!(~"Array not sorted");
+                    fail!("Array not sorted");
                 }
             }
         }
@@ -1219,7 +1219,7 @@ mod big_tests {
                         local_data::local_data_set(self.key, @(y+1));
                     }
                 }
-                _ => fail!(~"Expected key to work"),
+                _ => fail!("Expected key to work"),
             }
         }
     }
diff --git a/src/libstd/sort_stage0.rs b/src/libstd/sort_stage0.rs
index 00bd325dd0c..270f7196d29 100644
--- a/src/libstd/sort_stage0.rs
+++ b/src/libstd/sort_stage0.rs
@@ -577,7 +577,7 @@ impl<T:Copy + Ord> MergeState<T> {
             copy_vec(array, dest, array, c2, len2);
             util::swap(&mut array[dest+len2], &mut tmp[c1]);
         } else if len1 == 0 {
-            fail!(~"Comparison violates its contract!");
+            fail!("Comparison violates its contract!");
         } else {
             assert!(len2 == 0);
             assert!(len1 > 1);
@@ -699,7 +699,7 @@ impl<T:Copy + Ord> MergeState<T> {
             copy_vec(array, dest+1, array, c1+1, len1);
             util::swap(&mut array[dest], &mut tmp[c2]);
         } else if len2 == 0 {
-            fail!(~"Comparison violates its contract!");
+            fail!("Comparison violates its contract!");
         } else {
             assert!(len1 == 0);
             assert!(len2 != 0);
@@ -941,7 +941,7 @@ mod test_tim_sort {
     impl Ord for CVal {
         fn lt(&self, other: &CVal) -> bool {
             let rng = rand::rng();
-            if rng.gen::<float>() > 0.995 { fail!(~"It's happening!!!"); }
+            if rng.gen::<float>() > 0.995 { fail!("It's happening!!!"); }
             (*self).val < other.val
         }
         fn le(&self, other: &CVal) -> bool { (*self).val <= other.val }
@@ -995,7 +995,7 @@ mod test_tim_sort {
         };
 
         tim_sort(arr);
-        fail!(~"Guarantee the fail");
+        fail!("Guarantee the fail");
     }
 
     struct DVal { val: uint }
@@ -1056,7 +1056,7 @@ mod big_tests {
         fn isSorted<T:Ord>(arr: &const [T]) {
             for uint::range(0, arr.len()-1) |i| {
                 if arr[i] > arr[i+1] {
-                    fail!(~"Array not sorted");
+                    fail!("Array not sorted");
                 }
             }
         }
@@ -1127,7 +1127,7 @@ mod big_tests {
         fn isSorted<T:Ord>(arr: &const [@T]) {
             for uint::range(0, arr.len()-1) |i| {
                 if arr[i] > arr[i+1] {
-                    fail!(~"Array not sorted");
+                    fail!("Array not sorted");
                 }
             }
         }
@@ -1210,7 +1210,7 @@ mod big_tests {
                         local_data::local_data_set(self.key, @(y+1));
                     }
                 }
-                _ => fail!(~"Expected key to work"),
+                _ => fail!("Expected key to work"),
             }
         }
     }
diff --git a/src/libstd/std.rc b/src/libstd/std.rc
index 915aab59a71..d29791449b6 100644
--- a/src/libstd/std.rc
+++ b/src/libstd/std.rc
@@ -63,6 +63,7 @@ pub mod flatpipes;
 
 pub mod bitv;
 pub mod deque;
+#[cfg(not(stage0))]
 pub mod fun_treemap;
 pub mod list;
 pub mod priority_queue;
diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs
index 17d051518a9..449edacad32 100644
--- a/src/libstd/sync.rs
+++ b/src/libstd/sync.rs
@@ -15,11 +15,10 @@
  * in std.
  */
 
-use core::unstable::{Exclusive, exclusive};
+use core::unstable::sync::{Exclusive, exclusive};
 use core::ptr;
 use core::task;
 use core::util;
-use core::vec;
 
 /****************************************************************************
  * Internals
@@ -220,7 +219,7 @@ pub impl<'self> Condvar<'self> {
             do task::unkillable {
                 // Release lock, 'atomically' enqueuing ourselves in so doing.
                 do (**self.sem).with |state| {
-                    if condvar_id < vec::len(state.blocked) {
+                    if condvar_id < state.blocked.len() {
                         // Drop the lock.
                         state.count += 1;
                         if state.count <= 0 {
@@ -230,7 +229,7 @@ pub impl<'self> Condvar<'self> {
                         let SignalEnd = SignalEnd.swap_unwrap();
                         state.blocked[condvar_id].tail.send(SignalEnd);
                     } else {
-                        out_of_bounds = Some(vec::len(state.blocked));
+                        out_of_bounds = Some(state.blocked.len());
                     }
                 }
 
@@ -285,10 +284,10 @@ pub impl<'self> Condvar<'self> {
         let mut out_of_bounds = None;
         let mut result = false;
         do (**self.sem).with |state| {
-            if condvar_id < vec::len(state.blocked) {
+            if condvar_id < state.blocked.len() {
                 result = signal_waitqueue(&state.blocked[condvar_id]);
             } else {
-                out_of_bounds = Some(vec::len(state.blocked));
+                out_of_bounds = Some(state.blocked.len());
             }
         }
         do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") {
@@ -304,14 +303,14 @@ pub impl<'self> Condvar<'self> {
         let mut out_of_bounds = None;
         let mut queue = None;
         do (**self.sem).with |state| {
-            if condvar_id < vec::len(state.blocked) {
+            if condvar_id < state.blocked.len() {
                 // To avoid :broadcast_heavy, we make a new waitqueue,
                 // swap it out with the old one, and broadcast on the
                 // old one outside of the little-lock.
                 queue = Some(util::replace(&mut state.blocked[condvar_id],
                                            new_waitqueue()));
             } else {
-                out_of_bounds = Some(vec::len(state.blocked));
+                out_of_bounds = Some(state.blocked.len());
             }
         }
         do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") {
@@ -329,11 +328,9 @@ fn check_cvar_bounds<U>(out_of_bounds: Option<uint>, id: uint, act: &str,
                         blk: &fn() -> U) -> U {
     match out_of_bounds {
         Some(0) =>
-            fail!(fmt!("%s with illegal ID %u - this lock has no condvars!",
-                      act, id)),
+            fail!("%s with illegal ID %u - this lock has no condvars!", act, id),
         Some(length) =>
-            fail!(fmt!("%s with illegal ID %u - ID must be less than %u",
-                      act, id, length)),
+            fail!("%s with illegal ID %u - ID must be less than %u", act, id, length),
         None => blk()
     }
 }
@@ -578,7 +575,7 @@ pub impl RWlock {
                      token: RWlockWriteMode<'a>)
                   -> RWlockReadMode<'a> {
         if !ptr::ref_eq(self, token.lock) {
-            fail!(~"Can't downgrade() with a different rwlock's write_mode!");
+            fail!("Can't downgrade() with a different rwlock's write_mode!");
         }
         unsafe {
             do task::unkillable {
diff --git a/src/libstd/test.rs b/src/libstd/test.rs
index 71cbc0d7a6a..b2f73df316d 100644
--- a/src/libstd/test.rs
+++ b/src/libstd/test.rs
@@ -89,7 +89,7 @@ pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
           either::Left(o) => o,
           either::Right(m) => fail!(m)
         };
-    if !run_tests_console(&opts, tests) { fail!(~"Some tests failed"); }
+    if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
 }
 
 // A variant optimized for invocation with a static test vector.
@@ -109,7 +109,7 @@ pub fn test_main_static(args: &[~str], tests: &[TestDescAndFn]) {
             TestDescAndFn { testfn: StaticBenchFn(f), desc: copy t.desc },
 
             _ => {
-                fail!(~"non-static tests passed to test::test_main_static");
+                fail!("non-static tests passed to test::test_main_static");
             }
         }
     };
@@ -144,7 +144,7 @@ pub fn parse_opts(args: &[~str]) -> OptRes {
         };
 
     let filter =
-        if vec::len(matches.free) > 0 {
+        if matches.free.len() > 0 {
             option::Some(copy (matches).free[0])
         } else { option::None };
 
@@ -250,7 +250,7 @@ pub fn run_tests_console(opts: &TestOpts,
                                                   io::Truncate]) {
           result::Ok(w) => Some(w),
           result::Err(ref s) => {
-              fail!(fmt!("can't open output file: %s", *s))
+              fail!("can't open output file: %s", *s)
           }
         },
         None => None
@@ -849,7 +849,7 @@ mod tests {
         let args = ~[~"progname", ~"filter"];
         let opts = match parse_opts(args) {
           either::Left(copy o) => o,
-          _ => fail!(~"Malformed arg in first_free_arg_should_be_a_filter")
+          _ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
         };
         assert!("filter" == (copy opts.filter).get());
     }
@@ -859,7 +859,7 @@ mod tests {
         let args = ~[~"progname", ~"filter", ~"--ignored"];
         let opts = match parse_opts(args) {
           either::Left(copy o) => o,
-          _ => fail!(~"Malformed arg in parse_ignored_flag")
+          _ => fail!("Malformed arg in parse_ignored_flag")
         };
         assert!((opts.run_ignored));
     }
@@ -901,7 +901,7 @@ mod tests {
         ];
         let filtered = filter_tests(&opts, tests);
 
-        assert!((vec::len(filtered) == 1));
+        assert!(filtered.len() == 1);
         assert!((filtered[0].desc.name.to_str() == ~"1"));
         assert!((filtered[0].desc.ignore == false));
     }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index e731f679221..202b96f9797 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -29,9 +29,7 @@ pub mod rustrt {
 }
 
 /// A record specifying a time value in seconds and nanoseconds.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct Timespec { sec: i64, nsec: i32 }
 
 /*
@@ -100,9 +98,7 @@ pub fn tzset() {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct Tm {
     tm_sec: i32, // seconds after the minute ~[0-60]
     tm_min: i32, // minutes after the hour ~[0-59]
diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs
index 234982a12bc..e9fd0414244 100644
--- a/src/libstd/timer.rs
+++ b/src/libstd/timer.rs
@@ -63,13 +63,11 @@ pub fn delayed_send<T:Owned>(iotask: &IoTask,
                 } else {
                     let error_msg = uv::ll::get_last_err_info(
                         loop_ptr);
-                    fail!(~"timer::delayed_send() start failed: " +
-                        error_msg);
+                    fail!("timer::delayed_send() start failed: %s", error_msg);
                 }
             } else {
                 let error_msg = uv::ll::get_last_err_info(loop_ptr);
-                fail!(~"timer::delayed_send() init failed: " +
-                    error_msg);
+                fail!("timer::delayed_send() init failed: %s", error_msg);
             }
         }
     };
@@ -158,7 +156,7 @@ extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t, status: libc::c_int) {
         } else {
             let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
             let error_msg = uv::ll::get_last_err_info(loop_ptr);
-            fail!(~"timer::sleep() init failed: "+error_msg);
+            fail!("timer::sleep() init failed: %s", error_msg);
         }
     }
 }
diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs
index 2b39458d32d..e0ee3a1ee01 100644
--- a/src/libstd/treemap.rs
+++ b/src/libstd/treemap.rs
@@ -716,7 +716,7 @@ pub impl<K: TotalOrd, V> TreeNode<K, V> {
 #[cfg(stage0)]
 fn each<'r, K: TotalOrd, V>(_: &'r Option<~TreeNode<K, V>>,
                             _: &fn(&'r K, &'r V) -> bool) -> bool {
-    fail!(~"don't use me in stage0!")
+    fail!("don't use me in stage0!")
 }
 #[cfg(not(stage0))]
 fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
@@ -728,7 +728,7 @@ fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
 #[cfg(stage0)]
 fn each_reverse<'r, K: TotalOrd, V>(_: &'r Option<~TreeNode<K, V>>,
                                     _: &fn(&'r K, &'r V) -> bool) -> bool {
-    fail!(~"don't use me in stage0!")
+    fail!("don't use me in stage0!")
 }
 #[cfg(not(stage0))]
 fn each_reverse<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs
index 97df64d5266..c7b5d9eef72 100644
--- a/src/libstd/uv_global_loop.rs
+++ b/src/libstd/uv_global_loop.rs
@@ -180,11 +180,11 @@ mod test {
                                                            simple_timer_cb,
                                                            1u, 0u);
                         if(start_status != 0i32) {
-                            fail!(~"failure on ll::timer_start()");
+                            fail!("failure on ll::timer_start()");
                         }
                     }
                     else {
-                        fail!(~"failure on ll::timer_init()");
+                        fail!("failure on ll::timer_init()");
                     }
                 }
             };
diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs
index 5cccf2c348d..37052f7d1b7 100644
--- a/src/libstd/uv_ll.rs
+++ b/src/libstd/uv_ll.rs
@@ -730,8 +730,7 @@ pub mod uv_ll_struct_stubgen {
 }
 
 #[nolink]
-extern mod rustrt {
-
+extern {
     // libuv public API
     unsafe fn rust_uv_loop_new() -> *libc::c_void;
     unsafe fn rust_uv_loop_delete(lp: *libc::c_void);
@@ -884,49 +883,49 @@ extern mod rustrt {
 }
 
 pub unsafe fn loop_new() -> *libc::c_void {
-    return rustrt::rust_uv_loop_new();
+    return rust_uv_loop_new();
 }
 
 pub unsafe fn loop_delete(loop_handle: *libc::c_void) {
-    rustrt::rust_uv_loop_delete(loop_handle);
+    rust_uv_loop_delete(loop_handle);
 }
 
 pub unsafe fn run(loop_handle: *libc::c_void) {
-    rustrt::rust_uv_run(loop_handle);
+    rust_uv_run(loop_handle);
 }
 
 pub unsafe fn close<T>(handle: *T, cb: *u8) {
-    rustrt::rust_uv_close(handle as *libc::c_void, cb);
+    rust_uv_close(handle as *libc::c_void, cb);
 }
 
 pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) {
-    rustrt::rust_uv_walk(loop_handle, cb, arg);
+    rust_uv_walk(loop_handle, cb, arg);
 }
 
 pub unsafe fn idle_new() -> *uv_idle_t {
-    rustrt::rust_uv_idle_new()
+    rust_uv_idle_new()
 }
 
 pub unsafe fn idle_delete(handle: *uv_idle_t) {
-    rustrt::rust_uv_idle_delete(handle)
+    rust_uv_idle_delete(handle)
 }
 
 pub unsafe fn idle_init(loop_handle: *uv_loop_t,
                         handle: *uv_idle_t) -> libc::c_int {
-    rustrt::rust_uv_idle_init(loop_handle, handle)
+    rust_uv_idle_init(loop_handle, handle)
 }
 
 pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int {
-    rustrt::rust_uv_idle_start(handle, cb)
+    rust_uv_idle_start(handle, cb)
 }
 
 pub unsafe fn idle_stop(handle: *uv_idle_t) -> libc::c_int {
-    rustrt::rust_uv_idle_stop(handle)
+    rust_uv_idle_stop(handle)
 }
 
 pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t)
     -> libc::c_int {
-    return rustrt::rust_uv_tcp_init(loop_handle, handle);
+    return rust_uv_tcp_init(loop_handle, handle);
 }
 // FIXME ref #2064
 pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
@@ -934,7 +933,7 @@ pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
                       addr_ptr: *sockaddr_in,
                       after_connect_cb: *u8)
 -> libc::c_int {
-    return rustrt::rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr,
+    return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr,
                                     after_connect_cb, addr_ptr);
 }
 // FIXME ref #2064
@@ -943,40 +942,40 @@ pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t,
                       addr_ptr: *sockaddr_in6,
                       after_connect_cb: *u8)
 -> libc::c_int {
-    return rustrt::rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr,
+    return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr,
                                     after_connect_cb, addr_ptr);
 }
 // FIXME ref #2064
 pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t,
                    addr_ptr: *sockaddr_in) -> libc::c_int {
-    return rustrt::rust_uv_tcp_bind(tcp_server_ptr,
+    return rust_uv_tcp_bind(tcp_server_ptr,
                                  addr_ptr);
 }
 // FIXME ref #2064
 pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t,
                    addr_ptr: *sockaddr_in6) -> libc::c_int {
-    return rustrt::rust_uv_tcp_bind6(tcp_server_ptr,
+    return rust_uv_tcp_bind6(tcp_server_ptr,
                                  addr_ptr);
 }
 
 pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
                               name: *sockaddr_in) -> libc::c_int {
-    return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name);
+    return rust_uv_tcp_getpeername(tcp_handle_ptr, name);
 }
 
 pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
                                name: *sockaddr_in6) ->libc::c_int {
-    return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
+    return rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
 }
 
 pub unsafe fn listen<T>(stream: *T, backlog: libc::c_int,
                  cb: *u8) -> libc::c_int {
-    return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb);
+    return rust_uv_listen(stream as *libc::c_void, backlog, cb);
 }
 
 pub unsafe fn accept(server: *libc::c_void, client: *libc::c_void)
     -> libc::c_int {
-    return rustrt::rust_uv_accept(server as *libc::c_void,
+    return rust_uv_accept(server as *libc::c_void,
                                client as *libc::c_void);
 }
 
@@ -984,57 +983,57 @@ pub unsafe fn write<T>(req: *uv_write_t, stream: *T,
          buf_in: *~[uv_buf_t], cb: *u8) -> libc::c_int {
     let buf_ptr = vec::raw::to_ptr(*buf_in);
     let buf_cnt = vec::len(*buf_in) as i32;
-    return rustrt::rust_uv_write(req as *libc::c_void,
+    return rust_uv_write(req as *libc::c_void,
                               stream as *libc::c_void,
                               buf_ptr, buf_cnt, cb);
 }
 pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8,
                      on_read: *u8) -> libc::c_int {
-    return rustrt::rust_uv_read_start(stream as *libc::c_void,
+    return rust_uv_read_start(stream as *libc::c_void,
                                    on_alloc, on_read);
 }
 
 pub unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int {
-    return rustrt::rust_uv_read_stop(stream as *libc::c_void);
+    return rust_uv_read_stop(stream as *libc::c_void);
 }
 
 pub unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t {
-    return rustrt::rust_uv_last_error(loop_handle);
+    return rust_uv_last_error(loop_handle);
 }
 
 pub unsafe fn strerror(err: *uv_err_t) -> *libc::c_char {
-    return rustrt::rust_uv_strerror(err);
+    return rust_uv_strerror(err);
 }
 pub unsafe fn err_name(err: *uv_err_t) -> *libc::c_char {
-    return rustrt::rust_uv_err_name(err);
+    return rust_uv_err_name(err);
 }
 
 pub unsafe fn async_init(loop_handle: *libc::c_void,
                      async_handle: *uv_async_t,
                      cb: *u8) -> libc::c_int {
-    return rustrt::rust_uv_async_init(loop_handle,
+    return rust_uv_async_init(loop_handle,
                                    async_handle,
                                    cb);
 }
 
 pub unsafe fn async_send(async_handle: *uv_async_t) {
-    return rustrt::rust_uv_async_send(async_handle);
+    return rust_uv_async_send(async_handle);
 }
 pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
     let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t };
     let out_buf_ptr: *uv_buf_t = &out_buf;
-    rustrt::rust_uv_buf_init(out_buf_ptr, input, len as size_t);
+    rust_uv_buf_init(out_buf_ptr, input, len as size_t);
     return out_buf;
 }
 pub unsafe fn ip4_addr(ip: &str, port: int) -> sockaddr_in {
     do str::as_c_str(ip) |ip_buf| {
-        rustrt::rust_uv_ip4_addr(ip_buf as *u8,
+        rust_uv_ip4_addr(ip_buf as *u8,
                                  port as libc::c_int)
     }
 }
 pub unsafe fn ip6_addr(ip: &str, port: int) -> sockaddr_in6 {
     do str::as_c_str(ip) |ip_buf| {
-        rustrt::rust_uv_ip6_addr(ip_buf as *u8,
+        rust_uv_ip6_addr(ip_buf as *u8,
                                  port as libc::c_int)
     }
 }
@@ -1043,7 +1042,7 @@ pub unsafe fn ip4_name(src: &sockaddr_in) -> ~str {
     let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
                      0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8];
     do vec::as_imm_buf(dst) |dst_buf, size| {
-        rustrt::rust_uv_ip4_name(to_unsafe_ptr(src),
+        rust_uv_ip4_name(to_unsafe_ptr(src),
                                  dst_buf, size as libc::size_t);
         // seems that checking the result of uv_ip4_name
         // doesn't work too well..
@@ -1064,7 +1063,7 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str {
                        0u8,0u8,0u8,0u8,0u8,0u8];
     do vec::as_imm_buf(dst) |dst_buf, size| {
         let src_unsafe_ptr = to_unsafe_ptr(src);
-        let result = rustrt::rust_uv_ip6_name(src_unsafe_ptr,
+        let result = rust_uv_ip6_name(src_unsafe_ptr,
                                               dst_buf, size as libc::size_t);
         match result {
           0i32 => str::raw::from_buf(dst_buf),
@@ -1073,23 +1072,23 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str {
     }
 }
 pub unsafe fn ip4_port(src: &sockaddr_in) -> uint {
-    rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint
+    rust_uv_ip4_port(to_unsafe_ptr(src)) as uint
 }
 pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint {
-    rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint
+    rust_uv_ip6_port(to_unsafe_ptr(src)) as uint
 }
 
 pub unsafe fn timer_init(loop_ptr: *libc::c_void,
                      timer_ptr: *uv_timer_t) -> libc::c_int {
-    return rustrt::rust_uv_timer_init(loop_ptr, timer_ptr);
+    return rust_uv_timer_init(loop_ptr, timer_ptr);
 }
 pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
                       repeat: uint) -> libc::c_int {
-    return rustrt::rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint,
+    return rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint,
                                     repeat as libc::c_uint);
 }
 pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int {
-    return rustrt::rust_uv_timer_stop(timer_ptr);
+    return rust_uv_timer_stop(timer_ptr);
 }
 pub unsafe fn getaddrinfo(loop_ptr: *libc::c_void,
                            handle: *uv_getaddrinfo_t,
@@ -1097,7 +1096,7 @@ pub unsafe fn getaddrinfo(loop_ptr: *libc::c_void,
                            node_name_ptr: *u8,
                            service_name_ptr: *u8,
                            hints: *addrinfo) -> libc::c_int {
-    rustrt::rust_uv_getaddrinfo(loop_ptr,
+    rust_uv_getaddrinfo(loop_ptr,
                            handle,
                            cb,
                            node_name_ptr,
@@ -1105,7 +1104,7 @@ pub unsafe fn getaddrinfo(loop_ptr: *libc::c_void,
                            hints)
 }
 pub unsafe fn freeaddrinfo(res: *addrinfo) {
-    rustrt::rust_uv_freeaddrinfo(res);
+    rust_uv_freeaddrinfo(res);
 }
 
 // libuv struct initializers
@@ -1131,53 +1130,53 @@ pub fn getaddrinfo_t() -> uv_getaddrinfo_t {
 // data access helpers
 pub unsafe fn get_loop_for_uv_handle<T>(handle: *T)
     -> *libc::c_void {
-    return rustrt::rust_uv_get_loop_for_uv_handle(handle as *libc::c_void);
+    return rust_uv_get_loop_for_uv_handle(handle as *libc::c_void);
 }
 pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t)
     -> *uv_stream_t {
-    return rustrt::rust_uv_get_stream_handle_from_connect_req(
+    return rust_uv_get_stream_handle_from_connect_req(
         connect);
 }
 pub unsafe fn get_stream_handle_from_write_req(
     write_req: *uv_write_t)
     -> *uv_stream_t {
-    return rustrt::rust_uv_get_stream_handle_from_write_req(
+    return rust_uv_get_stream_handle_from_write_req(
         write_req);
 }
 pub unsafe fn get_data_for_uv_loop(loop_ptr: *libc::c_void) -> *libc::c_void {
-    rustrt::rust_uv_get_data_for_uv_loop(loop_ptr)
+    rust_uv_get_data_for_uv_loop(loop_ptr)
 }
 pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void,
                                    data: *libc::c_void) {
-    rustrt::rust_uv_set_data_for_uv_loop(loop_ptr, data);
+    rust_uv_set_data_for_uv_loop(loop_ptr, data);
 }
 pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *libc::c_void {
-    return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void);
+    return rust_uv_get_data_for_uv_handle(handle as *libc::c_void);
 }
 pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) {
-    rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void,
+    rust_uv_set_data_for_uv_handle(handle as *libc::c_void,
                                            data as *libc::c_void);
 }
 pub unsafe fn get_data_for_req<T>(req: *T) -> *libc::c_void {
-    return rustrt::rust_uv_get_data_for_req(req as *libc::c_void);
+    return rust_uv_get_data_for_req(req as *libc::c_void);
 }
 pub unsafe fn set_data_for_req<T, U>(req: *T,
                     data: *U) {
-    rustrt::rust_uv_set_data_for_req(req as *libc::c_void,
+    rust_uv_set_data_for_req(req as *libc::c_void,
                                      data as *libc::c_void);
 }
 pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
-    return rustrt::rust_uv_get_base_from_buf(buf);
+    return rust_uv_get_base_from_buf(buf);
 }
 pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t {
-    return rustrt::rust_uv_get_len_from_buf(buf);
+    return rust_uv_get_len_from_buf(buf);
 }
 pub unsafe fn malloc_buf_base_of(suggested_size: libc::size_t)
     -> *u8 {
-    return rustrt::rust_uv_malloc_buf_base_of(suggested_size);
+    return rust_uv_malloc_buf_base_of(suggested_size);
 }
 pub unsafe fn free_base_of_buf(buf: uv_buf_t) {
-    rustrt::rust_uv_free_base_of_buf(buf);
+    rust_uv_free_base_of_buf(buf);
 }
 
 pub unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> ~str {
@@ -1203,22 +1202,22 @@ pub struct uv_err_data {
 }
 
 pub unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool {
-    rustrt::rust_uv_is_ipv4_addrinfo(input)
+    rust_uv_is_ipv4_addrinfo(input)
 }
 pub unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool {
-    rustrt::rust_uv_is_ipv6_addrinfo(input)
+    rust_uv_is_ipv6_addrinfo(input)
 }
 pub unsafe fn get_INADDR_NONE() -> u32 {
-    rustrt::rust_uv_helper_get_INADDR_NONE()
+    rust_uv_helper_get_INADDR_NONE()
 }
 pub unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo {
-    rustrt::rust_uv_get_next_addrinfo(input)
+    rust_uv_get_next_addrinfo(input)
 }
 pub unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in {
-    rustrt::rust_uv_addrinfo_as_sockaddr_in(input)
+    rust_uv_addrinfo_as_sockaddr_in(input)
 }
 pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 {
-    rustrt::rust_uv_addrinfo_as_sockaddr_in6(input)
+    rust_uv_addrinfo_as_sockaddr_in6(input)
 }
 
 #[cfg(test)]
@@ -1359,7 +1358,7 @@ mod test {
             let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes);
             debug!("req_msg ptr: %u", req_msg_ptr as uint);
             let req_msg = ~[
-                buf_init(req_msg_ptr, vec::len(req_str_bytes))
+                buf_init(req_msg_ptr, req_str_bytes.len())
             ];
             // this is the enclosing record, we'll pass a ptr to
             // this to C..
@@ -1792,7 +1791,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_tcp_t>(
                 ~"uv_tcp_t",
-                super::rustrt::rust_uv_helper_uv_tcp_t_size()
+                super::rust_uv_helper_uv_tcp_t_size()
             );
         }
     }
@@ -1801,7 +1800,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_connect_t>(
                 ~"uv_connect_t",
-                super::rustrt::rust_uv_helper_uv_connect_t_size()
+                super::rust_uv_helper_uv_connect_t_size()
             );
         }
     }
@@ -1810,7 +1809,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_buf_t>(
                 ~"uv_buf_t",
-                super::rustrt::rust_uv_helper_uv_buf_t_size()
+                super::rust_uv_helper_uv_buf_t_size()
             );
         }
     }
@@ -1819,7 +1818,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_write_t>(
                 ~"uv_write_t",
-                super::rustrt::rust_uv_helper_uv_write_t_size()
+                super::rust_uv_helper_uv_write_t_size()
             );
         }
     }
@@ -1829,7 +1828,7 @@ mod test {
         unsafe {
             struct_size_check_common::<sockaddr_in>(
                 ~"sockaddr_in",
-                super::rustrt::rust_uv_helper_sockaddr_in_size()
+                super::rust_uv_helper_sockaddr_in_size()
             );
         }
     }
@@ -1837,7 +1836,7 @@ mod test {
     fn test_uv_ll_struct_size_sockaddr_in6() {
         unsafe {
             let foreign_handle_size =
-                super::rustrt::rust_uv_helper_sockaddr_in6_size();
+                super::rust_uv_helper_sockaddr_in6_size();
             let rust_handle_size = sys::size_of::<sockaddr_in6>();
             let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u",
                               foreign_handle_size as uint, rust_handle_size);
@@ -1856,7 +1855,7 @@ mod test {
     fn test_uv_ll_struct_size_addr_in() {
         unsafe {
             let foreign_handle_size =
-                super::rustrt::rust_uv_helper_addr_in_size();
+                super::rust_uv_helper_addr_in_size();
             let rust_handle_size = sys::size_of::<addr_in>();
             let output = fmt!("addr_in -- foreign: %u rust: %u",
                               foreign_handle_size as uint, rust_handle_size);
@@ -1872,7 +1871,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_async_t>(
                 ~"uv_async_t",
-                super::rustrt::rust_uv_helper_uv_async_t_size()
+                super::rust_uv_helper_uv_async_t_size()
             );
         }
     }
@@ -1882,7 +1881,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_timer_t>(
                 ~"uv_timer_t",
-                super::rustrt::rust_uv_helper_uv_timer_t_size()
+                super::rust_uv_helper_uv_timer_t_size()
             );
         }
     }
@@ -1893,7 +1892,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_getaddrinfo_t>(
                 ~"uv_getaddrinfo_t",
-                super::rustrt::rust_uv_helper_uv_getaddrinfo_t_size()
+                super::rust_uv_helper_uv_getaddrinfo_t_size()
             );
         }
     }
@@ -1904,7 +1903,7 @@ mod test {
         unsafe {
             struct_size_check_common::<uv_timer_t>(
                 ~"addrinfo",
-                super::rustrt::rust_uv_helper_uv_timer_t_size()
+                super::rust_uv_helper_uv_timer_t_size()
             );
         }
     }
diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs
index a9e4ec50c7c..f173df60df8 100644
--- a/src/libstd/workcache.rs
+++ b/src/libstd/workcache.rs
@@ -92,9 +92,7 @@ use core::util::replace;
 *
 */
 
-#[deriving(Eq)]
-#[auto_encode]
-#[auto_decode]
+#[deriving(Eq, Encodable, Decodable)]
 struct WorkKey {
     kind: ~str,
     name: ~str
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index f266b8871a2..1b166dcf366 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -58,9 +58,7 @@ enum AbiArchitecture {
     Archs(u32)  // Multiple architectures (bitset)
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct AbiSet {
     priv bits: u32   // each bit represents one of the abis below
 }
@@ -338,7 +336,7 @@ fn cannot_combine(n: Abi, m: Abi) {
                          (m == a && n == b));
         }
         None => {
-            fail!(~"Invalid match not detected");
+            fail!("Invalid match not detected");
         }
     }
 }
@@ -350,7 +348,7 @@ fn can_combine(n: Abi, m: Abi) {
     set.add(m);
     match set.check_valid() {
         Some((_, _)) => {
-            fail!(~"Valid match declared invalid");
+            fail!("Valid match declared invalid");
         }
         None => {}
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 5daa0de2272..dcbbd7ab531 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -17,6 +17,7 @@ use opt_vec::OptVec;
 use core::cast;
 use core::option::{None, Option, Some};
 use core::to_bytes;
+use core::to_bytes::IterBytes;
 use core::to_str::ToStr;
 use std::serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -46,9 +47,7 @@ pub type SyntaxContext = uint;
 pub type SCTable = ~[SyntaxContext_];
 pub static empty_ctxt : uint = 0;
 
-#[deriving(Eq)]
-#[auto_encode]
-#[auto_decode]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum SyntaxContext_ {
     EmptyCtxt,
     Mark (Mrk,SyntaxContext),
@@ -74,7 +73,7 @@ impl<S:Encoder> Encodable<S> for ident {
         unsafe {
             let intr =
                 match local_data::local_data_get(interner_key!()) {
-                    None => fail!(~"encode: TLS interner not set up"),
+                    None => fail!("encode: TLS interner not set up"),
                     Some(intr) => intr
                 };
 
@@ -88,7 +87,7 @@ impl<D:Decoder> Decodable<D> for ident {
         let intr = match unsafe {
             local_data::local_data_get(interner_key!())
         } {
-            None => fail!(~"decode: TLS interner not set up"),
+            None => fail!("decode: TLS interner not set up"),
             Some(intr) => intr
         };
 
@@ -98,12 +97,14 @@ impl<D:Decoder> Decodable<D> for ident {
 
 #[cfg(stage0)]
 impl to_bytes::IterBytes for ident {
+    #[inline(always)]
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
         self.repr.iter_bytes(lsb0, f)
     }
 }
 #[cfg(not(stage0))]
 impl to_bytes::IterBytes for ident {
+    #[inline(always)]
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
         self.repr.iter_bytes(lsb0, f)
     }
@@ -112,22 +113,32 @@ impl to_bytes::IterBytes for ident {
 // Functions may or may not have names.
 pub type fn_ident = Option<ident>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct Lifetime {
     id: node_id,
     span: span,
     ident: ident
 }
 
+#[cfg(stage0)]
+impl to_bytes::IterBytes for Lifetime {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
+        to_bytes::iter_bytes_3(&self.id, &self.span, &self.ident, lsb0, f)
+    }
+}
+
+#[cfg(not(stage0))]
+impl to_bytes::IterBytes for Lifetime {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
+        to_bytes::iter_bytes_3(&self.id, &self.span, &self.ident, lsb0, f)
+    }
+}
+
 // a "Path" is essentially Rust's notion of a name;
 // for instance: core::cmp::Eq  .  It's represented
 // as a sequence of identifiers, along with a bunch
 // of supporting information.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct Path {
     span: span,
     global: bool,
@@ -140,9 +151,7 @@ pub type crate_num = int;
 
 pub type node_id = int;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct def_id {
     crate: crate_num,
     node: node_id,
@@ -151,9 +160,7 @@ pub struct def_id {
 pub static local_crate: crate_num = 0;
 pub static crate_node_id: node_id = 0;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 // The AST represents all type param bounds as types.
 // typeck::collect::compute_bounds matches these against
 // the "special" built-in traits (see middle::lang_items) and
@@ -163,18 +170,14 @@ pub enum TyParamBound {
     RegionTyParamBound
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct TyParam {
     ident: ident,
     id: node_id,
     bounds: @OptVec<TyParamBound>
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct Generics {
     lifetimes: OptVec<Lifetime>,
     ty_params: OptVec<TyParam>
@@ -192,9 +195,7 @@ pub impl Generics {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum def {
     def_fn(def_id, purity),
     def_static_method(/* method */ def_id,
@@ -231,9 +232,7 @@ pub type crate_cfg = ~[@meta_item];
 
 pub type crate = spanned<crate_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct crate_ {
     module: _mod,
     attrs: ~[attribute],
@@ -242,9 +241,7 @@ pub struct crate_ {
 
 pub type meta_item = spanned<meta_item_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum meta_item_ {
     meta_word(@~str),
     meta_list(@~str, ~[@meta_item]),
@@ -253,9 +250,7 @@ pub enum meta_item_ {
 
 pub type blk = spanned<blk_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct blk_ {
     view_items: ~[@view_item],
     stmts: ~[@stmt],
@@ -264,26 +259,20 @@ pub struct blk_ {
     rules: blk_check_mode,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct pat {
     id: node_id,
     node: pat_,
     span: span,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct field_pat {
     ident: ident,
     pat: @pat,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum binding_mode {
     bind_by_copy,
     bind_by_ref(mutability),
@@ -317,9 +306,7 @@ impl to_bytes::IterBytes for binding_mode {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -344,9 +331,7 @@ pub enum pat_ {
     pat_vec(~[@pat], Option<@pat>, ~[@pat])
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum mutability { m_mutbl, m_imm, m_const, }
 
 #[cfg(stage0)]
@@ -362,9 +347,7 @@ impl to_bytes::IterBytes for mutability {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum Sigil {
     BorrowedSigil,
     OwnedSigil,
@@ -394,9 +377,7 @@ impl ToStr for Sigil {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum vstore {
     // FIXME (#3469): Change uint to @expr (actually only constant exprs)
     vstore_fixed(Option<uint>),     // [1,2,3,4]
@@ -405,9 +386,7 @@ pub enum vstore {
     vstore_slice(Option<@Lifetime>) // &'foo? [1,2,3,4]
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum expr_vstore {
     expr_vstore_uniq,                  // ~[1,2,3,4]
     expr_vstore_box,                   // @[1,2,3,4]
@@ -416,9 +395,7 @@ pub enum expr_vstore {
     expr_vstore_mut_slice,             // &mut [1,2,3,4]
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum binop {
     add,
     subtract,
@@ -440,9 +417,7 @@ pub enum binop {
     gt,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum unop {
     box(mutability),
     uniq(mutability),
@@ -453,9 +428,7 @@ pub enum unop {
 
 pub type stmt = spanned<stmt_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum stmt_ {
     stmt_decl(@decl, node_id),
 
@@ -471,9 +444,7 @@ pub enum stmt_ {
 
 // FIXME (pending discussion of #1697, #2178...): local should really be
 // a refinement on pat.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct local_ {
     is_mutbl: bool,
     ty: @Ty,
@@ -486,23 +457,17 @@ pub type local = spanned<local_>;
 
 pub type decl = spanned<decl_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum decl_ { decl_local(~[@local]), decl_item(@item), }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct arm {
     pats: ~[@pat],
     guard: Option<@expr>,
     body: blk,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct field_ {
     mutbl: mutability,
     ident: ident,
@@ -511,14 +476,10 @@ pub struct field_ {
 
 pub type field = spanned<field_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum blk_check_mode { default_blk, unsafe_blk, }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct expr {
     id: node_id,
     // Extra node ID is only used for index, assign_op, unary, binary, method
@@ -528,18 +489,14 @@ pub struct expr {
     span: span,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum CallSugar {
     NoSugar,
     DoSugar,
     ForSugar
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
@@ -572,6 +529,9 @@ pub enum expr_ {
     expr_field(@expr, ident, ~[@Ty]),
     expr_index(@expr, @expr),
     expr_path(@Path),
+
+    /// The special identifier `self`.
+    expr_self,
     expr_addr_of(mutability, @expr),
     expr_break(Option<ident>),
     expr_again(Option<ident>),
@@ -607,9 +567,7 @@ pub enum expr_ {
 // else knows what to do with them, so you'll probably get a syntax
 // error.
 //
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 pub enum token_tree {
     // a single token
@@ -682,9 +640,7 @@ pub enum token_tree {
 //
 pub type matcher = spanned<matcher_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum matcher_ {
     // match one token
     match_tok(::parse::token::Token),
@@ -697,18 +653,14 @@ pub enum matcher_ {
 
 pub type mac = spanned<mac_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum mac_ {
     mac_invoc_tt(@Path,~[token_tree]),   // new macro-invocation
 }
 
 pub type lit = spanned<lit_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum lit_ {
     lit_str(@~str),
     lit_int(i64, int_ty),
@@ -722,17 +674,13 @@ pub enum lit_ {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct mt {
     ty: @Ty,
     mutbl: mutability,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct ty_field_ {
     ident: ident,
     mt: mt,
@@ -740,23 +688,19 @@ pub struct ty_field_ {
 
 pub type ty_field = spanned<ty_field_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct ty_method {
     ident: ident,
     attrs: ~[attribute],
     purity: purity,
     decl: fn_decl,
     generics: Generics,
-    self_ty: self_ty,
+    explicit_self: explicit_self,
     id: node_id,
     span: span,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 // A trait method is either required (meaning it doesn't have an
 // implementation, just a signature) or provided (meaning it has a default
 // implementation).
@@ -765,9 +709,7 @@ pub enum trait_method {
     provided(@method),
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 impl ToStr for int_ty {
@@ -789,9 +731,7 @@ impl to_bytes::IterBytes for int_ty {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
 
 impl ToStr for uint_ty {
@@ -813,9 +753,7 @@ impl to_bytes::IterBytes for uint_ty {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum float_ty { ty_f, ty_f32, ty_f64, }
 
 impl ToStr for float_ty {
@@ -838,9 +776,7 @@ impl to_bytes::IterBytes for float_ty {
 }
 
 // NB Eq method appears below.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct Ty {
     id: node_id,
     node: ty_,
@@ -848,9 +784,7 @@ pub struct Ty {
 }
 
 // Not represented directly in the AST, referred to by name through a ty_path.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum prim_ty {
     ty_int(int_ty),
     ty_uint(uint_ty),
@@ -859,9 +793,7 @@ pub enum prim_ty {
     ty_bool,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum Onceness {
     Once,
     Many
@@ -889,21 +821,18 @@ impl to_bytes::IterBytes for Onceness {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct TyClosure {
     sigil: Sigil,
     region: Option<@Lifetime>,
     lifetimes: OptVec<Lifetime>,
     purity: purity,
     onceness: Onceness,
-    decl: fn_decl
+    decl: fn_decl,
+    bounds: OptVec<TyParamBound>
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct TyBareFn {
     purity: purity,
     abis: AbiSet,
@@ -911,9 +840,7 @@ pub struct TyBareFn {
     decl: fn_decl
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
@@ -947,17 +874,13 @@ impl to_bytes::IterBytes for Ty {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum asm_dialect {
     asm_att,
     asm_intel
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct inline_asm {
     asm: @~str,
     clobbers: @~str,
@@ -968,9 +891,7 @@ pub struct inline_asm {
     dialect: asm_dialect
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct arg {
     is_mutbl: bool,
     ty: @Ty,
@@ -978,18 +899,14 @@ pub struct arg {
     id: node_id,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct fn_decl {
     inputs: ~[arg],
     output: @Ty,
     cf: ret_style,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum purity {
     pure_fn, // declared with "pure fn"
     unsafe_fn, // declared with "unsafe fn"
@@ -1021,9 +938,7 @@ impl to_bytes::IterBytes for purity {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum ret_style {
     noreturn, // functions with return type _|_ that always
               // raise an error or exit (i.e. never return to the caller)
@@ -1043,10 +958,8 @@ impl to_bytes::IterBytes for ret_style {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
-pub enum self_ty_ {
+#[deriving(Eq, Encodable, Decodable)]
+pub enum explicit_self_ {
     sty_static,                                // no self
     sty_value,                                 // `self`
     sty_region(Option<@Lifetime>, mutability), // `&'lt self`
@@ -1054,16 +967,40 @@ pub enum self_ty_ {
     sty_uniq(mutability)                       // `~self`
 }
 
-pub type self_ty = spanned<self_ty_>;
+#[cfg(stage0)]
+impl to_bytes::IterBytes for explicit_self_ {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
+        match *self {
+            sty_static => 0u8.iter_bytes(lsb0, f),
+            sty_value => 1u8.iter_bytes(lsb0, f),
+            sty_region(ref lft, ref mutbl) => to_bytes::iter_bytes_3(&2u8, &lft, mutbl, lsb0, f),
+            sty_box(ref mutbl) => to_bytes::iter_bytes_2(&3u8, mutbl, lsb0, f),
+            sty_uniq(ref mutbl) => to_bytes::iter_bytes_2(&4u8, mutbl, lsb0, f),
+        }
+    }
+}
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[cfg(not(stage0))]
+impl to_bytes::IterBytes for explicit_self_ {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
+        match *self {
+            sty_static => 0u8.iter_bytes(lsb0, f),
+            sty_value => 1u8.iter_bytes(lsb0, f),
+            sty_region(ref lft, ref mutbl) => to_bytes::iter_bytes_3(&2u8, &lft, mutbl, lsb0, f),
+            sty_box(ref mutbl) => to_bytes::iter_bytes_2(&3u8, mutbl, lsb0, f),
+            sty_uniq(ref mutbl) => to_bytes::iter_bytes_2(&4u8, mutbl, lsb0, f),
+        }
+    }
+}
+
+pub type explicit_self = spanned<explicit_self_>;
+
+#[deriving(Eq, Encodable, Decodable)]
 pub struct method {
     ident: ident,
     attrs: ~[attribute],
     generics: Generics,
-    self_ty: self_ty,
+    explicit_self: explicit_self,
     purity: purity,
     decl: fn_decl,
     body: blk,
@@ -1073,23 +1010,17 @@ pub struct method {
     vis: visibility,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct _mod {
     view_items: ~[@view_item],
     items: ~[@item],
 }
 
 // Foreign mods can be named or anonymous
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum foreign_mod_sort { named, anonymous }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct foreign_mod {
     sort: foreign_mod_sort,
     abis: AbiSet,
@@ -1097,32 +1028,24 @@ pub struct foreign_mod {
     items: ~[@foreign_item],
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct variant_arg {
     ty: @Ty,
     id: node_id,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum variant_kind {
     tuple_variant_kind(~[variant_arg]),
     struct_variant_kind(@struct_def),
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct enum_def {
     variants: ~[variant],
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct variant_ {
     name: ident,
     attrs: ~[attribute],
@@ -1134,9 +1057,7 @@ pub struct variant_ {
 
 pub type variant = spanned<variant_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct path_list_ident_ {
     name: ident,
     id: node_id,
@@ -1146,9 +1067,7 @@ pub type path_list_ident = spanned<path_list_ident_>;
 
 pub type view_path = spanned<view_path_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum view_path_ {
 
     // quux = foo::bar::baz
@@ -1165,9 +1084,7 @@ pub enum view_path_ {
     view_path_list(@Path, ~[path_list_ident], node_id)
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct view_item {
     node: view_item_,
     attrs: ~[attribute],
@@ -1175,9 +1092,7 @@ pub struct view_item {
     span: span,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum view_item_ {
     view_item_extern_mod(ident, ~[@meta_item], node_id),
     view_item_use(~[@view_path]),
@@ -1189,15 +1104,11 @@ pub type attribute = spanned<attribute_>;
 // Distinguishes between attributes that decorate items and attributes that
 // are contained as statements within items. These two cases need to be
 // distinguished for pretty-printing.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum attr_style { attr_outer, attr_inner, }
 
 // doc-comments are promoted to attributes that have is_sugared_doc = true
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct attribute_ {
     style: attr_style,
     value: @meta_item,
@@ -1211,17 +1122,13 @@ pub struct attribute_ {
   If this impl is an item_impl, the impl_id is redundant (it could be the
   same as the impl's node id).
  */
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct trait_ref {
     path: @Path,
     ref_id: node_id,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum visibility { public, private, inherited }
 
 impl visibility {
@@ -1233,9 +1140,7 @@ impl visibility {
     }
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct struct_field_ {
     kind: struct_field_kind,
     id: node_id,
@@ -1245,17 +1150,13 @@ pub struct struct_field_ {
 
 pub type struct_field = spanned<struct_field_>;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum struct_field_kind {
     named_field(ident, visibility),
     unnamed_field   // element of a tuple-like struct
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct struct_def {
     fields: ~[@struct_field], /* fields, not including ctor */
     /* ID of the constructor. This is only used for tuple- or enum-like
@@ -1267,9 +1168,7 @@ pub struct struct_def {
   FIXME (#3300): Should allow items to be anonymous. Right now
   we just use dummy names for anon items.
  */
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct item {
     ident: ident,
     attrs: ~[attribute],
@@ -1279,9 +1178,7 @@ pub struct item {
     span: span,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum item_ {
     item_const(@Ty, @expr),
     item_fn(fn_decl, purity, AbiSet, Generics, blk),
@@ -1299,9 +1196,7 @@ pub enum item_ {
     item_mac(mac),
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct foreign_item {
     ident: ident,
     attrs: ~[attribute],
@@ -1311,9 +1206,7 @@ pub struct foreign_item {
     vis: visibility,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum foreign_item_ {
     foreign_item_fn(fn_decl, purity, Generics),
     foreign_item_const(@Ty)
@@ -1322,9 +1215,7 @@ pub enum foreign_item_ {
 // The data we save and restore about an inlined item or method.  This is not
 // part of the AST that we parse from a file, but it becomes part of the tree
 // that we trans.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 77a02adbafb..e9f15c0a8f5 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -60,12 +60,12 @@ pub fn path_to_str_with_sep(p: &[path_elt], sep: ~str, itr: @ident_interner)
     str::connect(strs, sep)
 }
 
-pub fn path_ident_to_str(p: path, i: ident, itr: @ident_interner) -> ~str {
-    if vec::is_empty(p) {
+pub fn path_ident_to_str(p: &path, i: ident, itr: @ident_interner) -> ~str {
+    if vec::is_empty(*p) {
         //FIXME /* FIXME (#2543) */ copy *i
         copy *itr.get(i)
     } else {
-        fmt!("%s::%s", path_to_str(p, itr), *itr.get(i))
+        fmt!("%s::%s", path_to_str(*p, itr), *itr.get(i))
     }
 }
 
@@ -304,7 +304,7 @@ pub fn map_struct_def(
                     cx.map.insert(ctor_id,
                                   node_struct_ctor(struct_def, item, p));
                 }
-                _ => fail!(~"struct def parent wasn't an item")
+                _ => fail!("struct def parent wasn't an item")
             }
         }
     }
@@ -338,7 +338,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
         fmt!("unknown node (id=%d)", id)
       }
       Some(&node_item(item, path)) => {
-        let path_str = path_ident_to_str(*path, item.ident, itr);
+        let path_str = path_ident_to_str(path, item.ident, itr);
         let item_str = match item.node {
           item_const(*) => ~"const",
           item_fn(*) => ~"fn",
@@ -355,7 +355,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
       }
       Some(&node_foreign_item(item, abi, _, path)) => {
         fmt!("foreign item %s with abi %? (id=%?)",
-             path_ident_to_str(*path, item.ident, itr), abi, id)
+             path_ident_to_str(path, item.ident, itr), abi, id)
       }
       Some(&node_method(m, _, path)) => {
         fmt!("method %s in %s (id=%?)",
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index ceff868d11f..d4a67d61d94 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -37,7 +37,7 @@ pub fn stmt_id(s: &stmt) -> node_id {
       stmt_decl(_, id) => id,
       stmt_expr(_, id) => id,
       stmt_semi(_, id) => id,
-      stmt_mac(*) => fail!(~"attempted to analyze unexpanded stmt")
+      stmt_mac(*) => fail!("attempted to analyze unexpanded stmt")
     }
 }
 
@@ -272,7 +272,7 @@ pub fn trait_method_to_ty_method(method: &trait_method) -> ty_method {
                 purity: m.purity,
                 decl: copy m.decl,
                 generics: copy m.generics,
-                self_ty: m.self_ty,
+                explicit_self: m.explicit_self,
                 id: m.id,
                 span: m.span,
             }
@@ -370,8 +370,7 @@ pub fn empty_generics() -> Generics {
 // ______________________________________________________________________
 // Enumerating the IDs which appear in an AST
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub struct id_range {
     min: node_id,
     max: node_id,
@@ -413,7 +412,12 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> {
                       match vp.node {
                           view_path_simple(_, _, id) => vfn(id),
                           view_path_glob(_, id) => vfn(id),
-                          view_path_list(_, _, id) => vfn(id)
+                          view_path_list(_, ref paths, id) => {
+                              vfn(id);
+                              for paths.each |p| {
+                                  vfn(p.node.id);
+                              }
+                          }
                       }
                   }
               }
@@ -679,19 +683,19 @@ mod test {
     #[test] fn xorpush_test () {
         let mut s = ~[];
         xorPush(&mut s,14);
-        assert_eq!(s,~[14]);
+        assert_eq!(copy s,~[14]);
         xorPush(&mut s,14);
-        assert_eq!(s,~[]);
+        assert_eq!(copy s,~[]);
         xorPush(&mut s,14);
-        assert_eq!(s,~[14]);
+        assert_eq!(copy s,~[14]);
         xorPush(&mut s,15);
-        assert_eq!(s,~[14,15]);
+        assert_eq!(copy s,~[14,15]);
         xorPush (&mut s,16);
-        assert_eq! (s,~[14,15,16]);
+        assert_eq!(copy s,~[14,15,16]);
         xorPush (&mut s,16);
-        assert_eq! (s,~[14,15]);
+        assert_eq!(copy s,~[14,15]);
         xorPush (&mut s,15);
-        assert_eq! (s,~[14]);
+        assert_eq!(copy s,~[14]);
     }
 
     // convert a list of uints to an @~[ident]
@@ -746,7 +750,7 @@ mod test {
         let mut t = mk_sctable();
 
         let test_sc = ~[M(3),R(id(101,0),14),M(9)];
-        assert_eq!(unfold_test_sc(test_sc,empty_ctxt,&mut t),3);
+        assert_eq!(unfold_test_sc(copy test_sc,empty_ctxt,&mut t),3);
         assert_eq!(t[1],Mark(9,0));
         assert_eq!(t[2],Rename(id(101,0),14,1));
         assert_eq!(t[3],Mark(3,2));
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 053ed76d66b..44a368738fd 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -127,9 +127,7 @@ pub struct span {
     expn_info: Option<@ExpnInfo>
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Eq, Encodable, Decodable)]
 pub struct spanned<T> { node: T, span: span }
 
 impl cmp::Eq for span {
@@ -152,6 +150,20 @@ impl<D:Decoder> Decodable<D> for span {
     }
 }
 
+#[cfg(stage0)]
+impl to_bytes::IterBytes for span {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
+        to_bytes::iter_bytes_3(&self.lo, &self.hi, &self.expn_info, lsb0, f);
+    }
+}
+
+#[cfg(not(stage0))]
+impl to_bytes::IterBytes for span {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
+        to_bytes::iter_bytes_3(&self.lo, &self.hi, &self.expn_info, lsb0, f)
+    }
+}
+
 pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> spanned<T> {
     respan(mk_sp(lo, hi), t)
 }
@@ -199,16 +211,62 @@ pub struct FileMapAndLine {fm: @FileMap, line: uint}
 pub struct FileMapAndBytePos {fm: @FileMap, pos: BytePos}
 pub struct NameAndSpan {name: ~str, span: Option<span>}
 
+#[cfg(stage0)]
+impl to_bytes::IterBytes for NameAndSpan {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
+        to_bytes::iter_bytes_2(&self.name, &self.span, lsb0, f)
+    }
+}
+
+#[cfg(not(stage0))]
+impl to_bytes::IterBytes for NameAndSpan {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
+        to_bytes::iter_bytes_2(&self.name, &self.span, lsb0, f)
+    }
+}
+
 pub struct CallInfo {
     call_site: span,
     callee: NameAndSpan
 }
 
+#[cfg(stage0)]
+impl to_bytes::IterBytes for CallInfo {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
+        to_bytes::iter_bytes_2(&self.call_site, &self.callee, lsb0, f)
+    }
+}
+
+#[cfg(not(stage0))]
+impl to_bytes::IterBytes for CallInfo {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
+        to_bytes::iter_bytes_2(&self.call_site, &self.callee, lsb0, f)
+    }
+}
+
 /// Extra information for tracking macro expansion of spans
 pub enum ExpnInfo {
     ExpandedFrom(CallInfo)
 }
 
+#[cfg(stage0)]
+impl to_bytes::IterBytes for ExpnInfo {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
+        match *self {
+            ExpandedFrom(ref call_info) => to_bytes::iter_bytes_2(&0u8, call_info, lsb0, f)
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl to_bytes::IterBytes for ExpnInfo {
+    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
+        match *self {
+            ExpandedFrom(ref call_info) => to_bytes::iter_bytes_2(&0u8, call_info, lsb0, f)
+        }
+    }
+}
+
 pub type FileName = ~str;
 
 pub struct FileLines
@@ -430,8 +488,7 @@ priv impl CodeMap {
             }
         }
         if (a >= len) {
-            fail!(fmt!("position %u does not resolve to a source location",
-                      pos.to_uint()))
+            fail!("position %u does not resolve to a source location", pos.to_uint())
         }
 
         return a;
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index b313a2fc6fc..993fa612a27 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -184,7 +184,7 @@ fn diagnosticcolor(lvl: level) -> u8 {
     }
 }
 
-fn print_diagnostic(topic: ~str, lvl: level, msg: &str) {
+fn print_diagnostic(topic: &str, lvl: level, msg: &str) {
     let use_color = term::color_supported() &&
         io::stderr().get_type() == io::Screen;
     if !topic.is_empty() {
@@ -232,7 +232,7 @@ fn highlight_lines(cm: @codemap::CodeMap,
     let max_lines = 6u;
     let mut elided = false;
     let mut display_lines = /* FIXME (#2543) */ copy lines.lines;
-    if vec::len(display_lines) > max_lines {
+    if display_lines.len() > max_lines {
         display_lines = vec::slice(display_lines, 0u, max_lines).to_vec();
         elided = true;
     }
@@ -243,7 +243,7 @@ fn highlight_lines(cm: @codemap::CodeMap,
         io::stderr().write_str(s);
     }
     if elided {
-        let last_line = display_lines[vec::len(display_lines) - 1u];
+        let last_line = display_lines[display_lines.len() - 1u];
         let s = fmt!("%s:%u ", fm.name, last_line + 1u);
         let mut indent = str::len(s);
         let mut out = ~"";
@@ -254,7 +254,7 @@ fn highlight_lines(cm: @codemap::CodeMap,
 
     // FIXME (#3260)
     // If there's one line at fault we can easily point to the problem
-    if vec::len(lines.lines) == 1u {
+    if lines.lines.len() == 1u {
         let lo = cm.lookup_char_pos(sp.lo);
         let mut digits = 0u;
         let mut num = (lines.lines[0] + 1u) / 10u;
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index 00c178b6d7c..97c5797cf57 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -119,13 +119,13 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
                 cons = str::connect(clobs, ",");
             }
             Options => {
-                let option = *p.parse_str();
+                let option = p.parse_str();
 
-                if option == ~"volatile" {
+                if "volatile" == *option {
                     volatile = true;
-                } else if option == ~"alignstack" {
+                } else if "alignstack" == *option {
                     alignstack = true;
-                } else if option == ~"intel" {
+                } else if "intel" == *option {
                     dialect = ast::asm_intel;
                 }
 
diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs
index 1d3af61be70..6bb3ac5eba4 100644
--- a/src/libsyntax/ext/auto_encode.rs
+++ b/src/libsyntax/ext/auto_encode.rs
@@ -8,102 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-
-The compiler code necessary to implement the #[auto_encode] and
-#[auto_decode] extension.  The idea here is that type-defining items may
-be tagged with #[auto_encode] and #[auto_decode], which will cause
-us to generate a little companion module with the same name as the item.
-
-For example, a type like:
-
-    #[auto_encode]
-    #[auto_decode]
-    struct Node {id: uint}
-
-would generate two implementations like:
-
-impl<S:std::serialize::Encoder> Encodable<S> for Node {
-    fn encode(&self, s: &S) {
-        do s.emit_struct("Node", 1) {
-            s.emit_field("id", 0, || s.emit_uint(self.id))
-        }
-    }
-}
-
-impl<D:Decoder> Decodable for node_id {
-    fn decode(d: &D) -> Node {
-        do d.read_struct("Node", 1) {
-            Node {
-                id: d.read_field(~"x", 0, || decode(d))
-            }
-        }
-    }
-}
-
-Other interesting scenarios are whe the item has type parameters or
-references other non-built-in types.  A type definition like:
-
-    #[auto_encode]
-    #[auto_decode]
-    struct spanned<T> {node: T, span: span}
-
-would yield functions like:
-
-    impl<
-        S: Encoder,
-        T: Encodable<S>
-    > spanned<T>: Encodable<S> {
-        fn encode<S:Encoder>(s: &S) {
-            do s.emit_rec {
-                s.emit_field("node", 0, || self.node.encode(s));
-                s.emit_field("span", 1, || self.span.encode(s));
-            }
-        }
-    }
-
-    impl<
-        D: Decoder,
-        T: Decodable<D>
-    > spanned<T>: Decodable<D> {
-        fn decode(d: &D) -> spanned<T> {
-            do d.read_rec {
-                {
-                    node: d.read_field(~"node", 0, || decode(d)),
-                    span: d.read_field(~"span", 1, || decode(d)),
-                }
-            }
-        }
-    }
-
-FIXME (#2810)--Hygiene. Search for "__" strings.  We also assume "std" is the
-standard library.
-
-Misc notes:
------------
-
-I use move mode arguments for ast nodes that will get inserted as is
-into the tree.  This is intended to prevent us from inserting the same
-node twice.
-
-*/
+/// Deprecated #[auto_encode] and #[auto_decode] syntax extensions
 
 use ast;
-use ast_util;
-use attr;
-use codemap;
 use codemap::span;
 use ext::base::*;
-use parse;
-use opt_vec;
-use opt_vec::OptVec;
-use ext::build;
-
-// Transitional reexports so qquote can find the paths it is looking for
-mod syntax {
-    pub use ext;
-    pub use parse;
-}
 
 pub fn expand_auto_encode(
     cx: @ext_ctxt,
@@ -111,53 +20,8 @@ pub fn expand_auto_encode(
     _mitem: @ast::meta_item,
     in_items: ~[@ast::item]
 ) -> ~[@ast::item] {
-    fn is_auto_encode(a: &ast::attribute) -> bool {
-        *attr::get_attr_name(a) == ~"auto_encode"
-    }
-
-    fn filter_attrs(item: @ast::item) -> @ast::item {
-        @ast::item {
-            attrs: item.attrs.filtered(|a| !is_auto_encode(a)),
-            .. copy *item
-        }
-    }
-
-    do vec::flat_map(in_items) |item| {
-        if item.attrs.any(is_auto_encode) {
-            match item.node {
-                ast::item_struct(ref struct_def, ref generics) => {
-                    let ser_impl = mk_struct_ser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        struct_def.fields,
-                        generics
-                    );
-
-                    ~[filter_attrs(*item), ser_impl]
-                },
-                ast::item_enum(ref enum_def, ref generics) => {
-                    let ser_impl = mk_enum_ser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        copy *enum_def,
-                        generics
-                    );
-
-                    ~[filter_attrs(*item), ser_impl]
-                },
-                _ => {
-                    cx.span_err(span, ~"#[auto_encode] can only be \
-                                        applied to structs, record types, \
-                                        and enum definitions");
-                    ~[*item]
-                }
-            }
-        } else {
-            ~[*item]
-        }
-    }
+    cx.span_err(span, "`#[auto_encode]` is deprecated, use `#[deriving(Encodable)]` instead");
+    in_items
 }
 
 pub fn expand_auto_decode(
@@ -166,1348 +30,6 @@ pub fn expand_auto_decode(
     _mitem: @ast::meta_item,
     in_items: ~[@ast::item]
 ) -> ~[@ast::item] {
-    fn is_auto_decode(a: &ast::attribute) -> bool {
-        *attr::get_attr_name(a) == ~"auto_decode"
-    }
-
-    fn filter_attrs(item: @ast::item) -> @ast::item {
-        @ast::item {
-            attrs: item.attrs.filtered(|a| !is_auto_decode(a)),
-            .. copy *item
-        }
-    }
-
-    do vec::flat_map(in_items) |item| {
-        if item.attrs.any(is_auto_decode) {
-            match item.node {
-                ast::item_struct(ref struct_def, ref generics) => {
-                    let deser_impl = mk_struct_deser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        struct_def.fields,
-                        generics
-                    );
-
-                    ~[filter_attrs(*item), deser_impl]
-                },
-                ast::item_enum(ref enum_def, ref generics) => {
-                    let deser_impl = mk_enum_deser_impl(
-                        cx,
-                        item.span,
-                        item.ident,
-                        copy *enum_def,
-                        generics
-                    );
-
-                    ~[filter_attrs(*item), deser_impl]
-                },
-                _ => {
-                    cx.span_err(span, ~"#[auto_decode] can only be \
-                                        applied to structs, record types, \
-                                        and enum definitions");
-                    ~[*item]
-                }
-            }
-        } else {
-            ~[*item]
-        }
-    }
-}
-
-trait ExtCtxtMethods {
-    fn bind_path(&self,
-                 span: span,
-                 ident: ast::ident,
-                 path: @ast::Path,
-                 bounds: @OptVec<ast::TyParamBound>)
-                 -> ast::TyParam;
-    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr;
-    fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
-    fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
-    fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
-                -> @ast::Path;
-    fn path_tps_global(&self,
-                       span: span,
-                       strs: ~[ast::ident],
-                       tps: ~[@ast::Ty])
-                       -> @ast::Path;
-    fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
-               -> @ast::Ty;
-    fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat;
-    fn stmt(&self, expr: @ast::expr) -> @ast::stmt;
-    fn lit_str(&self, span: span, s: @~str) -> @ast::expr;
-    fn lit_uint(&self, span: span, i: uint) -> @ast::expr;
-    fn lambda0(&self, blk: ast::blk) -> @ast::expr;
-    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr;
-    fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk;
-    fn expr_blk(&self, expr: @ast::expr) -> ast::blk;
-    fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
-    fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
-    fn expr_var(&self, span: span, var: &str) -> @ast::expr;
-    fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident)
-                  -> @ast::expr;
-    fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr])
-                 -> @ast::expr;
-    fn expr_method_call(&self,
-                        span: span,
-                        expr: @ast::expr,
-                        ident: ast::ident,
-                        args: ~[@ast::expr])
-                        -> @ast::expr;
-    fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr;
-    fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
-                    -> @ast::expr;
-    fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr;
-    fn lambda_stmts_1(&self,
-                      span: span,
-                      stmts: ~[@ast::stmt],
-                      ident: ast::ident)
-                      -> @ast::expr;
-}
-
-impl ExtCtxtMethods for @ext_ctxt {
-    fn bind_path(
-        &self,
-        _span: span,
-        ident: ast::ident,
-        path: @ast::Path,
-        bounds: @OptVec<ast::TyParamBound>
-    ) -> ast::TyParam {
-        let bound = ast::TraitTyParamBound(@ast::trait_ref {
-            ref_id: self.next_id(),
-            path: path
-        });
-
-        ast::TyParam {
-            ident: ident,
-            id: self.next_id(),
-            bounds: @bounds.prepend(bound)
-        }
-    }
-
-    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr {
-        @ast::expr {
-            id: self.next_id(),
-            callee_id: self.next_id(),
-            node: node,
-            span: span,
-        }
-    }
-
-    fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path {
-        @ast::Path {
-            span: span,
-            global: false,
-            idents: strs,
-            rp: None,
-            types: ~[]
-        }
-    }
-
-    fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path {
-        @ast::Path {
-            span: span,
-            global: true,
-            idents: strs,
-            rp: None,
-            types: ~[]
-        }
-    }
-
-    fn path_tps(
-        &self,
-        span: span,
-        strs: ~[ast::ident],
-        tps: ~[@ast::Ty]
-    ) -> @ast::Path {
-        @ast::Path {
-            span: span,
-            global: false,
-            idents: strs,
-            rp: None,
-            types: tps
-        }
-    }
-
-    fn path_tps_global(
-        &self,
-        span: span,
-        strs: ~[ast::ident],
-        tps: ~[@ast::Ty]
-    ) -> @ast::Path {
-        @ast::Path {
-            span: span,
-            global: true,
-            idents: strs,
-            rp: None,
-            types: tps
-        }
-    }
-
-    fn ty_path(
-        &self,
-        span: span,
-        strs: ~[ast::ident],
-        tps: ~[@ast::Ty]
-    ) -> @ast::Ty {
-        @ast::Ty {
-            id: self.next_id(),
-            node: ast::ty_path(
-                self.path_tps(span, strs, tps),
-                self.next_id()),
-            span: span,
-        }
-    }
-
-    fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat {
-        @ast::pat {
-            id: self.next_id(),
-            node: ast::pat_ident(
-                ast::bind_by_ref(ast::m_imm),
-                self.path(span, ~[nm]),
-                None),
-            span: span,
-        }
-    }
-
-    fn stmt(&self, expr: @ast::expr) -> @ast::stmt {
-        @codemap::spanned { node: ast::stmt_semi(expr, self.next_id()),
-                       span: expr.span }
-    }
-
-    fn lit_str(&self, span: span, s: @~str) -> @ast::expr {
-        self.expr(
-            span,
-            ast::expr_vstore(
-                self.expr(
-                    span,
-                    ast::expr_lit(
-                        @codemap::spanned { node: ast::lit_str(s),
-                                        span: span})),
-                ast::expr_vstore_uniq))
-    }
-
-    fn lit_uint(&self, span: span, i: uint) -> @ast::expr {
-        self.expr(
-            span,
-            ast::expr_lit(
-                @codemap::spanned { node: ast::lit_uint(i as u64, ast::ty_u),
-                                span: span}))
-    }
-
-    fn lambda0(&self, blk: ast::blk) -> @ast::expr {
-        let ext_cx = *self;
-        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
-        quote_expr!( || $blk_e )
-    }
-
-    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr {
-        let ext_cx = *self;
-        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
-        quote_expr!( |$ident| $blk_e )
-    }
-
-    fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk {
-        codemap::spanned {
-            node: ast::blk_ {
-                view_items: ~[],
-                stmts: stmts,
-                expr: None,
-                id: self.next_id(),
-                rules: ast::default_blk,
-            },
-            span: span,
-        }
-    }
-
-    fn expr_blk(&self, expr: @ast::expr) -> ast::blk {
-        codemap::spanned {
-            node: ast::blk_ {
-                view_items: ~[],
-                stmts: ~[],
-                expr: Some(expr),
-                id: self.next_id(),
-                rules: ast::default_blk,
-            },
-            span: expr.span,
-        }
-    }
-
-    fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr {
-        self.expr(span, ast::expr_path(self.path(span, strs)))
-    }
-
-    fn expr_path_global(
-        &self,
-        span: span,
-        strs: ~[ast::ident]
-    ) -> @ast::expr {
-        self.expr(span, ast::expr_path(self.path_global(span, strs)))
-    }
-
-    fn expr_var(&self, span: span, var: &str) -> @ast::expr {
-        self.expr_path(span, ~[self.ident_of(var)])
-    }
-
-    fn expr_field(
-        &self,
-        span: span,
-        expr: @ast::expr,
-        ident: ast::ident
-    ) -> @ast::expr {
-        self.expr(span, ast::expr_field(expr, ident, ~[]))
-    }
-
-    fn expr_call(
-        &self,
-        span: span,
-        expr: @ast::expr,
-        args: ~[@ast::expr]
-    ) -> @ast::expr {
-        self.expr(span, ast::expr_call(expr, args, ast::NoSugar))
-    }
-
-    fn expr_method_call(
-        &self,
-        span: span,
-        expr: @ast::expr,
-        ident: ast::ident,
-        args: ~[@ast::expr]
-    ) -> @ast::expr {
-        self.expr(span,
-                  ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar))
-    }
-
-    fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr {
-        self.lambda0(self.expr_blk(expr))
-    }
-
-    fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
-                    -> @ast::expr {
-        self.lambda1(self.expr_blk(expr), ident)
-    }
-
-    fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
-        self.lambda0(self.blk(span, stmts))
-    }
-
-    fn lambda_stmts_1(&self,
-                      span: span,
-                      stmts: ~[@ast::stmt],
-                      ident: ast::ident)
-                      -> @ast::expr {
-        self.lambda1(self.blk(span, stmts), ident)
-    }
-}
-
-fn mk_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    ty_param: ast::TyParam,
-    path: @ast::Path,
-    generics: &ast::Generics,
-    f: &fn(@ast::Ty) -> @ast::method
-) -> @ast::item {
-    /*!
-     *
-     * Given that we are deriving auto-encode a type `T<'a, ...,
-     * 'z, A, ..., Z>`, creates an impl like:
-     *
-     *      impl<'a, ..., 'z, A:Tr, ..., Z:Tr> Tr for T<A, ..., Z> { ... }
-     *
-     * where Tr is either Serializable and Deserialize.
-     *
-     * FIXME(#5090): Remove code duplication between this and the code
-     * in deriving.rs
-     */
-
-
-    // Copy the lifetimes
-    let impl_lifetimes = generics.lifetimes.map(|l| {
-        build::mk_lifetime(cx, l.span, l.ident)
-    });
-
-    // All the type parameters need to bound to the trait.
-    let mut impl_tps = opt_vec::with(ty_param);
-    for generics.ty_params.each |tp| {
-        let t_bound = ast::TraitTyParamBound(@ast::trait_ref {
-            path: path,
-            ref_id: cx.next_id(),
-        });
-
-        impl_tps.push(ast::TyParam {
-            ident: tp.ident,
-            id: cx.next_id(),
-            bounds: @tp.bounds.prepend(t_bound)
-        })
-    }
-
-    let opt_trait = Some(@ast::trait_ref {
-        path: path,
-        ref_id: cx.next_id(),
-    });
-
-    let ty = cx.ty_path(
-        span,
-        ~[ident],
-        opt_vec::take_vec(generics.ty_params.map(
-            |tp| cx.ty_path(span, ~[tp.ident], ~[])))
-    );
-
-    let generics = ast::Generics {
-        lifetimes: impl_lifetimes,
-        ty_params: impl_tps
-    };
-
-    @ast::item {
-        // This is a new-style impl declaration.
-        // XXX: clownshoes
-        ident: parse::token::special_idents::clownshoes_extensions,
-        attrs: ~[],
-        id: cx.next_id(),
-        node: ast::item_impl(generics, opt_trait, ty, ~[f(ty)]),
-        vis: ast::public,
-        span: span,
-    }
-}
-
-fn mk_ser_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    generics: &ast::Generics,
-    body: @ast::expr
-) -> @ast::item {
-    // Make a path to the std::serialize::Encodable typaram.
-    let ty_param = cx.bind_path(
-        span,
-        cx.ident_of("__S"),
-        cx.path_global(
-            span,
-            ~[
-                cx.ident_of("std"),
-                cx.ident_of("serialize"),
-                cx.ident_of("Encoder"),
-            ]
-        ),
-        @opt_vec::Empty
-    );
-
-    // Make a path to the std::serialize::Encodable trait.
-    let path = cx.path_tps_global(
-        span,
-        ~[
-            cx.ident_of("std"),
-            cx.ident_of("serialize"),
-            cx.ident_of("Encodable"),
-        ],
-        ~[cx.ty_path(span, ~[cx.ident_of("__S")], ~[])]
-    );
-
-    mk_impl(
-        cx,
-        span,
-        ident,
-        ty_param,
-        path,
-        generics,
-        |_ty| mk_ser_method(cx, span, cx.expr_blk(body))
-    )
-}
-
-fn mk_deser_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    generics: &ast::Generics,
-    body: @ast::expr
-) -> @ast::item {
-    // Make a path to the std::serialize::Decodable typaram.
-    let ty_param = cx.bind_path(
-        span,
-        cx.ident_of("__D"),
-        cx.path_global(
-            span,
-            ~[
-                cx.ident_of("std"),
-                cx.ident_of("serialize"),
-                cx.ident_of("Decoder"),
-            ]
-        ),
-        @opt_vec::Empty
-    );
-
-    // Make a path to the std::serialize::Decodable trait.
-    let path = cx.path_tps_global(
-        span,
-        ~[
-            cx.ident_of("std"),
-            cx.ident_of("serialize"),
-            cx.ident_of("Decodable"),
-        ],
-        ~[cx.ty_path(span, ~[cx.ident_of("__D")], ~[])]
-    );
-
-    mk_impl(
-        cx,
-        span,
-        ident,
-        ty_param,
-        path,
-        generics,
-        |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body))
-    )
-}
-
-fn mk_ser_method(
-    cx: @ext_ctxt,
-    span: span,
-    ser_body: ast::blk
-) -> @ast::method {
-    let ty_s = @ast::Ty {
-        id: cx.next_id(),
-        node: ast::ty_rptr(
-            None,
-            ast::mt {
-                ty: cx.ty_path(span, ~[cx.ident_of("__S")], ~[]),
-                mutbl: ast::m_mutbl
-            }
-        ),
-        span: span,
-    };
-
-    let ser_inputs = ~[ast::arg {
-        is_mutbl: false,
-        ty: ty_s,
-        pat: @ast::pat {
-            id: cx.next_id(),
-            node: ast::pat_ident(
-                ast::bind_by_copy,
-                ast_util::ident_to_path(span, cx.ident_of("__s")),
-                None),
-            span: span,
-        },
-        id: cx.next_id(),
-    }];
-
-    let ser_output = @ast::Ty {
-        id: cx.next_id(),
-        node: ast::ty_nil,
-        span: span,
-    };
-
-    let ser_decl = ast::fn_decl {
-        inputs: ser_inputs,
-        output: ser_output,
-        cf: ast::return_val,
-    };
-
-    @ast::method {
-        ident: cx.ident_of("encode"),
-        attrs: ~[],
-        generics: ast_util::empty_generics(),
-        self_ty: codemap::spanned {
-            node: ast::sty_region(None, ast::m_imm),
-            span: span
-        },
-        purity: ast::impure_fn,
-        decl: ser_decl,
-        body: ser_body,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: ast::public,
-    }
-}
-
-fn mk_deser_method(
-    cx: @ext_ctxt,
-    span: span,
-    ty: @ast::Ty,
-    deser_body: ast::blk
-) -> @ast::method {
-    let ty_d = @ast::Ty {
-        id: cx.next_id(),
-        node: ast::ty_rptr(
-            None,
-            ast::mt {
-                ty: cx.ty_path(span, ~[cx.ident_of("__D")], ~[]),
-                mutbl: ast::m_mutbl
-            }
-        ),
-        span: span,
-    };
-
-    let deser_inputs = ~[
-        ast::arg {
-            is_mutbl: false,
-            ty: ty_d,
-            pat: @ast::pat {
-                id: cx.next_id(),
-                node: ast::pat_ident(ast::bind_by_copy,
-                                     ast_util::ident_to_path(span,
-                                                             cx.ident_of(
-                                                                "__d")),
-                                     None),
-                span: span,
-            },
-            id: cx.next_id(),
-        }
-    ];
-
-    let deser_decl = ast::fn_decl {
-        inputs: deser_inputs,
-        output: ty,
-        cf: ast::return_val,
-    };
-
-    @ast::method {
-        ident: cx.ident_of("decode"),
-        attrs: ~[],
-        generics: ast_util::empty_generics(),
-        self_ty: codemap::spanned { node: ast::sty_static, span: span },
-        purity: ast::impure_fn,
-        decl: deser_decl,
-        body: deser_body,
-        id: cx.next_id(),
-        span: span,
-        self_id: cx.next_id(),
-        vis: ast::public,
-    }
-}
-
-fn mk_struct_ser_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    fields: &[@ast::struct_field],
-    generics: &ast::Generics
-) -> @ast::item {
-    let fields = do mk_struct_fields(fields).mapi |idx, field| {
-        // ast for `|__s| self.$(name).encode(__s)`
-        let expr_lambda = cx.lambda_expr_1(
-            cx.expr_method_call(
-                span,
-                cx.expr_field(
-                    span,
-                    cx.expr_var(span, "self"),
-                    field.ident
-                ),
-                cx.ident_of("encode"),
-                ~[cx.expr_var(span, "__s")]
-            ),
-            cx.ident_of("__s")
-        );
-
-        // ast for `__s.emit_struct_field($(name), $(idx), $(expr_lambda))`
-        cx.stmt(
-            cx.expr_method_call(
-                span,
-                cx.expr_var(span, "__s"),
-                cx.ident_of("emit_struct_field"),
-                ~[
-                    cx.lit_str(span, @cx.str_of(field.ident)),
-                    cx.lit_uint(span, idx),
-                    expr_lambda,
-                ]
-            )
-        )
-    };
-
-    // ast for `__s.emit_struct($(name), |__s| $(fields))`
-    let ser_body = cx.expr_method_call(
-        span,
-        cx.expr_var(span, "__s"),
-        cx.ident_of("emit_struct"),
-        ~[
-            cx.lit_str(span, @cx.str_of(ident)),
-            cx.lit_uint(span, vec::len(fields)),
-            cx.lambda_stmts_1(span, fields, cx.ident_of("__s")),
-        ]
-    );
-
-    mk_ser_impl(cx, span, ident, generics, ser_body)
-}
-
-fn mk_struct_deser_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    fields: ~[@ast::struct_field],
-    generics: &ast::Generics
-) -> @ast::item {
-    let fields = do mk_struct_fields(fields).mapi |idx, field| {
-        // ast for `|__d| std::serialize::decode(__d)`
-        let expr_lambda = cx.lambda1(
-            cx.expr_blk(
-                cx.expr_call(
-                    span,
-                    cx.expr_path_global(span, ~[
-                        cx.ident_of("std"),
-                        cx.ident_of("serialize"),
-                        cx.ident_of("Decodable"),
-                        cx.ident_of("decode"),
-                    ]),
-                    ~[cx.expr_var(span, "__d")]
-                )
-            ),
-            cx.ident_of("__d")
-        );
-
-        // ast for `__d.read_struct_field($(name), $(idx), $(expr_lambda))`
-        let expr: @ast::expr = cx.expr_method_call(
-            span,
-            cx.expr_var(span, "__d"),
-            cx.ident_of("read_struct_field"),
-            ~[
-                cx.lit_str(span, @cx.str_of(field.ident)),
-                cx.lit_uint(span, idx),
-                expr_lambda,
-            ]
-        );
-
-        codemap::spanned {
-            node: ast::field_ {
-                mutbl: field.mutbl,
-                ident: field.ident,
-                expr: expr,
-            },
-            span: span,
-        }
-    };
-
-    // ast for `read_struct($(name), |__d| $(fields))`
-    let body = cx.expr_method_call(
-        span,
-        cx.expr_var(span, "__d"),
-        cx.ident_of("read_struct"),
-        ~[
-            cx.lit_str(span, @cx.str_of(ident)),
-            cx.lit_uint(span, vec::len(fields)),
-            cx.lambda_expr_1(
-                cx.expr(
-                    span,
-                    ast::expr_struct(
-                        cx.path(span, ~[ident]),
-                        fields,
-                        None
-                    )
-                ),
-                cx.ident_of("__d")
-            ),
-        ]
-    );
-
-    mk_deser_impl(cx, span, ident, generics, body)
-}
-
-// Records and structs don't have the same fields types, but they share enough
-// that if we extract the right subfields out we can share the code
-// generator code.
-struct field {
-    span: span,
-    ident: ast::ident,
-    mutbl: ast::mutability,
-}
-
-fn mk_struct_fields(fields: &[@ast::struct_field]) -> ~[field] {
-    do fields.map |field| {
-        let ident = match field.node.kind {
-            ast::named_field(ident, _) => ident,
-            _ => fail!(~"[auto_encode] does not support unnamed fields")
-        };
-
-        field {
-            span: field.span,
-            ident: ident,
-            mutbl: ast::m_imm,
-        }
-    }
-}
-
-fn mk_enum_ser_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    enum_def: ast::enum_def,
-    generics: &ast::Generics
-) -> @ast::item {
-    let body = mk_enum_ser_body(
-        cx,
-        span,
-        ident,
-        copy enum_def.variants
-    );
-
-    mk_ser_impl(cx, span, ident, generics, body)
-}
-
-fn mk_enum_deser_impl(
-    cx: @ext_ctxt,
-    span: span,
-    ident: ast::ident,
-    enum_def: ast::enum_def,
-    generics: &ast::Generics
-) -> @ast::item {
-    let body = mk_enum_deser_body(
-        cx,
-        span,
-        ident,
-        enum_def.variants
-    );
-
-    mk_deser_impl(cx, span, ident, generics, body)
-}
-
-fn ser_variant(
-    cx: @ext_ctxt,
-    span: span,
-    v_name: ast::ident,
-    v_idx: uint,
-    args: ~[ast::variant_arg]
-) -> ast::arm {
-    // Name the variant arguments.
-    let names = args.mapi(|i, _arg| cx.ident_of(fmt!("__v%u", i)));
-
-    // Bind the names to the variant argument type.
-    let pats = args.mapi(|i, arg| cx.binder_pat(arg.ty.span, names[i]));
-
-    let pat_node = if pats.is_empty() {
-        ast::pat_ident(
-            ast::bind_infer,
-            cx.path(span, ~[v_name]),
-            None
-        )
-    } else {
-        ast::pat_enum(
-            cx.path(span, ~[v_name]),
-            Some(pats)
-        )
-    };
-
-    let pat = @ast::pat {
-        id: cx.next_id(),
-        node: pat_node,
-        span: span,
-    };
-
-    let stmts = do args.mapi |a_idx, _arg| {
-        // ast for `__s.emit_enum_variant_arg`
-        let expr_emit = cx.expr_field(
-            span,
-            cx.expr_var(span, "__s"),
-            cx.ident_of("emit_enum_variant_arg")
-        );
-
-        // ast for `|__s| $(v).encode(__s)`
-        let expr_encode = cx.lambda_expr_1(
-            cx.expr_method_call(
-                span,
-                 cx.expr_path(span, ~[names[a_idx]]),
-                 cx.ident_of("encode"),
-                ~[cx.expr_var(span, "__s")]
-            ),
-            cx.ident_of("__s")
-        );
-
-        // ast for `$(expr_emit)($(a_idx), $(expr_encode))`
-        cx.stmt(
-            cx.expr_call(
-                span,
-                expr_emit,
-                ~[cx.lit_uint(span, a_idx), expr_encode]
-            )
-        )
-    };
-
-    // ast for `__s.emit_enum_variant($(name), $(idx), $(sz), $(lambda))`
-    let body = cx.expr_method_call(
-        span,
-        cx.expr_var(span, "__s"),
-        cx.ident_of("emit_enum_variant"),
-        ~[
-            cx.lit_str(span, @cx.str_of(v_name)),
-            cx.lit_uint(span, v_idx),
-            cx.lit_uint(span, stmts.len()),
-            cx.lambda_stmts_1(span, stmts, cx.ident_of("__s")),
-        ]
-    );
-
-    ast::arm { pats: ~[pat], guard: None, body: cx.expr_blk(body) }
-}
-
-fn mk_enum_ser_body(
-    cx: @ext_ctxt,
-    span: span,
-    name: ast::ident,
-    variants: ~[ast::variant]
-) -> @ast::expr {
-    let arms = do variants.mapi |v_idx, variant| {
-        match variant.node.kind {
-            ast::tuple_variant_kind(ref args) =>
-                ser_variant(
-                    cx,
-                    span,
-                    variant.node.name,
-                    v_idx,
-                    /*bad*/ copy *args
-                ),
-            ast::struct_variant_kind(*) =>
-                fail!(~"struct variants unimplemented"),
-        }
-    };
-
-    // ast for `match *self { $(arms) }`
-    let match_expr = cx.expr(
-        span,
-        ast::expr_match(
-            cx.expr(
-                span,
-                ast::expr_unary(ast::deref, cx.expr_var(span, "self"))
-            ),
-            arms
-        )
-    );
-
-    // ast for `__s.emit_enum($(name), || $(match_expr))`
-    cx.expr_method_call(
-        span,
-        cx.expr_var(span, "__s"),
-        cx.ident_of("emit_enum"),
-        ~[
-            cx.lit_str(span, @cx.str_of(name)),
-            cx.lambda_expr_1(match_expr, cx.ident_of("__s")),
-        ]
-    )
-}
-
-fn mk_enum_deser_variant_nary(
-    cx: @ext_ctxt,
-    span: span,
-    name: ast::ident,
-    args: ~[ast::variant_arg]
-) -> @ast::expr {
-    let args = do args.mapi |idx, _arg| {
-        // ast for `|__s| std::serialize::decode(__d)`
-        let expr_lambda = cx.lambda_expr_1(
-            cx.expr_call(
-                span,
-                cx.expr_path_global(span, ~[
-                    cx.ident_of("std"),
-                    cx.ident_of("serialize"),
-                    cx.ident_of("Decodable"),
-                    cx.ident_of("decode"),
-                ]),
-                ~[cx.expr_var(span, "__d")]
-            ),
-            cx.ident_of("__d")
-        );
-
-        // ast for `__d.read_enum_variant_arg($(a_idx), $(expr_lambda))`
-        cx.expr_method_call(
-            span,
-            cx.expr_var(span, "__d"),
-            cx.ident_of("read_enum_variant_arg"),
-            ~[cx.lit_uint(span, idx), expr_lambda]
-        )
-    };
-
-    // ast for `$(name)($(args))`
-    cx.expr_call(span, cx.expr_path(span, ~[name]), args)
-}
-
-fn mk_enum_deser_body(
-    ext_cx: @ext_ctxt,
-    span: span,
-    name: ast::ident,
-    variants: ~[ast::variant]
-) -> @ast::expr {
-    let expr_arm_names = build::mk_base_vec_e(
-        ext_cx,
-        span,
-         do variants.map |variant| {
-            build::mk_base_str(
-                ext_cx,
-                span,
-                ext_cx.str_of(variant.node.name)
-            )
-        }
-    );
-
-    let mut arms = do variants.mapi |v_idx, variant| {
-        let body = match variant.node.kind {
-            ast::tuple_variant_kind(ref args) => {
-                if args.is_empty() {
-                    // for a nullary variant v, do "v"
-                    ext_cx.expr_path(span, ~[variant.node.name])
-                } else {
-                    // for an n-ary variant v, do "v(a_1, ..., a_n)"
-                    mk_enum_deser_variant_nary(
-                        ext_cx,
-                        span,
-                        variant.node.name,
-                        copy *args
-                    )
-                }
-            },
-            ast::struct_variant_kind(*) =>
-                fail!(~"struct variants unimplemented"),
-        };
-
-        let pat = @ast::pat {
-            id: ext_cx.next_id(),
-            node: ast::pat_lit(ext_cx.lit_uint(span, v_idx)),
-            span: span,
-        };
-
-        ast::arm {
-            pats: ~[pat],
-            guard: None,
-            body: ext_cx.expr_blk(body),
-        }
-    };
-
-    let quoted_expr = copy quote_expr!(
-      ::core::sys::FailWithCause::fail_with("explicit failure", "empty", 1);
-    ).node;
-
-    let impossible_case = ast::arm {
-        pats: ~[@ast::pat {
-            id: ext_cx.next_id(),
-            node: ast::pat_wild,
-            span: span,
-        }],
-        guard: None,
-
-        // FIXME(#3198): proper error message
-        body: ext_cx.expr_blk(ext_cx.expr(span, quoted_expr)),
-    };
-
-    arms.push(impossible_case);
-
-    // ast for `|i| { match i { $(arms) } }`
-    let expr_lambda = ext_cx.expr(
-        span,
-        ast::expr_fn_block(
-            ast::fn_decl {
-                inputs: ~[
-                    ast::arg {
-                        is_mutbl: false,
-                        ty: @ast::Ty {
-                            id: ext_cx.next_id(),
-                            node: ast::ty_infer,
-                            span: span
-                        },
-                        pat: @ast::pat {
-                            id: ext_cx.next_id(),
-                            node: ast::pat_ident(
-                                ast::bind_by_copy,
-                                ast_util::ident_to_path(span,
-                                    ext_cx.ident_of("__d")),
-                                None),
-                            span: span,
-                        },
-                        id: ext_cx.next_id(),
-                    },
-                    ast::arg {
-                        is_mutbl: false,
-                        ty: @ast::Ty {
-                            id: ext_cx.next_id(),
-                            node: ast::ty_infer,
-                            span: span
-                        },
-                        pat: @ast::pat {
-                            id: ext_cx.next_id(),
-                            node: ast::pat_ident(
-                                ast::bind_by_copy,
-                                ast_util::ident_to_path(span,
-                                    ext_cx.ident_of("i")),
-                                None),
-                            span: span,
-                        },
-                        id: ext_cx.next_id(),
-                    }
-                ],
-                output: @ast::Ty {
-                    id: ext_cx.next_id(),
-                    node: ast::ty_infer,
-                    span: span,
-                },
-                cf: ast::return_val,
-            },
-            ext_cx.expr_blk(
-                ext_cx.expr(
-                    span,
-                    ast::expr_match(ext_cx.expr_var(span, "i"), arms)
-                )
-            )
-        )
-    );
-
-    // ast for `__d.read_enum_variant($expr_arm_names, $(expr_lambda))`
-    let expr_lambda = ext_cx.lambda_expr_1(
-        ext_cx.expr_method_call(
-            span,
-            ext_cx.expr_var(span, "__d"),
-            ext_cx.ident_of("read_enum_variant"),
-            ~[expr_arm_names, expr_lambda]
-        ),
-        ext_cx.ident_of("__d")
-    );
-
-    // ast for `__d.read_enum($(e_name), $(expr_lambda))`
-    ext_cx.expr_method_call(
-        span,
-        ext_cx.expr_var(span, "__d"),
-        ext_cx.ident_of("read_enum"),
-        ~[
-            ext_cx.lit_str(span, @ext_cx.str_of(name)),
-            expr_lambda
-        ]
-    )
-}
-
-#[cfg(test)]
-mod test {
-    use core::option::{None, Some};
-    use std::serialize::Encodable;
-    use std::serialize::Encoder;
-
-    // just adding the ones I want to test, for now:
-    #[deriving(Eq)]
-    pub enum call {
-        CallToEmitEnum(~str),
-        CallToEmitEnumVariant(~str, uint, uint),
-        CallToEmitEnumVariantArg(uint),
-        CallToEmitUint(uint),
-        CallToEmitNil,
-        CallToEmitStruct(~str,uint),
-        CallToEmitField(~str,uint),
-        CallToEmitOption,
-        CallToEmitOptionNone,
-        CallToEmitOptionSome,
-        // all of the ones I was too lazy to handle:
-        CallToOther
-    }
-    // using `@mut` rather than changing the
-    // type of self in every method of every encoder everywhere.
-    pub struct TestEncoder {call_log : @mut ~[call]}
-
-    pub impl TestEncoder {
-        // these self's should be &mut self's, as well....
-        fn add_to_log (&self, c : call) {
-            self.call_log.push(copy c);
-        }
-        fn add_unknown_to_log (&self) {
-            self.add_to_log (CallToOther)
-        }
-    }
-
-    impl Encoder for TestEncoder {
-        fn emit_nil(&mut self) { self.add_to_log(CallToEmitNil) }
-
-        fn emit_uint(&mut self, v: uint) {
-            self.add_to_log(CallToEmitUint(v));
-        }
-        fn emit_u64(&mut self, _v: u64) { self.add_unknown_to_log(); }
-        fn emit_u32(&mut self, _v: u32) { self.add_unknown_to_log(); }
-        fn emit_u16(&mut self, _v: u16) { self.add_unknown_to_log(); }
-        fn emit_u8(&mut self, _v: u8)   { self.add_unknown_to_log(); }
-
-        fn emit_int(&mut self, _v: int) { self.add_unknown_to_log(); }
-        fn emit_i64(&mut self, _v: i64) { self.add_unknown_to_log(); }
-        fn emit_i32(&mut self, _v: i32) { self.add_unknown_to_log(); }
-        fn emit_i16(&mut self, _v: i16) { self.add_unknown_to_log(); }
-        fn emit_i8(&mut self, _v: i8)   { self.add_unknown_to_log(); }
-
-        fn emit_bool(&mut self, _v: bool) { self.add_unknown_to_log(); }
-
-        fn emit_f64(&mut self, _v: f64) { self.add_unknown_to_log(); }
-        fn emit_f32(&mut self, _v: f32) { self.add_unknown_to_log(); }
-        fn emit_float(&mut self, _v: float) { self.add_unknown_to_log(); }
-
-        fn emit_char(&mut self, _v: char) { self.add_unknown_to_log(); }
-        fn emit_str(&mut self, _v: &str) { self.add_unknown_to_log(); }
-
-        fn emit_enum(&mut self, name: &str, f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitEnum(name.to_str()));
-            f(self);
-        }
-
-        fn emit_enum_variant(&mut self,
-                             name: &str,
-                             id: uint,
-                             cnt: uint,
-                             f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitEnumVariant(name.to_str(), id, cnt));
-            f(self);
-        }
-
-        fn emit_enum_variant_arg(&mut self,
-                                 idx: uint,
-                                 f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitEnumVariantArg(idx));
-            f(self);
-        }
-
-        fn emit_enum_struct_variant(&mut self,
-                                    name: &str,
-                                    id: uint,
-                                    cnt: uint,
-                                    f: &fn(&mut TestEncoder)) {
-            self.emit_enum_variant(name, id, cnt, f)
-        }
-
-        fn emit_enum_struct_variant_field(&mut self,
-                                          _name: &str,
-                                          idx: uint,
-                                          f: &fn(&mut TestEncoder)) {
-            self.emit_enum_variant_arg(idx, f)
-        }
-
-        fn emit_struct(&mut self,
-                       name: &str,
-                       len: uint,
-                       f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitStruct (name.to_str(),len));
-            f(self);
-        }
-        fn emit_struct_field(&mut self,
-                             name: &str,
-                             idx: uint,
-                             f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitField (name.to_str(),idx));
-            f(self);
-        }
-
-        fn emit_tuple(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-        fn emit_tuple_arg(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-
-        fn emit_tuple_struct(&mut self,
-                             _name: &str,
-                             _len: uint,
-                             f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-
-        fn emit_tuple_struct_arg(&mut self,
-                                 _idx: uint,
-                                 f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-
-        fn emit_option(&mut self, f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitOption);
-            f(self);
-        }
-        fn emit_option_none(&mut self) {
-            self.add_to_log(CallToEmitOptionNone);
-        }
-        fn emit_option_some(&mut self, f: &fn(&mut TestEncoder)) {
-            self.add_to_log(CallToEmitOptionSome);
-            f(self);
-        }
-
-        fn emit_seq(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-        fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-
-        fn emit_map(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-        fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-        fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
-            self.add_unknown_to_log();
-            f(self);
-        }
-    }
-
-
-    fn to_call_log<E:Encodable<TestEncoder>>(val: E) -> ~[call] {
-        let mut te = TestEncoder {
-            call_log: @mut ~[]
-        };
-        val.encode(&mut te);
-        copy *te.call_log
-    }
-
-    #[auto_encode]
-    enum Written {
-        Book(uint,uint),
-        Magazine(~str)
-    }
-
-    #[test]
-    fn test_encode_enum() {
-        assert_eq!(
-            to_call_log(Book(34,44)),
-            ~[
-                CallToEmitEnum(~"Written"),
-                CallToEmitEnumVariant(~"Book",0,2),
-                CallToEmitEnumVariantArg(0),
-                CallToEmitUint(34),
-                CallToEmitEnumVariantArg(1),
-                CallToEmitUint(44),
-            ]
-        );
-    }
-
-    pub struct BPos(uint);
-
-    #[auto_encode]
-    pub struct HasPos { pos : BPos }
-
-    #[test]
-    fn test_encode_newtype() {
-        assert_eq!(
-            to_call_log(HasPos { pos:BPos(48) }),
-            ~[
-                CallToEmitStruct(~"HasPos",1),
-                CallToEmitField(~"pos",0),
-                CallToEmitUint(48),
-            ]
-        );
-    }
-
-    #[test]
-    fn test_encode_option() {
-        let mut v = None;
-
-        assert_eq!(
-            to_call_log(v),
-            ~[
-                CallToEmitOption,
-                CallToEmitOptionNone,
-            ]
-        );
-
-        v = Some(54u);
-        assert_eq!(
-            to_call_log(v),
-            ~[
-                CallToEmitOption,
-                CallToEmitOptionSome,
-                CallToEmitUint(54)
-            ]
-        );
-    }
+    cx.span_err(span, "`#[auto_decode]` is deprecated, use `#[deriving(Decodable)]` instead");
+    in_items
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 95e858f6143..a97c69ba4ff 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -139,6 +139,8 @@ pub fn syntax_expander_table() -> SyntaxEnv {
         @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
     syntax_expanders.insert(@~"env",
                             builtin_normal_tt(ext::env::expand_syntax_ext));
+    syntax_expanders.insert(@~"bytes",
+                            builtin_normal_tt(ext::bytes::expand_syntax_ext));
     syntax_expanders.insert(@~"concat_idents",
                             builtin_normal_tt(
                                 ext::concat_idents::expand_syntax_ext));
@@ -148,15 +150,6 @@ pub fn syntax_expander_table() -> SyntaxEnv {
     syntax_expanders.insert(@~"deriving",
                             @SE(ItemDecorator(
                                 ext::deriving::expand_meta_deriving)));
-    syntax_expanders.insert(@~"deriving_eq",
-                            @SE(ItemDecorator(
-                                ext::deriving::eq::expand_deriving_obsolete)));
-    syntax_expanders.insert(@~"deriving_iter_bytes",
-                            @SE(ItemDecorator(
-                                ext::deriving::iter_bytes::expand_deriving_obsolete)));
-    syntax_expanders.insert(@~"deriving_clone",
-                            @SE(ItemDecorator(
-                                ext::deriving::clone::expand_deriving_obsolete)));
 
     // Quasi-quoting expanders
     syntax_expanders.insert(@~"quote_tokens",
@@ -351,7 +344,7 @@ pub fn expr_to_ident(cx: @ext_ctxt,
                      err_msg: &str) -> ast::ident {
     match expr.node {
       ast::expr_path(p) => {
-        if vec::len(p.types) > 0u || vec::len(p.idents) != 1u {
+        if p.types.len() > 0u || p.idents.len() != 1u {
             cx.span_fatal(expr.span, err_msg);
         }
         return p.idents[0];
@@ -479,11 +472,11 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
     // names? I think not.
     // delaying implementing this....
     fn each_key (&self, _f: &fn (&K)->bool) {
-        fail!(~"unimplemented 2013-02-15T10:01");
+        fail!("unimplemented 2013-02-15T10:01");
     }
 
     fn each_value (&self, _f: &fn (&V) -> bool) {
-        fail!(~"unimplemented 2013-02-15T10:02");
+        fail!("unimplemented 2013-02-15T10:02");
     }
 
     // Returns a copy of the value that the name maps to.
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 3bfb93b34b3..624e0495e59 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -196,6 +196,7 @@ pub fn mk_global_struct_e(cx: @ext_ctxt,
 }
 pub fn mk_glob_use(cx: @ext_ctxt,
                    sp: span,
+                   vis: ast::visibility,
                    path: ~[ast::ident]) -> @ast::view_item {
     let glob = @codemap::spanned {
         node: ast::view_path_glob(mk_raw_path(sp, path), cx.next_id()),
@@ -203,7 +204,7 @@ pub fn mk_glob_use(cx: @ext_ctxt,
     };
     @ast::view_item { node: ast::view_item_use(~[glob]),
                       attrs: ~[],
-                      vis: ast::private,
+                      vis: vis,
                       span: sp }
 }
 pub fn mk_local(cx: @ext_ctxt, sp: span, mutbl: bool,
@@ -509,7 +510,7 @@ pub fn mk_unreachable(cx: @ext_ctxt, span: span) -> @ast::expr {
         ],
         ~[
             mk_base_str(cx, span, ~"internal error: entered unreachable code"),
-            mk_base_str(cx, span, loc.file.name),
+            mk_base_str(cx, span, copy loc.file.name),
             mk_uint(cx, span, loc.line),
         ]
     )
@@ -518,6 +519,10 @@ pub fn mk_unreachable_arm(cx: @ext_ctxt, span: span) -> ast::arm {
     mk_arm(cx, span, ~[mk_pat_wild(cx, span)], mk_unreachable(cx, span))
 }
 
+pub fn make_self(cx: @ext_ctxt, span: span) -> @ast::expr {
+    build::mk_expr(cx, span, ast::expr_self)
+}
+
 //
 // Duplication functions
 //
@@ -534,3 +539,301 @@ pub fn duplicate_expr(cx: @ext_ctxt, expr: @ast::expr) -> @ast::expr {
     folder.fold_expr(expr)
 }
 
+
+
+// Transitional reexports so qquote can find the paths it is looking for
+mod syntax {
+    pub use ext;
+    pub use parse;
+}
+
+trait ExtCtxtMethods {
+    fn bind_path(&self,
+                 span: span,
+                 ident: ast::ident,
+                 path: @ast::Path,
+                 bounds: @OptVec<ast::TyParamBound>)
+                 -> ast::TyParam;
+    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr;
+    fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
+    fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
+    fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
+                -> @ast::Path;
+    fn path_tps_global(&self,
+                       span: span,
+                       strs: ~[ast::ident],
+                       tps: ~[@ast::Ty])
+                       -> @ast::Path;
+    fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
+               -> @ast::Ty;
+    fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat;
+    fn stmt(&self, expr: @ast::expr) -> @ast::stmt;
+    fn lit_str(&self, span: span, s: @~str) -> @ast::expr;
+    fn lit_uint(&self, span: span, i: uint) -> @ast::expr;
+    fn lambda0(&self, blk: ast::blk) -> @ast::expr;
+    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr;
+    fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk;
+    fn expr_blk(&self, expr: @ast::expr) -> ast::blk;
+    fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
+    fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
+    fn expr_var(&self, span: span, var: &str) -> @ast::expr;
+    fn expr_self(&self, span: span) -> @ast::expr;
+    fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident)
+                  -> @ast::expr;
+    fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr])
+                 -> @ast::expr;
+    fn expr_method_call(&self,
+                        span: span,
+                        expr: @ast::expr,
+                        ident: ast::ident,
+                        args: ~[@ast::expr])
+                        -> @ast::expr;
+    fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr;
+    fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
+                    -> @ast::expr;
+    fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr;
+    fn lambda_stmts_1(&self,
+                      span: span,
+                      stmts: ~[@ast::stmt],
+                      ident: ast::ident)
+                      -> @ast::expr;
+}
+
+impl ExtCtxtMethods for @ext_ctxt {
+    fn bind_path(
+        &self,
+        _span: span,
+        ident: ast::ident,
+        path: @ast::Path,
+        bounds: @OptVec<ast::TyParamBound>
+    ) -> ast::TyParam {
+        let bound = ast::TraitTyParamBound(@ast::trait_ref {
+            ref_id: self.next_id(),
+            path: path
+        });
+
+        ast::TyParam {
+            ident: ident,
+            id: self.next_id(),
+            bounds: @bounds.prepend(bound)
+        }
+    }
+
+    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr {
+        @ast::expr {
+            id: self.next_id(),
+            callee_id: self.next_id(),
+            node: node,
+            span: span,
+        }
+    }
+
+    fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path {
+        @ast::Path {
+            span: span,
+            global: false,
+            idents: strs,
+            rp: None,
+            types: ~[]
+        }
+    }
+
+    fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path {
+        @ast::Path {
+            span: span,
+            global: true,
+            idents: strs,
+            rp: None,
+            types: ~[]
+        }
+    }
+
+    fn path_tps(
+        &self,
+        span: span,
+        strs: ~[ast::ident],
+        tps: ~[@ast::Ty]
+    ) -> @ast::Path {
+        @ast::Path {
+            span: span,
+            global: false,
+            idents: strs,
+            rp: None,
+            types: tps
+        }
+    }
+
+    fn path_tps_global(
+        &self,
+        span: span,
+        strs: ~[ast::ident],
+        tps: ~[@ast::Ty]
+    ) -> @ast::Path {
+        @ast::Path {
+            span: span,
+            global: true,
+            idents: strs,
+            rp: None,
+            types: tps
+        }
+    }
+
+    fn ty_path(
+        &self,
+        span: span,
+        strs: ~[ast::ident],
+        tps: ~[@ast::Ty]
+    ) -> @ast::Ty {
+        @ast::Ty {
+            id: self.next_id(),
+            node: ast::ty_path(
+                self.path_tps(span, strs, tps),
+                self.next_id()),
+            span: span,
+        }
+    }
+
+    fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat {
+        @ast::pat {
+            id: self.next_id(),
+            node: ast::pat_ident(
+                ast::bind_by_ref(ast::m_imm),
+                self.path(span, ~[nm]),
+                None),
+            span: span,
+        }
+    }
+
+    fn stmt(&self, expr: @ast::expr) -> @ast::stmt {
+        @codemap::spanned { node: ast::stmt_semi(expr, self.next_id()),
+                       span: expr.span }
+    }
+
+    fn lit_str(&self, span: span, s: @~str) -> @ast::expr {
+        self.expr(
+            span,
+            ast::expr_vstore(
+                self.expr(
+                    span,
+                    ast::expr_lit(
+                        @codemap::spanned { node: ast::lit_str(s),
+                                        span: span})),
+                ast::expr_vstore_uniq))
+    }
+
+    fn lit_uint(&self, span: span, i: uint) -> @ast::expr {
+        self.expr(
+            span,
+            ast::expr_lit(
+                @codemap::spanned { node: ast::lit_uint(i as u64, ast::ty_u),
+                                span: span}))
+    }
+
+    fn lambda0(&self, blk: ast::blk) -> @ast::expr {
+        let ext_cx = *self;
+        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
+        quote_expr!( || $blk_e )
+    }
+
+    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr {
+        let ext_cx = *self;
+        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
+        quote_expr!( |$ident| $blk_e )
+    }
+
+    fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk {
+        codemap::spanned {
+            node: ast::blk_ {
+                view_items: ~[],
+                stmts: stmts,
+                expr: None,
+                id: self.next_id(),
+                rules: ast::default_blk,
+            },
+            span: span,
+        }
+    }
+
+    fn expr_blk(&self, expr: @ast::expr) -> ast::blk {
+        codemap::spanned {
+            node: ast::blk_ {
+                view_items: ~[],
+                stmts: ~[],
+                expr: Some(expr),
+                id: self.next_id(),
+                rules: ast::default_blk,
+            },
+            span: expr.span,
+        }
+    }
+
+    fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr {
+        self.expr(span, ast::expr_path(self.path(span, strs)))
+    }
+
+    fn expr_path_global(
+        &self,
+        span: span,
+        strs: ~[ast::ident]
+    ) -> @ast::expr {
+        self.expr(span, ast::expr_path(self.path_global(span, strs)))
+    }
+
+    fn expr_var(&self, span: span, var: &str) -> @ast::expr {
+        self.expr_path(span, ~[self.ident_of(var)])
+    }
+
+    fn expr_self(&self, span: span) -> @ast::expr {
+        self.expr(span, ast::expr_self)
+    }
+
+    fn expr_field(
+        &self,
+        span: span,
+        expr: @ast::expr,
+        ident: ast::ident
+    ) -> @ast::expr {
+        self.expr(span, ast::expr_field(expr, ident, ~[]))
+    }
+
+    fn expr_call(
+        &self,
+        span: span,
+        expr: @ast::expr,
+        args: ~[@ast::expr]
+    ) -> @ast::expr {
+        self.expr(span, ast::expr_call(expr, args, ast::NoSugar))
+    }
+
+    fn expr_method_call(
+        &self,
+        span: span,
+        expr: @ast::expr,
+        ident: ast::ident,
+        args: ~[@ast::expr]
+    ) -> @ast::expr {
+        self.expr(span,
+                  ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar))
+    }
+
+    fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr {
+        self.lambda0(self.expr_blk(expr))
+    }
+
+    fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
+                    -> @ast::expr {
+        self.lambda1(self.expr_blk(expr), ident)
+    }
+
+    fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
+        self.lambda0(self.blk(span, stmts))
+    }
+
+    fn lambda_stmts_1(&self,
+                      span: span,
+                      stmts: ~[@ast::stmt],
+                      ident: ast::ident)
+                      -> @ast::expr {
+        self.lambda1(self.blk(span, stmts), ident)
+    }
+}
diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
new file mode 100644
index 00000000000..03020f26a93
--- /dev/null
+++ b/src/libsyntax/ext/bytes.rs
@@ -0,0 +1,28 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/* The compiler code necessary to support the bytes! extension. */
+
+use ast;
+use codemap::span;
+use ext::base::*;
+use ext::base;
+use ext::build::{mk_u8, mk_slice_vec_e};
+
+pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
+    -> base::MacResult {
+    let var = get_single_str_from_tts(cx, sp, tts, "bytes!");
+    let mut bytes = ~[];
+    for var.each |byte| {
+        bytes.push(mk_u8(cx, sp, byte));
+    }
+    let e = mk_slice_vec_e(cx, sp, bytes);
+    MRExpr(e)
+}
diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs
index 1c33fe35070..aceb60ebbd7 100644
--- a/src/libsyntax/ext/deriving/clone.rs
+++ b/src/libsyntax/ext/deriving/clone.rs
@@ -28,11 +28,11 @@ pub fn expand_deriving_clone(cx: @ext_ctxt,
             MethodDef {
                 name: ~"clone",
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[],
                 ret_ty: Self,
                 const_nonmatching: false,
-                combine_substructure: cs_clone
+                combine_substructure: |c, s, sub| cs_clone("Clone", c, s, sub)
             }
         ]
     };
@@ -42,17 +42,39 @@ pub fn expand_deriving_clone(cx: @ext_ctxt,
                             &trait_def)
 }
 
-pub fn expand_deriving_obsolete(cx: @ext_ctxt,
-                                span: span,
-                                _mitem: @meta_item,
-                                in_items: ~[@item])
-                             -> ~[@item] {
-    cx.span_err(span, ~"`#[deriving_clone]` is obsolete; use `#[deriving(Clone)]` instead");
-    in_items
+pub fn expand_deriving_deep_clone(cx: @ext_ctxt,
+                                 span: span,
+                                 mitem: @meta_item,
+                                 in_items: ~[@item])
+    -> ~[@item] {
+    let trait_def = TraitDef {
+        path: Path::new(~[~"core", ~"clone", ~"DeepClone"]),
+        additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
+        methods: ~[
+            MethodDef {
+                name: ~"deep_clone",
+                generics: LifetimeBounds::empty(),
+                explicit_self: borrowed_explicit_self(),
+                args: ~[],
+                ret_ty: Self,
+                const_nonmatching: false,
+                // cs_clone uses the ident passed to it, i.e. it will
+                // call deep_clone (not clone) here.
+                combine_substructure: |c, s, sub| cs_clone("DeepClone", c, s, sub)
+            }
+        ]
+    };
+
+    expand_deriving_generic(cx, span,
+                            mitem, in_items,
+                            &trait_def)
 }
 
-fn cs_clone(cx: @ext_ctxt, span: span,
-            substr: &Substructure) -> @expr {
+fn cs_clone(
+    name: &str,
+    cx: @ext_ctxt, span: span,
+    substr: &Substructure) -> @expr {
     let clone_ident = substr.method_ident;
     let ctor_ident;
     let all_fields;
@@ -60,19 +82,23 @@ fn cs_clone(cx: @ext_ctxt, span: span,
         build::mk_method_call(cx, span, field, clone_ident, ~[]);
 
     match *substr.fields {
-        Struct(af) => {
+        Struct(ref af) => {
             ctor_ident = ~[ substr.type_ident ];
             all_fields = af;
         }
-        EnumMatching(_, variant, af) => {
+        EnumMatching(_, variant, ref af) => {
             ctor_ident = ~[ variant.node.name ];
             all_fields = af;
         },
-        EnumNonMatching(*) => cx.span_bug(span, "Non-matching enum variants in `deriving(Clone)`"),
-        StaticEnum(*) | StaticStruct(*) => cx.span_bug(span, "Static method in `deriving(Clone)`")
+        EnumNonMatching(*) => cx.span_bug(span,
+                                          fmt!("Non-matching enum variants in `deriving(%s)`",
+                                               name)),
+        StaticEnum(*) | StaticStruct(*) => cx.span_bug(span,
+                                                       fmt!("Static method in `deriving(%s)`",
+                                                            name))
     }
 
-    match all_fields {
+    match *all_fields {
         [(None, _, _), .. _] => {
             // enum-like
             let subcalls = all_fields.map(|&(_, self_f, _)| subcall(self_f));
@@ -84,8 +110,8 @@ fn cs_clone(cx: @ext_ctxt, span: span,
                 let ident = match o_id {
                     Some(i) => i,
                     None => cx.span_bug(span,
-                                        ~"unnamed field in normal struct \
-                                          in `deriving(Clone)`")
+                                        fmt!("unnamed field in normal struct in `deriving(%s)`",
+                                             name))
                 };
                 build::Field { ident: ident, ex: subcall(self_f) }
             };
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs
index e431e1f78bf..3d93f844ea3 100644
--- a/src/libsyntax/ext/deriving/cmp/eq.rs
+++ b/src/libsyntax/ext/deriving/cmp/eq.rs
@@ -34,7 +34,7 @@ pub fn expand_deriving_eq(cx: @ext_ctxt,
             MethodDef {
                 name: $name,
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[borrowed_self()],
                 ret_ty: Literal(Path::new(~[~"bool"])),
                 const_nonmatching: true,
@@ -56,11 +56,3 @@ pub fn expand_deriving_eq(cx: @ext_ctxt,
     expand_deriving_generic(cx, span, mitem, in_items,
                             &trait_def)
 }
-
-pub fn expand_deriving_obsolete(cx: @ext_ctxt,
-                                span: span,
-                                _mitem: @meta_item,
-                                in_items: ~[@item]) -> ~[@item] {
-    cx.span_err(span, ~"`#[deriving_eq]` is obsolete; use `#[deriving(Eq)]` instead");
-    in_items
-}
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs
index a9234c858f4..5445aef4491 100644
--- a/src/libsyntax/ext/deriving/cmp/ord.rs
+++ b/src/libsyntax/ext/deriving/cmp/ord.rs
@@ -24,7 +24,7 @@ pub fn expand_deriving_ord(cx: @ext_ctxt,
             MethodDef {
                 name: $name,
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[borrowed_self()],
                 ret_ty: Literal(Path::new(~[~"bool"])),
                 const_nonmatching: false,
@@ -65,8 +65,6 @@ fn cs_ord(less: bool, equal: bool,
     let false_blk_expr = build::mk_block(cx, span,
                                          ~[], ~[],
                                          Some(build::mk_bool(cx, span, false)));
-    let true_blk = build::mk_simple_block(cx, span,
-                                          build::mk_bool(cx, span, true));
     let base = build::mk_bool(cx, span, equal);
 
     cs_fold(
@@ -108,6 +106,8 @@ fn cs_ord(less: bool, equal: bool,
 
             let cmp = build::mk_method_call(cx, span,
                                             self_f, binop, other_fs.to_owned());
+            let true_blk = build::mk_simple_block(cx, span,
+                                                  build::mk_bool(cx, span, true));
             let if_ = expr_if(cmp, true_blk, Some(elseif));
 
             build::mk_expr(cx, span, if_)
diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs
index 068a7bc06b1..4541569b829 100644
--- a/src/libsyntax/ext/deriving/cmp/totaleq.rs
+++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs
@@ -33,7 +33,7 @@ pub fn expand_deriving_totaleq(cx: @ext_ctxt,
             MethodDef {
                 name: ~"equals",
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[borrowed_self()],
                 ret_ty: Literal(Path::new(~[~"bool"])),
                 const_nonmatching: true,
diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs
index 7d560a197d0..8f156e6a9e3 100644
--- a/src/libsyntax/ext/deriving/cmp/totalord.rs
+++ b/src/libsyntax/ext/deriving/cmp/totalord.rs
@@ -27,7 +27,7 @@ pub fn expand_deriving_totalord(cx: @ext_ctxt,
             MethodDef {
                 name: ~"cmp",
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[borrowed_self()],
                 ret_ty: Literal(Path::new(~[~"core", ~"cmp", ~"Ordering"])),
                 const_nonmatching: false,
@@ -55,15 +55,16 @@ pub fn ordering_const(cx: @ext_ctxt, span: span, cnst: Ordering) -> @expr {
 
 pub fn cs_cmp(cx: @ext_ctxt, span: span,
               substr: &Substructure) -> @expr {
-    let lexical_ord = ~[cx.ident_of("core"),
-                        cx.ident_of("cmp"),
-                        cx.ident_of("lexical_ordering")];
 
     cs_same_method_fold(
         // foldr (possibly) nests the matches in lexical_ordering better
         false,
         |cx, span, old, new| {
-            build::mk_call_global(cx, span, lexical_ord, ~[old, new])
+            build::mk_call_global(cx, span,
+                                  ~[cx.ident_of("core"),
+                                    cx.ident_of("cmp"),
+                                    cx.ident_of("lexical_ordering")],
+                                  ~[old, new])
         },
         ordering_const(cx, span, Equal),
         |cx, span, list, _| {
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index fd5d26a1787..2e2f382a768 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -8,6 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*!
+The compiler code necessary for #[deriving(Decodable)]. See
+encodable.rs for more.
+*/
+
 use ast;
 use ast::*;
 use ext::base::ext_ctxt;
@@ -119,13 +124,13 @@ fn create_decode_method(
     let body_block = build::mk_simple_block(cx, span, expr);
 
     // Create the method.
-    let self_ty = spanned { node: sty_static, span: span };
+    let explicit_self = spanned { node: sty_static, span: span };
     let method_ident = cx.ident_of("decode");
     @ast::method {
         ident: method_ident,
         attrs: ~[],
         generics: ast_util::empty_generics(),
-        self_ty: self_ty,
+        explicit_self: explicit_self,
         purity: impure_fn,
         decl: fn_decl,
         body: body_block,
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 2786c9c6eb5..8a1c3933f51 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -8,6 +8,74 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*!
+
+The compiler code necessary to implement the #[deriving(Encodable)]
+(and Decodable, in decodable.rs) extension.  The idea here is that
+type-defining items may be tagged with #[deriving(Encodable,
+Decodable)].
+
+For example, a type like:
+
+    #[deriving(Encodable, Decodable)]
+    struct Node {id: uint}
+
+would generate two implementations like:
+
+impl<S:std::serialize::Encoder> Encodable<S> for Node {
+    fn encode(&self, s: &S) {
+        do s.emit_struct("Node", 1) {
+            s.emit_field("id", 0, || s.emit_uint(self.id))
+        }
+    }
+}
+
+impl<D:Decoder> Decodable for node_id {
+    fn decode(d: &D) -> Node {
+        do d.read_struct("Node", 1) {
+            Node {
+                id: d.read_field(~"x", 0, || decode(d))
+            }
+        }
+    }
+}
+
+Other interesting scenarios are whe the item has type parameters or
+references other non-built-in types.  A type definition like:
+
+    #[deriving(Encodable, Decodable)]
+    struct spanned<T> {node: T, span: span}
+
+would yield functions like:
+
+    impl<
+        S: Encoder,
+        T: Encodable<S>
+    > spanned<T>: Encodable<S> {
+        fn encode<S:Encoder>(s: &S) {
+            do s.emit_rec {
+                s.emit_field("node", 0, || self.node.encode(s));
+                s.emit_field("span", 1, || self.span.encode(s));
+            }
+        }
+    }
+
+    impl<
+        D: Decoder,
+        T: Decodable<D>
+    > spanned<T>: Decodable<D> {
+        fn decode(d: &D) -> spanned<T> {
+            do d.read_rec {
+                {
+                    node: d.read_field(~"node", 0, || decode(d)),
+                    span: d.read_field(~"span", 1, || decode(d)),
+                }
+            }
+        }
+    }
+*/
+
+
 use ast;
 use ast::*;
 use ext::base::ext_ctxt;
@@ -111,13 +179,13 @@ fn create_encode_method(
     let body_block = build::mk_block_(cx, span, statements);
 
     // Create the method.
-    let self_ty = spanned { node: sty_region(None, m_imm), span: span };
+    let explicit_self = spanned { node: sty_region(None, m_imm), span: span };
     let method_ident = cx.ident_of("encode");
     @ast::method {
         ident: method_ident,
         attrs: ~[],
         generics: ast_util::empty_generics(),
-        self_ty: self_ty,
+        explicit_self: explicit_self,
         purity: impure_fn,
         decl: fn_decl,
         body: body_block,
@@ -204,8 +272,6 @@ fn expand_deriving_encodable_struct_method(
     type_ident: ident,
     struct_def: &struct_def
 ) -> @method {
-    let self_ident = cx.ident_of("self");
-
     // Create the body of the method.
     let mut idx = 0;
     let mut statements = ~[];
@@ -213,12 +279,10 @@ fn expand_deriving_encodable_struct_method(
         match struct_field.node.kind {
             named_field(ident, _) => {
                 // Create the accessor for this field.
-                let self_field = build::mk_access(
-                    cx,
-                    span,
-                    ~[self_ident],
-                    ident
-                );
+                let self_field = build::mk_access_(cx,
+                                                   span,
+                                                   build::make_self(cx, span),
+                                                   ident);
 
                 // Call the substructure method.
                 let encode_expr = call_substructure_encode_method(
@@ -407,3 +471,247 @@ fn expand_deriving_encodable_enum_method(
     // Create the method.
     create_encode_method(cx, span, ~[stmt])
 }
+
+#[cfg(test)]
+mod test {
+    extern mod std;
+    use core::option::{None, Some};
+    use std::serialize::Encodable;
+    use std::serialize::Encoder;
+
+    // just adding the ones I want to test, for now:
+    #[deriving(Eq)]
+    pub enum call {
+        CallToEmitEnum(~str),
+        CallToEmitEnumVariant(~str, uint, uint),
+        CallToEmitEnumVariantArg(uint),
+        CallToEmitUint(uint),
+        CallToEmitNil,
+        CallToEmitStruct(~str,uint),
+        CallToEmitField(~str,uint),
+        CallToEmitOption,
+        CallToEmitOptionNone,
+        CallToEmitOptionSome,
+        // all of the ones I was too lazy to handle:
+        CallToOther
+    }
+    // using `@mut` rather than changing the
+    // type of self in every method of every encoder everywhere.
+    pub struct TestEncoder {call_log : @mut ~[call]}
+
+    pub impl TestEncoder {
+        // these self's should be &mut self's, as well....
+        fn add_to_log (&self, c : call) {
+            self.call_log.push(copy c);
+        }
+        fn add_unknown_to_log (&self) {
+            self.add_to_log (CallToOther)
+        }
+    }
+
+    impl Encoder for TestEncoder {
+        fn emit_nil(&mut self) { self.add_to_log(CallToEmitNil) }
+
+        fn emit_uint(&mut self, v: uint) {
+            self.add_to_log(CallToEmitUint(v));
+        }
+        fn emit_u64(&mut self, _v: u64) { self.add_unknown_to_log(); }
+        fn emit_u32(&mut self, _v: u32) { self.add_unknown_to_log(); }
+        fn emit_u16(&mut self, _v: u16) { self.add_unknown_to_log(); }
+        fn emit_u8(&mut self, _v: u8)   { self.add_unknown_to_log(); }
+
+        fn emit_int(&mut self, _v: int) { self.add_unknown_to_log(); }
+        fn emit_i64(&mut self, _v: i64) { self.add_unknown_to_log(); }
+        fn emit_i32(&mut self, _v: i32) { self.add_unknown_to_log(); }
+        fn emit_i16(&mut self, _v: i16) { self.add_unknown_to_log(); }
+        fn emit_i8(&mut self, _v: i8)   { self.add_unknown_to_log(); }
+
+        fn emit_bool(&mut self, _v: bool) { self.add_unknown_to_log(); }
+
+        fn emit_f64(&mut self, _v: f64) { self.add_unknown_to_log(); }
+        fn emit_f32(&mut self, _v: f32) { self.add_unknown_to_log(); }
+        fn emit_float(&mut self, _v: float) { self.add_unknown_to_log(); }
+
+        fn emit_char(&mut self, _v: char) { self.add_unknown_to_log(); }
+        fn emit_str(&mut self, _v: &str) { self.add_unknown_to_log(); }
+
+        fn emit_enum(&mut self, name: &str, f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitEnum(name.to_str()));
+            f(self);
+        }
+
+        fn emit_enum_variant(&mut self,
+                             name: &str,
+                             id: uint,
+                             cnt: uint,
+                             f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitEnumVariant(name.to_str(), id, cnt));
+            f(self);
+        }
+
+        fn emit_enum_variant_arg(&mut self,
+                                 idx: uint,
+                                 f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitEnumVariantArg(idx));
+            f(self);
+        }
+
+        fn emit_enum_struct_variant(&mut self,
+                                    name: &str,
+                                    id: uint,
+                                    cnt: uint,
+                                    f: &fn(&mut TestEncoder)) {
+            self.emit_enum_variant(name, id, cnt, f)
+        }
+
+        fn emit_enum_struct_variant_field(&mut self,
+                                          _name: &str,
+                                          idx: uint,
+                                          f: &fn(&mut TestEncoder)) {
+            self.emit_enum_variant_arg(idx, f)
+        }
+
+        fn emit_struct(&mut self,
+                       name: &str,
+                       len: uint,
+                       f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitStruct (name.to_str(),len));
+            f(self);
+        }
+        fn emit_struct_field(&mut self,
+                             name: &str,
+                             idx: uint,
+                             f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitField (name.to_str(),idx));
+            f(self);
+        }
+
+        fn emit_tuple(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+        fn emit_tuple_arg(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+
+        fn emit_tuple_struct(&mut self,
+                             _name: &str,
+                             _len: uint,
+                             f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+
+        fn emit_tuple_struct_arg(&mut self,
+                                 _idx: uint,
+                                 f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+
+        fn emit_option(&mut self, f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitOption);
+            f(self);
+        }
+        fn emit_option_none(&mut self) {
+            self.add_to_log(CallToEmitOptionNone);
+        }
+        fn emit_option_some(&mut self, f: &fn(&mut TestEncoder)) {
+            self.add_to_log(CallToEmitOptionSome);
+            f(self);
+        }
+
+        fn emit_seq(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+        fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+
+        fn emit_map(&mut self, _len: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+        fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+        fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) {
+            self.add_unknown_to_log();
+            f(self);
+        }
+    }
+
+
+    fn to_call_log<E:Encodable<TestEncoder>>(val: E) -> ~[call] {
+        let mut te = TestEncoder {
+            call_log: @mut ~[]
+        };
+        val.encode(&mut te);
+        copy *te.call_log
+    }
+
+    #[deriving(Encodable)]
+    enum Written {
+        Book(uint,uint),
+        Magazine(~str)
+    }
+
+    #[test]
+    fn test_encode_enum() {
+        assert_eq!(
+            to_call_log(Book(34,44)),
+            ~[
+                CallToEmitEnum(~"Written"),
+                CallToEmitEnumVariant(~"Book",0,2),
+                CallToEmitEnumVariantArg(0),
+                CallToEmitUint(34),
+                CallToEmitEnumVariantArg(1),
+                CallToEmitUint(44),
+            ]
+        );
+    }
+
+    pub struct BPos(uint);
+
+    #[deriving(Encodable)]
+    pub struct HasPos { pos : BPos }
+
+    #[test]
+    fn test_encode_newtype() {
+        assert_eq!(
+            to_call_log(HasPos { pos:BPos(48) }),
+            ~[
+                CallToEmitStruct(~"HasPos",1),
+                CallToEmitField(~"pos",0),
+                CallToEmitUint(48),
+            ]
+        );
+    }
+
+    #[test]
+    fn test_encode_option() {
+        let mut v = None;
+
+        assert_eq!(
+            to_call_log(v),
+            ~[
+                CallToEmitOption,
+                CallToEmitOptionNone,
+            ]
+        );
+
+        v = Some(54u);
+        assert_eq!(
+            to_call_log(v),
+            ~[
+                CallToEmitOption,
+                CallToEmitOptionSome,
+                CallToEmitUint(54)
+            ]
+        );
+    }
+}
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index d785f3816de..fc14e3c3f73 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -216,7 +216,7 @@ pub struct MethodDef<'self> {
     /// Whether there is a self argument (outer Option) i.e. whether
     /// this is a static function, and whether it is a pointer (inner
     /// Option)
-    self_ty: Option<Option<PtrTy>>,
+    explicit_self: Option<Option<PtrTy>>,
 
     /// Arguments other than the self argument
     args: ~[Ty],
@@ -259,14 +259,14 @@ pub enum SubstructureFields<'self> {
     fields: `(field ident, self, [others])`, where the field ident is
     only non-`None` in the case of a struct variant.
     */
-    EnumMatching(uint, ast::variant, ~[(Option<ident>, @expr, ~[@expr])]),
+    EnumMatching(uint, &'self ast::variant, ~[(Option<ident>, @expr, ~[@expr])]),
 
     /**
     non-matching variants of the enum, [(variant index, ast::variant,
     [field ident, fields])] (i.e. all fields for self are in the
     first tuple, for other1 are in the second tuple, etc.)
     */
-    EnumNonMatching(~[(uint, ast::variant, ~[(Option<ident>, @expr)])]),
+    EnumNonMatching(&'self [(uint, ast::variant, ~[(Option<ident>, @expr)])]),
 
     /// A static method where Self is a struct
     StaticStruct(&'self ast::struct_def, Either<uint, ~[ident]>),
@@ -290,7 +290,7 @@ representing each variant: (variant index, ast::variant instance,
 */
 pub type EnumNonMatchFunc<'self> =
     &'self fn(@ext_ctxt, span,
-              ~[(uint, ast::variant,
+              &[(uint, ast::variant,
                  ~[(Option<ident>, @expr)])],
               &[@expr]) -> @expr;
 
@@ -321,7 +321,7 @@ impl<'self> TraitDef<'self> {
                          type_ident: ident,
                          generics: &Generics) -> @ast::item {
         let methods = do self.methods.map |method_def| {
-            let (self_ty, self_args, nonself_args, tys) =
+            let (explicit_self, self_args, nonself_args, tys) =
                 method_def.split_self_nonself_args(cx, span, type_ident, generics);
 
             let body = if method_def.is_static() {
@@ -339,7 +339,7 @@ impl<'self> TraitDef<'self> {
 
             method_def.create_method(cx, span,
                                      type_ident, generics,
-                                     self_ty, tys,
+                                     explicit_self, tys,
                                      body)
         };
 
@@ -352,7 +352,7 @@ impl<'self> TraitDef<'self> {
                        type_ident: ident,
                        generics: &Generics) -> @ast::item {
         let methods = do self.methods.map |method_def| {
-            let (self_ty, self_args, nonself_args, tys) =
+            let (explicit_self, self_args, nonself_args, tys) =
                 method_def.split_self_nonself_args(cx, span, type_ident, generics);
 
             let body = if method_def.is_static() {
@@ -370,7 +370,7 @@ impl<'self> TraitDef<'self> {
 
             method_def.create_method(cx, span,
                                      type_ident, generics,
-                                     self_ty, tys,
+                                     explicit_self, tys,
                                      body)
         };
 
@@ -404,27 +404,27 @@ impl<'self> MethodDef<'self> {
     }
 
     fn is_static(&self) -> bool {
-        self.self_ty.is_none()
+        self.explicit_self.is_none()
     }
 
     fn split_self_nonself_args(&self, cx: @ext_ctxt, span: span,
                              type_ident: ident, generics: &Generics)
-        -> (ast::self_ty, ~[@expr], ~[@expr], ~[(ident, @ast::Ty)]) {
+        -> (ast::explicit_self, ~[@expr], ~[@expr], ~[(ident, @ast::Ty)]) {
 
         let mut self_args = ~[], nonself_args = ~[], arg_tys = ~[];
-        let mut ast_self_ty = respan(span, ast::sty_static);
         let mut nonstatic = false;
 
-        match self.self_ty {
-            Some(self_ptr) => {
-                let (self_expr, self_ty) = ty::get_explicit_self(cx, span, self_ptr);
+        let ast_explicit_self = match self.explicit_self {
+            Some(ref self_ptr) => {
+                let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr);
 
-                ast_self_ty = self_ty;
                 self_args.push(self_expr);
                 nonstatic = true;
+
+                explicit_self
             }
-            _ => {}
-        }
+            None => respan(span, ast::sty_static),
+        };
 
         for self.args.eachi |i, ty| {
             let ast_ty = ty.to_ty(cx, span, type_ident, generics);
@@ -448,13 +448,13 @@ impl<'self> MethodDef<'self> {
             }
         }
 
-        (ast_self_ty, self_args, nonself_args, arg_tys)
+        (ast_explicit_self, self_args, nonself_args, arg_tys)
     }
 
     fn create_method(&self, cx: @ext_ctxt, span: span,
                      type_ident: ident,
                      generics: &Generics,
-                     self_ty: ast::self_ty,
+                     explicit_self: ast::explicit_self,
                      arg_types: ~[(ident, @ast::Ty)],
                      body: @expr) -> @ast::method {
         // create the generics that aren't for Self
@@ -476,7 +476,7 @@ impl<'self> MethodDef<'self> {
             ident: method_ident,
             attrs: ~[],
             generics: fn_generics,
-            self_ty: self_ty,
+            explicit_self: explicit_self,
             purity: ast::impure_fn,
             decl: fn_decl,
             body: body_block,
@@ -616,9 +616,10 @@ impl<'self> MethodDef<'self> {
                                self_args: &[@expr],
                                nonself_args: &[@expr])
         -> @expr {
+        let mut matches = ~[];
         self.build_enum_match(cx, span, enum_def, type_ident,
                               self_args, nonself_args,
-                              None, ~[], 0)
+                              None, &mut matches, 0)
     }
 
 
@@ -650,58 +651,57 @@ impl<'self> MethodDef<'self> {
                         self_args: &[@expr],
                         nonself_args: &[@expr],
                         matching: Option<uint>,
-                        matches_so_far: ~[(uint, ast::variant,
-                                           ~[(Option<ident>, @expr)])],
+                        matches_so_far: &mut ~[(uint, ast::variant,
+                                              ~[(Option<ident>, @expr)])],
                         match_count: uint) -> @expr {
         if match_count == self_args.len() {
             // we've matched against all arguments, so make the final
             // expression at the bottom of the match tree
-            match matches_so_far {
-                [] => cx.span_bug(span, ~"no self match on an enum in generic `deriving`"),
-                _ => {
-                    // we currently have a vec of vecs, where each
-                    // subvec is the fields of one of the arguments,
-                    // but if the variants all match, we want this as
-                    // vec of tuples, where each tuple represents a
-                    // field.
-
-                    let substructure;
-
-                    // most arms don't have matching variants, so do a
-                    // quick check to see if they match (even though
-                    // this means iterating twice) instead of being
-                    // optimistic and doing a pile of allocations etc.
-                    match matching {
-                        Some(variant_index) => {
-                            // `ref` inside let matches is buggy. Causes havoc wih rusc.
-                            // let (variant_index, ref self_vec) = matches_so_far[0];
-                            let (variant, self_vec) = match matches_so_far[0] {
-                                (_, v, ref s) => (v, s)
-                            };
-
-                            let mut enum_matching_fields = vec::from_elem(self_vec.len(), ~[]);
-
-                            for matches_so_far.tail().each |&(_, _, other_fields)| {
-                                for other_fields.eachi |i, &(_, other_field)| {
-                                    enum_matching_fields[i].push(other_field);
-                                }
-                            }
-                            let field_tuples =
-                                do vec::map_zip(*self_vec,
-                                             enum_matching_fields) |&(id, self_f), &other| {
-                                (id, self_f, other)
-                            };
-                            substructure = EnumMatching(variant_index, variant, field_tuples);
-                        }
-                        None => {
-                            substructure = EnumNonMatching(matches_so_far);
+            if matches_so_far.len() == 0 {
+                cx.span_bug(span, ~"no self match on an enum in generic \
+                                    `deriving`");
+            }
+            // we currently have a vec of vecs, where each
+            // subvec is the fields of one of the arguments,
+            // but if the variants all match, we want this as
+            // vec of tuples, where each tuple represents a
+            // field.
+
+            let substructure;
+
+            // most arms don't have matching variants, so do a
+            // quick check to see if they match (even though
+            // this means iterating twice) instead of being
+            // optimistic and doing a pile of allocations etc.
+            match matching {
+                Some(variant_index) => {
+                    // `ref` inside let matches is buggy. Causes havoc wih rusc.
+                    // let (variant_index, ref self_vec) = matches_so_far[0];
+                    let (variant, self_vec) = match matches_so_far[0] {
+                        (_, ref v, ref s) => (v, s)
+                    };
+
+                    let mut enum_matching_fields = vec::from_elem(self_vec.len(), ~[]);
+
+                    for matches_so_far.tail().each |&(_, _, other_fields)| {
+                        for other_fields.eachi |i, &(_, other_field)| {
+                            enum_matching_fields[i].push(other_field);
                         }
                     }
-                    self.call_substructure_method(cx, span, type_ident,
-                                                  self_args, nonself_args,
-                                                  &substructure)
+                    let field_tuples =
+                        do vec::map_zip(*self_vec,
+                                     enum_matching_fields) |&(id, self_f), &other| {
+                        (id, self_f, other)
+                    };
+                    substructure = EnumMatching(variant_index, variant, field_tuples);
+                }
+                None => {
+                    substructure = EnumNonMatching(*matches_so_far);
                 }
             }
+            self.call_substructure_method(cx, span, type_ident,
+                                          self_args, nonself_args,
+                                          &substructure)
 
         } else {  // there are still matches to create
             let current_match_str = if match_count == 0 {
@@ -712,9 +712,6 @@ impl<'self> MethodDef<'self> {
 
             let mut arms = ~[];
 
-            // this is used as a stack
-            let mut matches_so_far = matches_so_far;
-
             // the code for nonmatching variants only matters when
             // we've seen at least one other variant already
             if self.const_nonmatching && match_count > 0 {
@@ -732,7 +729,7 @@ impl<'self> MethodDef<'self> {
                                                                     current_match_str,
                                                                     ast::m_imm);
 
-                matches_so_far.push((index, *variant, idents));
+                matches_so_far.push((index, /*bad*/ copy *variant, idents));
                 let arm_expr = self.build_enum_match(cx, span,
                                                      enum_def,
                                                      type_ident,
@@ -744,9 +741,10 @@ impl<'self> MethodDef<'self> {
                 arms.push(build::mk_arm(cx, span, ~[ pattern ], arm_expr));
 
                 if enum_def.variants.len() > 1 {
+                    let e = &EnumNonMatching(&[]);
                     let wild_expr = self.call_substructure_method(cx, span, type_ident,
                                                                   self_args, nonself_args,
-                                                                  &EnumNonMatching(~[]));
+                                                                  e);
                     let wild_arm = build::mk_arm(cx, span,
                                                  ~[ build::mk_pat_wild(cx, span) ],
                                                  wild_expr);
@@ -760,7 +758,7 @@ impl<'self> MethodDef<'self> {
                                                                        current_match_str,
                                                                        ast::m_imm);
 
-                    matches_so_far.push((index, *variant, idents));
+                    matches_so_far.push((index, /*bad*/ copy *variant, idents));
                     let new_matching =
                         match matching {
                             _ if match_count == 0 => Some(index),
@@ -850,7 +848,7 @@ pub fn cs_fold(use_foldl: bool,
                cx: @ext_ctxt, span: span,
                substructure: &Substructure) -> @expr {
     match *substructure.fields {
-        EnumMatching(_, _, all_fields) | Struct(all_fields) => {
+        EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             if use_foldl {
                 do all_fields.foldl(base) |&old, &(_, self_f, other_fs)| {
                     f(cx, span, old, self_f, other_fs)
@@ -861,8 +859,9 @@ pub fn cs_fold(use_foldl: bool,
                 }
             }
         },
-        EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span,
-                                                      all_enums, substructure.nonself_args),
+        EnumNonMatching(ref all_enums) => enum_nonmatch_f(cx, span,
+                                                          *all_enums,
+                                                          substructure.nonself_args),
         StaticEnum(*) | StaticStruct(*) => {
             cx.span_bug(span, "Static function in `deriving`")
         }
@@ -885,7 +884,7 @@ pub fn cs_same_method(f: &fn(@ext_ctxt, span, ~[@expr]) -> @expr,
                       cx: @ext_ctxt, span: span,
                       substructure: &Substructure) -> @expr {
     match *substructure.fields {
-        EnumMatching(_, _, all_fields) | Struct(all_fields) => {
+        EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             // call self_n.method(other_1_n, other_2_n, ...)
             let called = do all_fields.map |&(_, self_field, other_fields)| {
                 build::mk_method_call(cx, span,
@@ -896,8 +895,9 @@ pub fn cs_same_method(f: &fn(@ext_ctxt, span, ~[@expr]) -> @expr,
 
             f(cx, span, called)
         },
-        EnumNonMatching(all_enums) => enum_nonmatch_f(cx, span,
-                                                      all_enums, substructure.nonself_args),
+        EnumNonMatching(ref all_enums) => enum_nonmatch_f(cx, span,
+                                                          *all_enums,
+                                                          substructure.nonself_args),
         StaticEnum(*) | StaticStruct(*) => {
             cx.span_bug(span, "Static function in `deriving`")
         }
diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs
index 9eb246ffe22..1c9ec6ece2e 100644
--- a/src/libsyntax/ext/deriving/iter_bytes.rs
+++ b/src/libsyntax/ext/deriving/iter_bytes.rs
@@ -26,7 +26,7 @@ pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
             MethodDef {
                 name: ~"iter_bytes",
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[
                     Literal(Path::new(~[~"bool"])),
                     Literal(Path::new(~[~"core", ~"to_bytes", ~"Cb"]))
@@ -41,16 +41,6 @@ pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
     expand_deriving_generic(cx, span, mitem, in_items, &trait_def)
 }
 
-pub fn expand_deriving_obsolete(cx: @ext_ctxt,
-                                span: span,
-                                _mitem: @meta_item,
-                                in_items: ~[@item])
-                             -> ~[@item] {
-    cx.span_err(span, ~"`#[deriving_iter_bytes]` is obsolete; use `#[deriving(IterBytes)]` \
-                        instead");
-    in_items
-}
-
 fn iter_bytes_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr {
     let lsb0_f = match substr.nonself_args {
         [l, f] => ~[l, f],
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index 78eacafe3d7..78cd5cdb423 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -8,8 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// The compiler code necessary to implement the #[deriving(Eq)] and
-/// #[deriving(IterBytes)] extensions.
+/*!
+The compiler code necessary to implement the #[deriving] extensions.
+
+
+FIXME (#2810)--Hygiene. Search for "__" strings (in other files too).
+We also assume "std" is the standard library, and "core" is the core
+library.
+
+*/
 
 use ast;
 use ast::{Ty, enum_def, expr, ident, item, Generics, meta_item, struct_def};
@@ -59,7 +66,7 @@ pub fn expand_meta_deriving(cx: @ext_ctxt,
     use ast::{meta_list, meta_name_value, meta_word};
 
     match mitem.node {
-        meta_name_value(_, l) => {
+        meta_name_value(_, ref l) => {
             cx.span_err(l.span, ~"unexpected value in `deriving`");
             in_items
         }
@@ -67,7 +74,7 @@ pub fn expand_meta_deriving(cx: @ext_ctxt,
             cx.span_warn(mitem.span, ~"empty trait list in `deriving`");
             in_items
         }
-        meta_list(_, titems) => {
+        meta_list(_, ref titems) => {
             do titems.foldr(in_items) |&titem, in_items| {
                 match titem.node {
                     meta_name_value(tname, _) |
@@ -77,6 +84,7 @@ pub fn expand_meta_deriving(cx: @ext_ctxt,
                                                                    titem, in_items)));
                         match *tname {
                             ~"Clone" => expand!(clone::expand_deriving_clone),
+                            ~"DeepClone" => expand!(clone::expand_deriving_deep_clone),
 
                             ~"IterBytes" => expand!(iter_bytes::expand_deriving_iter_bytes),
 
@@ -92,9 +100,9 @@ pub fn expand_meta_deriving(cx: @ext_ctxt,
 
                             ~"ToStr" => expand!(to_str::expand_deriving_to_str),
 
-                            tname => {
+                            ref tname => {
                                 cx.span_err(titem.span, fmt!("unknown \
-                                    `deriving` trait: `%s`", tname));
+                                    `deriving` trait: `%s`", *tname));
                                 in_items
                             }
                         }
@@ -203,8 +211,6 @@ pub fn create_derived_impl(cx: @ext_ctxt,
      *
      * where B1, B2, ... are the bounds given by `bounds_paths`.
      *
-     * FIXME(#5090): Remove code duplication between this and the
-     * code in auto_encode.rs
      */
 
     // Copy the lifetimes
@@ -371,8 +377,7 @@ pub fn expand_enum_or_struct_match(cx: @ext_ctxt,
                                span: span,
                                arms: ~[ ast::arm ])
                             -> @expr {
-    let self_ident = cx.ident_of("self");
-    let self_expr = build::mk_path(cx, span, ~[ self_ident ]);
+    let self_expr = build::make_self(cx, span);
     let self_expr = build::mk_unary(cx, span, ast::deref, self_expr);
     let self_match_expr = ast::expr_match(self_expr, arms);
     build::mk_expr(cx, span, self_match_expr)
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index 9030be86f39..2d91fcd346a 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -32,7 +32,7 @@ pub fn expand_deriving_rand(cx: @ext_ctxt,
                     bounds: ~[(~"R",
                                ~[ Path::new(~[~"core", ~"rand", ~"Rng"]) ])]
                 },
-                self_ty: None,
+                explicit_self: None,
                 args: ~[
                     Ptr(~Literal(Path::new_local(~"R")),
                         Borrowed(None, ast::m_mutbl))
diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs
index 6010354349e..13cb09e970d 100644
--- a/src/libsyntax/ext/deriving/to_str.rs
+++ b/src/libsyntax/ext/deriving/to_str.rs
@@ -27,7 +27,7 @@ pub fn expand_deriving_to_str(cx: @ext_ctxt,
             MethodDef {
                 name: ~"to_str",
                 generics: LifetimeBounds::empty(),
-                self_ty: borrowed_explicit_self(),
+                explicit_self: borrowed_explicit_self(),
                 args: ~[],
                 ret_ty: Ptr(~Literal(Path::new_local(~"str")), Owned),
                 const_nonmatching: false,
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index 08947efa7b7..8fd372e4792 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -63,7 +63,7 @@ pub impl Path {
     fn to_path(&self, cx: @ext_ctxt, span: span,
                self_ty: ident, self_generics: &Generics) -> @ast::Path {
         let idents = self.path.map(|s| cx.ident_of(*s) );
-        let lt = mk_lifetime(cx, span, self.lifetime);
+        let lt = mk_lifetime(cx, span, &self.lifetime);
         let tys = self.params.map(|t| t.to_ty(cx, span, self_ty, self_generics));
 
         if self.global {
@@ -106,9 +106,9 @@ pub fn nil_ty() -> Ty {
     Tuple(~[])
 }
 
-fn mk_lifetime(cx: @ext_ctxt, span: span, lt: Option<~str>) -> Option<@ast::Lifetime> {
-    match lt {
-        Some(s) => Some(@build::mk_lifetime(cx, span, cx.ident_of(s))),
+fn mk_lifetime(cx: @ext_ctxt, span: span, lt: &Option<~str>) -> Option<@ast::Lifetime> {
+    match *lt {
+        Some(ref s) => Some(@build::mk_lifetime(cx, span, cx.ident_of(*s))),
         None => None
     }
 }
@@ -123,10 +123,10 @@ pub impl Ty {
                     Owned => {
                         build::mk_ty_uniq(cx, span, raw_ty)
                     }
-                    Managed(copy mutbl) => {
+                    Managed(mutbl) => {
                         build::mk_ty_box(cx, span, raw_ty, mutbl)
                     }
-                    Borrowed(copy lt, copy mutbl) => {
+                    Borrowed(ref lt, mutbl) => {
                         let lt = mk_lifetime(cx, span, lt);
                         build::mk_ty_rptr(cx, span, raw_ty, lt, mutbl)
                     }
@@ -191,7 +191,7 @@ fn mk_generics(lifetimes: ~[ast::Lifetime],  ty_params: ~[ast::TyParam]) -> Gene
     }
 }
 
-/// Lifetimes and bounds on type paramers
+/// Lifetimes and bounds on type parameters
 pub struct LifetimeBounds {
     lifetimes: ~[~str],
     bounds: ~[(~str, ~[Path])]
@@ -216,20 +216,20 @@ pub impl LifetimeBounds {
 }
 
 
-pub fn get_explicit_self(cx: @ext_ctxt, span: span, self_ptr: Option<PtrTy>)
-    -> (@expr, ast::self_ty) {
-    let self_path = build::mk_path(cx, span, ~[cx.ident_of("self")]);
-    match self_ptr {
+pub fn get_explicit_self(cx: @ext_ctxt, span: span, self_ptr: &Option<PtrTy>)
+    -> (@expr, ast::explicit_self) {
+    let self_path = build::make_self(cx, span);
+    match *self_ptr {
         None => {
             (self_path, respan(span, ast::sty_value))
         }
-        Some(ptr) => {
+        Some(ref ptr) => {
             let self_ty = respan(
                 span,
-                match ptr {
+                match *ptr {
                     Owned => ast::sty_uniq(ast::m_imm),
                     Managed(mutbl) => ast::sty_box(mutbl),
-                    Borrowed(lt, mutbl) => {
+                    Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| @build::mk_lifetime(cx, span,
                                                                 cx.ident_of(*s)));
                         ast::sty_region(lt, mutbl)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 0fe28dadbc7..f9ca84473fb 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -468,7 +468,7 @@ pub fn core_macros() -> ~str {
                 let expected_val = $expected;
                 // check both directions of equality....
                 if !((given_val == expected_val) && (expected_val == given_val)) {
-                    fail!(fmt!(\"left: %? != right: %?\", given_val, expected_val));
+                    fail!(\"left: %? does not equal right: %?\", given_val, expected_val);
                 }
             }
         )
@@ -542,7 +542,41 @@ pub fn core_macros() -> ~str {
         }
     )
 
-
+    //
+    // A scheme-style conditional that helps to improve code clarity in some instances when
+    // the `if`, `else if`, and `else` keywords obscure predicates undesirably.
+    //
+    // # Example
+    //
+    // ~~~
+    // let clamped =
+    //     if x > mx { mx }
+    //     else if x < mn { mn }
+    //     else { x };
+    // ~~~
+    //
+    // Using `cond!`, the above could be written as:
+    //
+    // ~~~
+    // let clamped = cond!(
+    //     (x > mx) { mx }
+    //     (x < mn) { mn }
+    //     _        { x  }
+    // );
+    // ~~~
+    //
+    // The optional default case is denoted by `_`.
+    //
+    macro_rules! cond (
+        ( $(($pred:expr) $body:block)+ _ $default:block ) => (
+            $(if $pred $body else)+
+            $default
+        );
+        // for if the default case was ommitted
+        ( $(($pred:expr) $body:block)+ ) => (
+            $(if $pred $body)else+
+        );
+    )
 }";
 }
 
@@ -660,14 +694,13 @@ mod test {
 
     // make sure that fail! is present
     #[test] fn fail_exists_test () {
-        let src = ~"fn main() { fail!(~\"something appropriately gloomy\");}";
+        let src = ~"fn main() { fail!(\"something appropriately gloomy\");}";
         let sess = parse::new_parse_sess(None);
-        let cfg = ~[];
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             @src,
-            cfg,sess);
-        expand_crate(sess,cfg,crate_ast);
+            ~[],sess);
+        expand_crate(sess,~[],crate_ast);
     }
 
     // these following tests are quite fragile, in that they don't test what
@@ -679,13 +712,12 @@ mod test {
         let src = ~"fn bogus() {macro_rules! z (() => (3+4))}\
                     fn inty() -> int { z!() }";
         let sess = parse::new_parse_sess(None);
-        let cfg = ~[];
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             @src,
-            cfg,sess);
+            ~[],sess);
         // should fail:
-        expand_crate(sess,cfg,crate_ast);
+        expand_crate(sess,~[],crate_ast);
     }
 
     // make sure that macros can leave scope for modules
@@ -694,13 +726,12 @@ mod test {
         let src = ~"mod foo {macro_rules! z (() => (3+4))}\
                     fn inty() -> int { z!() }";
         let sess = parse::new_parse_sess(None);
-        let cfg = ~[];
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             @src,
-            cfg,sess);
+            ~[],sess);
         // should fail:
-        expand_crate(sess,cfg,crate_ast);
+        expand_crate(sess,~[],crate_ast);
     }
 
     // macro_escape modules shouldn't cause macros to leave scope
@@ -708,13 +739,12 @@ mod test {
         let src = ~"#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\
                     fn inty() -> int { z!() }";
         let sess = parse::new_parse_sess(None);
-        let cfg = ~[];
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             @src,
-            cfg,sess);
+            ~[], sess);
         // should fail:
-        expand_crate(sess,cfg,crate_ast);
+        expand_crate(sess,~[],crate_ast);
     }
 
     #[test] fn core_macros_must_parse () {
@@ -733,7 +763,7 @@ mod test {
             cfg,~[make_dummy_attr (@~"macro_escape")],sess);
         match item_ast {
             Some(_) => (), // success
-            None => fail!(~"expected this to parse")
+            None => fail!("expected this to parse")
         }
     }
 
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index 1a8edec3714..26b3178a911 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -62,7 +62,7 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span,
     // which tells the RT::conv* functions how to perform the conversion
 
     fn make_rt_conv_expr(cx: @ext_ctxt, sp: span, cnv: &Conv) -> @ast::expr {
-        fn make_flags(cx: @ext_ctxt, sp: span, flags: ~[Flag]) -> @ast::expr {
+        fn make_flags(cx: @ext_ctxt, sp: span, flags: &[Flag]) -> @ast::expr {
             let mut tmp_expr = make_rt_path_expr(cx, sp, "flag_none");
             for flags.each |f| {
                 let fstr = match *f {
diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs
index f9346f49b61..5c99ddc9040 100644
--- a/src/libsyntax/ext/pipes/parse_proto.rs
+++ b/src/libsyntax/ext/pipes/parse_proto.rs
@@ -32,7 +32,7 @@ impl proto_parser for parser::Parser {
                 sep: None,
                 trailing_sep_allowed: false,
             },
-            |self| self.parse_state(proto)
+            |this| this.parse_state(proto)
         );
 
         return proto;
@@ -70,7 +70,7 @@ impl proto_parser for parser::Parser {
                 sep: Some(token::COMMA),
                 trailing_sep_allowed: true,
             },
-            |self| self.parse_message(state)
+            |this| this.parse_message(state)
         );
     }
 
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index 7c78ec066d0..f897eb787e5 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -154,14 +154,14 @@ pub struct protocol_ {
 
 pub impl protocol_ {
     /// Get a state.
-    fn get_state(&self, name: ~str) -> state {
-        self.states.find(|i| i.name == name).get()
+    fn get_state(&self, name: &str) -> state {
+        self.states.find(|i| name == i.name).get()
     }
 
     fn get_state_by_id(&self, id: uint) -> state { self.states[id] }
 
-    fn has_state(&self, name: ~str) -> bool {
-        self.states.find(|i| i.name == name).is_some()
+    fn has_state(&self, name: &str) -> bool {
+        self.states.find(|i| name == i.name).is_some()
     }
 
     fn filename(&self) -> ~str {
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 9344a49c9a9..fc673c4422f 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -41,7 +41,6 @@ pub mod rt {
     pub use parse::new_parser_from_tts;
     pub use codemap::{BytePos, span, dummy_spanned};
 
-    use print::pprust;
     use print::pprust::{item_to_str, ty_to_str};
 
     pub trait ToTokens {
@@ -452,9 +451,9 @@ fn mk_binop(cx: @ext_ctxt, sp: span, bop: token::binop) -> @ast::expr {
                    ids_ext(cx, ~[name.to_owned()]))
 }
 
-fn mk_token(cx: @ext_ctxt, sp: span, tok: token::Token) -> @ast::expr {
+fn mk_token(cx: @ext_ctxt, sp: span, tok: &token::Token) -> @ast::expr {
 
-    match tok {
+    match *tok {
         BINOP(binop) => {
             return build::mk_call(cx, sp,
                                   ids_ext(cx, ~[~"BINOP"]),
@@ -556,12 +555,12 @@ fn mk_token(cx: @ext_ctxt, sp: span, tok: token::Token) -> @ast::expr {
                                   ~[mk_ident(cx, sp, ident)]);
         }
 
-        INTERPOLATED(_) => fail!(~"quote! with interpolated token"),
+        INTERPOLATED(_) => fail!("quote! with interpolated token"),
 
         _ => ()
     }
 
-    let name = match tok {
+    let name = match *tok {
         EQ => "EQ",
         LT => "LT",
         LE => "LE",
@@ -612,7 +611,7 @@ fn mk_tt(cx: @ext_ctxt, sp: span, tt: &ast::token_tree)
             let e_tok =
                 build::mk_call(cx, sp,
                                ids_ext(cx, ~[~"tt_tok"]),
-                               ~[e_sp, mk_token(cx, sp, *tok)]);
+                               ~[e_sp, mk_token(cx, sp, tok)]);
             let e_push =
                 build::mk_method_call(cx, sp,
                                       build::mk_path(cx, sp, ids_ext(cx, ~[~"tt"])),
@@ -623,7 +622,7 @@ fn mk_tt(cx: @ext_ctxt, sp: span, tt: &ast::token_tree)
         }
 
         ast::tt_delim(ref tts) => mk_tts(cx, sp, *tts),
-        ast::tt_seq(*) => fail!(~"tt_seq in quote!"),
+        ast::tt_seq(*) => fail!("tt_seq in quote!"),
 
         ast::tt_nonterminal(sp, ident) => {
 
@@ -678,10 +677,11 @@ fn expand_tts(cx: @ext_ctxt,
     // We want to emit a block expression that does a sequence of 'use's to
     // import the runtime module, followed by a tt-building expression.
 
-    let uses = ~[ build::mk_glob_use(cx, sp, ids_ext(cx, ~[~"syntax",
-                                                           ~"ext",
-                                                           ~"quote",
-                                                           ~"rt"])) ];
+    let uses = ~[ build::mk_glob_use(cx, sp, ast::public,
+                                     ids_ext(cx, ~[~"syntax",
+                                                   ~"ext",
+                                                   ~"quote",
+                                                   ~"rt"])) ];
 
     // We also bind a single value, sp, to ext_cx.call_site()
     //
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index 9660afb1bc0..1bb40808142 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -34,9 +34,9 @@ pub fn expand_trace_macros(cx: @ext_ctxt,
         rdr.dup()
     );
 
-    if rust_parser.is_keyword(&~"true") {
+    if rust_parser.is_keyword("true") {
         cx.set_trace_macros(true);
-    } else if rust_parser.is_keyword(&~"false") {
+    } else if rust_parser.is_keyword("false") {
         cx.set_trace_macros(false);
     } else {
         cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`")
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 46b09aca8b2..aa211973f1c 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -130,7 +130,6 @@ pub fn count_names(ms: &[matcher]) -> uint {
         }})
 }
 
-#[allow(non_implicitly_copyable_typarams)]
 pub fn initial_matcher_pos(ms: ~[matcher], sep: Option<Token>, lo: BytePos)
                         -> ~MatcherPos {
     let mut match_idx_hi = 0u;
@@ -184,15 +183,15 @@ pub enum named_match {
 
 pub type earley_item = ~MatcherPos;
 
-pub fn nameize(p_s: @mut ParseSess, ms: ~[matcher], res: ~[@named_match])
+pub fn nameize(p_s: @mut ParseSess, ms: &[matcher], res: &[@named_match])
             -> HashMap<ident,@named_match> {
-    fn n_rec(p_s: @mut ParseSess, m: matcher, res: ~[@named_match],
+    fn n_rec(p_s: @mut ParseSess, m: &matcher, res: &[@named_match],
              ret_val: &mut HashMap<ident, @named_match>) {
-        match m {
+        match *m {
           codemap::spanned {node: match_tok(_), _} => (),
           codemap::spanned {node: match_seq(ref more_ms, _, _, _, _), _} => {
-            for (*more_ms).each() |next_m| {
-                n_rec(p_s, *next_m, res, ret_val)
+            for more_ms.each |next_m| {
+                n_rec(p_s, next_m, res, ret_val)
             };
           }
           codemap::spanned {
@@ -207,7 +206,7 @@ pub fn nameize(p_s: @mut ParseSess, ms: ~[matcher], res: ~[@named_match])
         }
     }
     let mut ret_val = HashMap::new();
-    for ms.each() |m| { n_rec(p_s, *m, res, &mut ret_val) }
+    for ms.each |m| { n_rec(p_s, m, res, &mut ret_val) }
     return ret_val;
 }
 
@@ -234,10 +233,10 @@ pub fn parse(
     sess: @mut ParseSess,
     cfg: ast::crate_cfg,
     rdr: @reader,
-    ms: ~[matcher]
+    ms: &[matcher]
 ) -> parse_result {
     let mut cur_eis = ~[];
-    cur_eis.push(initial_matcher_pos(copy ms, None, rdr.peek().sp.lo));
+    cur_eis.push(initial_matcher_pos(ms.to_owned(), None, rdr.peek().sp.lo));
 
     loop {
         let mut bb_eis = ~[]; // black-box parsed by parser.rs
@@ -277,7 +276,7 @@ pub fn parse(
 
                         // Only touch the binders we have actually bound
                         for uint::range(ei.match_lo, ei.match_hi) |idx| {
-                            let sub = ei.matches[idx];
+                            let sub = copy ei.matches[idx];
                             new_pos.matches[idx]
                                 .push(@matched_seq(sub,
                                                    mk_sp(ei.sp_lo,
@@ -410,31 +409,31 @@ pub fn parse(
     }
 }
 
-pub fn parse_nt(p: &Parser, name: ~str) -> nonterminal {
+pub fn parse_nt(p: &Parser, name: &str) -> nonterminal {
     match name {
-      ~"item" => match p.parse_item(~[]) {
+      "item" => match p.parse_item(~[]) {
         Some(i) => token::nt_item(i),
         None => p.fatal(~"expected an item keyword")
       },
-      ~"block" => token::nt_block(p.parse_block()),
-      ~"stmt" => token::nt_stmt(p.parse_stmt(~[])),
-      ~"pat" => token::nt_pat(p.parse_pat(true)),
-      ~"expr" => token::nt_expr(p.parse_expr()),
-      ~"ty" => token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)),
+      "block" => token::nt_block(p.parse_block()),
+      "stmt" => token::nt_stmt(p.parse_stmt(~[])),
+      "pat" => token::nt_pat(p.parse_pat(true)),
+      "expr" => token::nt_expr(p.parse_expr()),
+      "ty" => token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)),
       // this could be handled like a token, since it is one
-      ~"ident" => match *p.token {
+      "ident" => match *p.token {
         token::IDENT(sn,b) => { p.bump(); token::nt_ident(sn,b) }
         _ => p.fatal(~"expected ident, found "
                      + token::to_str(p.reader.interner(), &copy *p.token))
       },
-      ~"path" => token::nt_path(p.parse_path_with_tps(false)),
-      ~"tt" => {
+      "path" => token::nt_path(p.parse_path_with_tps(false)),
+      "tt" => {
         *p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
         let res = token::nt_tt(@p.parse_token_tree());
         *p.quote_depth -= 1u;
         res
       }
-      ~"matchers" => token::nt_matchers(p.parse_matchers()),
+      "matchers" => token::nt_matchers(p.parse_matchers()),
       _ => p.fatal(~"Unsupported builtin nonterminal parser: " + name)
     }
 }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 169652b1120..be6cc7a846a 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -63,19 +63,19 @@ pub fn add_new_extension(cx: @ext_ctxt,
 
     // Extract the arguments:
     let lhses = match *argument_map.get(&lhs_nm) {
-        @matched_seq(ref s, _) => /* FIXME (#2543) */ copy *s,
+        @matched_seq(ref s, _) => /* FIXME (#2543) */ @copy *s,
         _ => cx.span_bug(sp, ~"wrong-structured lhs")
     };
 
     let rhses = match *argument_map.get(&rhs_nm) {
-      @matched_seq(ref s, _) => /* FIXME (#2543) */ copy *s,
+      @matched_seq(ref s, _) => /* FIXME (#2543) */ @copy *s,
       _ => cx.span_bug(sp, ~"wrong-structured rhs")
     };
 
     // Given `lhses` and `rhses`, this is the new macro we create
     fn generic_extension(cx: @ext_ctxt, sp: span, name: ident,
                          arg: &[ast::token_tree],
-                         lhses: ~[@named_match], rhses: ~[@named_match])
+                         lhses: &[@named_match], rhses: &[@named_match])
     -> MacResult {
 
         if cx.trace_macros() {
@@ -93,7 +93,7 @@ pub fn add_new_extension(cx: @ext_ctxt,
         let s_d = cx.parse_sess().span_diagnostic;
         let itr = cx.parse_sess().interner;
 
-        for lhses.eachi() |i, lhs| { // try each arm's matchers
+        for lhses.eachi |i, lhs| { // try each arm's matchers
             match *lhs {
               @matched_nonterminal(nt_matchers(ref mtcs)) => {
                 // `none` is because we're not interpolating
@@ -103,7 +103,7 @@ pub fn add_new_extension(cx: @ext_ctxt,
                     None,
                     vec::to_owned(arg)
                 ) as @reader;
-                match parse(cx.parse_sess(), cx.cfg(), arg_rdr, (*mtcs)) {
+                match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
                   success(named_matches) => {
                     let rhs = match rhses[i] {
                         // okay, what's your transcriber?
@@ -146,7 +146,7 @@ pub fn add_new_extension(cx: @ext_ctxt,
     }
 
     let exp: @fn(@ext_ctxt, span, &[ast::token_tree]) -> MacResult =
-        |cx, sp, arg| generic_extension(cx, sp, name, arg, lhses, rhses);
+        |cx, sp, arg| generic_extension(cx, sp, name, arg, *lhses, *rhses);
 
     return MRDef(MacroDef{
         name: copy *cx.parse_sess().interner.get(name),
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 19c83e21a86..438efb2326c 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -91,11 +91,11 @@ pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader {
         sp_diag: r.sp_diag,
         interner: r.interner,
         stack: dup_tt_frame(r.stack),
-        interpolations: r.interpolations,
         repeat_idx: copy r.repeat_idx,
         repeat_len: copy r.repeat_len,
         cur_tok: copy r.cur_tok,
-        cur_span: r.cur_span
+        cur_span: r.cur_span,
+        interpolations: copy r.interpolations,
     }
 }
 
@@ -127,7 +127,7 @@ enum lis {
     lis_unconstrained, lis_constraint(uint, ident), lis_contradiction(~str)
 }
 
-fn lockstep_iter_size(t: token_tree, r: &mut TtReader) -> lis {
+fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
     fn lis_merge(lhs: lis, rhs: lis, r: &mut TtReader) -> lis {
         match lhs {
           lis_unconstrained => copy rhs,
@@ -146,10 +146,10 @@ fn lockstep_iter_size(t: token_tree, r: &mut TtReader) -> lis {
           }
         }
     }
-    match t {
+    match *t {
       tt_delim(ref tts) | tt_seq(_, ref tts, _, _) => {
-        vec::foldl(lis_unconstrained, (*tts), |lis, tt| {
-            let lis2 = lockstep_iter_size(*tt, r);
+        vec::foldl(lis_unconstrained, *tts, |lis, tt| {
+            let lis2 = lockstep_iter_size(tt, r);
             lis_merge(lis, lis2, r)
         })
       }
@@ -230,7 +230,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
           }
           tt_seq(sp, copy tts, copy sep, zerok) => {
             let t = tt_seq(sp, copy tts, copy sep, zerok);
-            match lockstep_iter_size(t, r) {
+            match lockstep_iter_size(&t, r) {
               lis_unconstrained => {
                 r.sp_diag.span_fatal(
                     sp, /* blame macro writer */
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 338b9b29f00..275a7b963a4 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -44,7 +44,7 @@ pub trait ast_fold {
 pub struct AstFoldFns {
     //unlike the others, item_ is non-trivial
     fold_crate: @fn(&crate_, span, @ast_fold) -> (crate_, span),
-    fold_view_item: @fn(view_item_, @ast_fold) -> view_item_,
+    fold_view_item: @fn(&view_item_, @ast_fold) -> view_item_,
     fold_foreign_item: @fn(@foreign_item, @ast_fold) -> @foreign_item,
     fold_item: @fn(@item, @ast_fold) -> Option<@item>,
     fold_struct_field: @fn(@struct_field, @ast_fold) -> @struct_field,
@@ -112,7 +112,7 @@ fn fold_arg_(a: arg, fld: @ast_fold) -> arg {
     }
 }
 //used in noop_fold_expr, and possibly elsewhere in the future
-fn fold_mac_(m: mac, fld: @ast_fold) -> mac {
+fn fold_mac_(m: &mac, fld: @ast_fold) -> mac {
     spanned {
         node: match m.node { mac_invoc_tt(*) => copy m.node },
         span: fld.new_span(m.span),
@@ -174,8 +174,8 @@ pub fn noop_fold_crate(c: &crate_, fld: @ast_fold) -> crate_ {
     }
 }
 
-fn noop_fold_view_item(vi: view_item_, _fld: @ast_fold) -> view_item_ {
-    return /* FIXME (#2543) */ copy vi;
+fn noop_fold_view_item(vi: &view_item_, _fld: @ast_fold) -> view_item_ {
+    return /* FIXME (#2543) */ copy *vi;
 }
 
 
@@ -323,7 +323,7 @@ fn noop_fold_method(m: @method, fld: @ast_fold) -> @method {
         ident: fld.fold_ident(m.ident),
         attrs: /* FIXME (#2543) */ copy m.attrs,
         generics: fold_generics(&m.generics, fld),
-        self_ty: m.self_ty,
+        explicit_self: m.explicit_self,
         purity: m.purity,
         decl: fold_fn_decl(&m.decl, fld),
         body: fld.fold_block(&m.body),
@@ -351,7 +351,7 @@ fn noop_fold_stmt(s: &stmt_, fld: @ast_fold) -> stmt_ {
         stmt_decl(d, nid) => stmt_decl(fld.fold_decl(d), fld.new_id(nid)),
         stmt_expr(e, nid) => stmt_expr(fld.fold_expr(e), fld.new_id(nid)),
         stmt_semi(e, nid) => stmt_semi(fld.fold_expr(e), fld.new_id(nid)),
-        stmt_mac(ref mac, semi) => stmt_mac(fold_mac((*mac)), semi)
+        stmt_mac(ref mac, semi) => stmt_mac(fold_mac(mac), semi)
     }
 }
 
@@ -524,6 +524,7 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
             expr_index(fld.fold_expr(el), fld.fold_expr(er))
         }
         expr_path(pth) => expr_path(fld.fold_path(pth)),
+        expr_self => expr_self,
         expr_break(ref opt_ident) => {
             expr_break(opt_ident.map(|x| fld.fold_ident(*x)))
         }
@@ -539,14 +540,14 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
                 fld.fold_expr(e)
             )
         }
-        expr_inline_asm(a) => {
+        expr_inline_asm(ref a) => {
             expr_inline_asm(inline_asm {
                 inputs: a.inputs.map(|&(c, in)| (c, fld.fold_expr(in))),
                 outputs: a.outputs.map(|&(c, out)| (c, fld.fold_expr(out))),
-                .. a
+                .. copy *a
             })
         }
-        expr_mac(ref mac) => expr_mac(fold_mac((*mac))),
+        expr_mac(ref mac) => expr_mac(fold_mac(mac)),
         expr_struct(path, ref fields, maybe_expr) => {
             expr_struct(
                 fld.fold_path(path),
@@ -588,13 +589,14 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
                 purity: f.purity,
                 region: f.region,
                 onceness: f.onceness,
+                bounds: f.bounds.map(|x| fold_ty_param_bound(x, fld)),
                 decl: fold_fn_decl(&f.decl, fld),
-                lifetimes: f.lifetimes,
+                lifetimes: copy f.lifetimes,
             })
         }
         ty_bare_fn(ref f) => {
             ty_bare_fn(@TyBareFn {
-                lifetimes: f.lifetimes,
+                lifetimes: copy f.lifetimes,
                 purity: f.purity,
                 abis: f.abis,
                 decl: fold_fn_decl(&f.decl, fld)
@@ -608,7 +610,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
                 fld.fold_expr(e)
             )
         }
-        ty_mac(ref mac) => ty_mac(fold_mac(*mac))
+        ty_mac(ref mac) => ty_mac(fold_mac(mac))
     }
 }
 
@@ -739,7 +741,7 @@ impl ast_fold for AstFoldFns {
     fn fold_view_item(@self, x: @view_item) ->
        @view_item {
         @ast::view_item {
-            node: (self.fold_view_item)(x.node, self as @ast_fold),
+            node: (self.fold_view_item)(&x.node, self as @ast_fold),
             attrs: vec::map(x.attrs, |a|
                   fold_attribute_(*a, self as @ast_fold)),
             vis: x.vis,
diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs
index 6110579863d..fb3622396c9 100644
--- a/src/libsyntax/opt_vec.rs
+++ b/src/libsyntax/opt_vec.rs
@@ -20,8 +20,7 @@ use core::prelude::*;
 use core::old_iter;
 use core::old_iter::BaseIter;
 
-#[auto_encode]
-#[auto_decode]
+#[deriving(Encodable, Decodable)]
 pub enum OptVec<T> {
     Empty,
     Vec(~[T])
@@ -63,7 +62,7 @@ impl<T> OptVec<T> {
 
     fn get<'a>(&'a self, i: uint) -> &'a T {
         match *self {
-            Empty => fail!(fmt!("Invalid index %u", i)),
+            Empty => fail!("Invalid index %u", i),
             Vec(ref v) => &v[i]
         }
     }
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index acfd18c74de..89873b27935 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -111,7 +111,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str {
         return str::connect(lines, ~"\n");
     }
 
-    fail!(~"not a doc-comment: " + comment);
+    fail!("not a doc-comment: %s", comment);
 }
 
 fn read_to_eol(rdr: @mut StringReader) -> ~str {
@@ -192,7 +192,7 @@ fn read_line_comments(rdr: @mut StringReader, code_to_the_left: bool,
 
 // FIXME #3961: This is not the right way to convert string byte
 // offsets to characters.
-fn all_whitespace(s: ~str, begin: uint, end: uint) -> bool {
+fn all_whitespace(s: &str, begin: uint, end: uint) -> bool {
     let mut i: uint = begin;
     while i != end {
         if !is_whitespace(s[i] as char) { return false; } i += 1u;
@@ -276,7 +276,7 @@ fn read_block_comment(rdr: @mut StringReader,
 
     let mut style = if code_to_the_left { trailing } else { isolated };
     consume_non_eol_whitespace(rdr);
-    if !is_eof(rdr) && rdr.curr != '\n' && vec::len(lines) == 1u {
+    if !is_eof(rdr) && rdr.curr != '\n' && lines.len() == 1u {
         style = mixed;
     }
     debug!("<<< block comment");
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index 1df6860fede..6595343654f 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -137,27 +137,27 @@ pub impl Parser {
 
     // A sanity check that the word we are asking for is a known keyword
     // NOTE: this could be done statically....
-    fn require_keyword(&self, word: &~str) {
-        if !self.keywords.contains(word) {
-            self.bug(fmt!("unknown keyword: %s", *word));
+    fn require_keyword(&self, word: &str) {
+        if !self.keywords.contains_equiv(&word) {
+            self.bug(fmt!("unknown keyword: %s", word));
         }
     }
 
     // return true when this token represents the given string, and is not
     // followed immediately by :: .
-    fn token_is_word(&self, word: &~str, tok: &token::Token) -> bool {
+    fn token_is_word(&self, word: &str, tok: &token::Token) -> bool {
         match *tok {
-            token::IDENT(sid, false) => { *self.id_to_str(sid) == *word }
+            token::IDENT(sid, false) => { word == *self.id_to_str(sid) }
              _ => { false }
         }
     }
 
-    fn token_is_keyword(&self, word: &~str, tok: &token::Token) -> bool {
+    fn token_is_keyword(&self, word: &str, tok: &token::Token) -> bool {
         self.require_keyword(word);
         self.token_is_word(word, tok)
     }
 
-    fn is_keyword(&self, word: &~str) -> bool {
+    fn is_keyword(&self, word: &str) -> bool {
         self.token_is_keyword(word, &copy *self.token)
     }
 
@@ -177,10 +177,10 @@ pub impl Parser {
     // if the given word is not a keyword, signal an error.
     // if the next token is the given keyword, eat it and return
     // true. Otherwise, return false.
-    fn eat_keyword(&self, word: &~str) -> bool {
+    fn eat_keyword(&self, word: &str) -> bool {
         self.require_keyword(word);
         let is_kw = match *self.token {
-            token::IDENT(sid, false) => *word == *self.id_to_str(sid),
+            token::IDENT(sid, false) => word == *self.id_to_str(sid),
             _ => false
         };
         if is_kw { self.bump() }
@@ -190,13 +190,13 @@ pub impl Parser {
     // if the given word is not a keyword, signal an error.
     // if the next token is not the given word, signal an error.
     // otherwise, eat it.
-    fn expect_keyword(&self, word: &~str) {
+    fn expect_keyword(&self, word: &str) {
         self.require_keyword(word);
         if !self.eat_keyword(word) {
             self.fatal(
                 fmt!(
                     "expected `%s`, found `%s`",
-                    *word,
+                    word,
                     self.this_token_to_str()
                 )
             );
@@ -204,8 +204,8 @@ pub impl Parser {
     }
 
     // return true if the given string is a strict keyword
-    fn is_strict_keyword(&self, word: &~str) -> bool {
-        self.strict_keywords.contains(word)
+    fn is_strict_keyword(&self, word: &str) -> bool {
+        self.strict_keywords.contains_equiv(&word)
     }
 
     // signal an error if the current token is a strict keyword
@@ -213,22 +213,23 @@ pub impl Parser {
         match *self.token {
             token::IDENT(_, false) => {
                 let w = token_to_str(self.reader, &copy *self.token);
-                self.check_strict_keywords_(&w);
+                self.check_strict_keywords_(w);
             }
             _ => ()
         }
     }
 
     // signal an error if the given string is a strict keyword
-    fn check_strict_keywords_(&self, w: &~str) {
+    fn check_strict_keywords_(&self, w: &str) {
         if self.is_strict_keyword(w) {
-            self.fatal(fmt!("found `%s` in ident position", *w));
+            self.span_err(*self.last_span,
+                          fmt!("found `%s` in ident position", w));
         }
     }
 
     // return true if this is a reserved keyword
-    fn is_reserved_keyword(&self, word: &~str) -> bool {
-        self.reserved_keywords.contains(word)
+    fn is_reserved_keyword(&self, word: &str) -> bool {
+        self.reserved_keywords.contains_equiv(&word)
     }
 
     // signal an error if the current token is a reserved keyword
@@ -236,16 +237,16 @@ pub impl Parser {
         match *self.token {
             token::IDENT(_, false) => {
                 let w = token_to_str(self.reader, &copy *self.token);
-                self.check_reserved_keywords_(&w);
+                self.check_reserved_keywords_(w);
             }
             _ => ()
         }
     }
 
     // signal an error if the given string is a reserved keyword
-    fn check_reserved_keywords_(&self, w: &~str) {
+    fn check_reserved_keywords_(&self, w: &str) {
         if self.is_reserved_keyword(w) {
-            self.fatal(fmt!("`%s` is a reserved keyword", *w));
+            self.fatal(fmt!("`%s` is a reserved keyword", w));
         }
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ce41d377346..9a8a6620652 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -351,15 +351,14 @@ mod test {
     use core::option::None;
     use core::int;
     use core::num::NumCast;
-    use core::path::Path;
-    use codemap::{dummy_sp, CodeMap, span, BytePos, spanned};
+    use codemap::{CodeMap, span, BytePos, spanned};
     use opt_vec;
     use ast;
     use abi;
     use ast_util::mk_ident;
     use parse::parser::Parser;
-    use parse::token::{ident_interner, mk_ident_interner, mk_fresh_ident_interner};
-    use diagnostic::{span_handler, mk_span_handler, mk_handler, Emitter};
+    use parse::token::{ident_interner, mk_fresh_ident_interner};
+    use diagnostic::{mk_span_handler, mk_handler};
 
     // add known names to interner for testing
     fn mk_testing_interner() -> @ident_interner {
@@ -408,7 +407,7 @@ mod test {
 
     // map a string to tts, return the tt without its parsesess
     fn string_to_tts_only(source_str : @~str) -> ~[ast::token_tree] {
-        let (tts,ps) = string_to_tts_t(source_str);
+        let (tts,_ps) = string_to_tts_t(source_str);
         tts
     }
 
@@ -475,13 +474,15 @@ mod test {
                               span:sp(0,6)})
     }
 
-    #[should_fail]
+    // FIXME (#6416): For some reason, this fails and causes a test failure, even though it's
+    // marked as `#[should_fail]`.
+    /*#[should_fail]
     #[test] fn bad_path_expr_1() {
         string_to_expr(@~"::abc::def::return");
-    }
+    }*/
 
     #[test] fn string_to_tts_1 () {
-        let (tts,ps) = string_to_tts_t(@~"fn a (b : int) { b; }");
+        let (tts,_ps) = string_to_tts_t(@~"fn a (b : int) { b; }");
         assert_eq!(to_json_str(@tts),
                    ~"[\
                 [\"tt_tok\",null,[\"IDENT\",\"fn\",false]],\
@@ -546,7 +547,7 @@ mod test {
     }
 
     fn parser_done(p: Parser){
-        assert_eq!(*p.token,token::EOF);
+        assert_eq!(copy *p.token,token::EOF);
     }
 
     #[test] fn parse_ident_pat () {
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index e9e5bdfe13d..859fde90e29 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -61,6 +61,7 @@ pub enum ObsoleteSyntax {
     ObsoleteStaticMethod,
     ObsoleteConstItem,
     ObsoleteFixedLengthVectorType,
+    ObsoleteNamedExternModule,
 }
 
 #[cfg(stage0)]
@@ -225,6 +226,11 @@ pub impl Parser {
                 "fixed-length vector notation",
                 "instead of `[T * N]`, write `[T, ..N]`"
             ),
+            ObsoleteNamedExternModule => (
+                "named external module",
+                "instead of `extern mod foo { ... }`, write `mod foo { \
+                 extern { ... } }`"
+            ),
         };
 
         self.report(sp, kind, kind_str, desc);
@@ -247,9 +253,9 @@ pub impl Parser {
         }
     }
 
-    fn token_is_obsolete_ident(&self, ident: &str, token: Token) -> bool {
-        match token {
-            token::IDENT(copy sid, _) => {
+    fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool {
+        match *token {
+            token::IDENT(sid, _) => {
                 str::eq_slice(*self.id_to_str(sid), ident)
             }
             _ => false
@@ -257,7 +263,7 @@ pub impl Parser {
     }
 
     fn is_obsolete_ident(&self, ident: &str) -> bool {
-        self.token_is_obsolete_ident(ident, *self.token)
+        self.token_is_obsolete_ident(ident, self.token)
     }
 
     fn eat_obsolete_ident(&self, ident: &str) -> bool {
@@ -283,7 +289,7 @@ pub impl Parser {
     fn try_parse_obsolete_with(&self) -> bool {
         if *self.token == token::COMMA
             && self.token_is_obsolete_ident("with",
-                                            self.look_ahead(1u)) {
+                                            &self.look_ahead(1u)) {
             self.bump();
         }
         if self.eat_obsolete_ident("with") {
@@ -295,13 +301,13 @@ pub impl Parser {
         }
     }
 
-    fn try_parse_obsolete_priv_section(&self, attrs: ~[attribute]) -> bool {
-        if self.is_keyword(&~"priv") && self.look_ahead(1) == token::LBRACE {
+    fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) -> bool {
+        if self.is_keyword("priv") && self.look_ahead(1) == token::LBRACE {
             self.obsolete(copy *self.span, ObsoletePrivSection);
-            self.eat_keyword(&~"priv");
+            self.eat_keyword("priv");
             self.bump();
             while *self.token != token::RBRACE {
-                self.parse_single_struct_field(ast::private, attrs);
+                self.parse_single_struct_field(ast::private, attrs.to_owned());
             }
             self.bump();
             true
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5aa45ab3c9b..25b45a5f3b5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -19,14 +19,14 @@ use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
 use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
 use ast::{blk_check_mode, box};
 use ast::{crate, crate_cfg, decl, decl_item};
-use ast::{decl_local, default_blk, deref, div, enum_def};
+use ast::{decl_local, default_blk, deref, div, enum_def, explicit_self};
 use ast::{expr, expr_, expr_addr_of, expr_match, expr_again};
 use ast::{expr_assign, expr_assign_op, expr_binary, expr_block};
 use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
 use ast::{expr_field, expr_fn_block, expr_if, expr_index};
 use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
 use ast::{expr_method_call, expr_paren, expr_path, expr_repeat};
-use ast::{expr_ret, expr_struct, expr_tup, expr_unary};
+use ast::{expr_ret, expr_self, expr_struct, expr_tup, expr_unary};
 use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
 use ast::{expr_vstore_slice, expr_vstore_box};
 use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
@@ -43,7 +43,7 @@ use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
 use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct};
 use ast::{pat_tup, pat_uniq, pat_wild, private};
 use ast::{rem, required};
-use ast::{ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl};
+use ast::{ret_style, return_val, shl, shr, stmt, stmt_decl};
 use ast::{stmt_expr, stmt_semi, stmt_mac, struct_def, struct_field};
 use ast::{struct_variant_kind, subtract};
 use ast::{sty_box, sty_region, sty_static, sty_uniq, sty_value};
@@ -82,6 +82,7 @@ use parse::obsolete::ObsoleteMode;
 use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer};
 use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod};
 use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType};
+use parse::obsolete::{ObsoleteNamedExternModule};
 use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
 use parse::token::{is_plain_ident, INTERPOLATED, special_idents, token_to_binop};
 use parse::token;
@@ -337,10 +338,10 @@ pub impl Parser {
 
     // is this one of the keywords that signals a closure type?
     fn token_is_closure_keyword(&self, tok: &token::Token) -> bool {
-        self.token_is_keyword(&~"pure", tok) ||
-            self.token_is_keyword(&~"unsafe", tok) ||
-            self.token_is_keyword(&~"once", tok) ||
-            self.token_is_keyword(&~"fn", tok)
+        self.token_is_keyword("pure", tok) ||
+            self.token_is_keyword("unsafe", tok) ||
+            self.token_is_keyword("once", tok) ||
+            self.token_is_keyword("fn", tok)
     }
 
     fn token_is_lifetime(&self, tok: &token::Token) -> bool {
@@ -377,7 +378,7 @@ pub impl Parser {
         let opt_abis = self.parse_opt_abis();
         let abis = opt_abis.get_or_default(AbiSet::Rust());
         let purity = self.parse_unsafety();
-        self.expect_keyword(&~"fn");
+        self.expect_keyword("fn");
         let (decl, lifetimes) = self.parse_ty_fn_decl();
         return ty_bare_fn(@TyBareFn {
             abis: abis,
@@ -394,12 +395,13 @@ pub impl Parser {
                         -> ty_ {
         /*
 
-        (&|~|@) ['r] [pure|unsafe] [once] fn <'lt> (S) -> T
-        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~~^ ^~^    ^
-           |     |     |             |         |    |     |
-           |     |     |             |         |    |   Return type
-           |     |     |             |         |  Argument types
-           |     |     |             |     Lifetimes
+        (&|~|@) ['r] [pure|unsafe] [once] fn [:Bounds] <'lt> (S) -> T
+        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~~~~~~^ ^~~~^ ^~^    ^
+           |     |     |             |           |       |    |     |
+           |     |     |             |           |       |    |   Return type
+           |     |     |             |           |       |  Argument types
+           |     |     |             |           |   Lifetimes
+           |     |     |             |       Closure bounds
            |     |     |          Once-ness (a.k.a., affine)
            |     |   Purity
            | Lifetime bound
@@ -412,11 +414,11 @@ pub impl Parser {
 
         let purity = self.parse_unsafety();
         let onceness = parse_onceness(self);
-        self.expect_keyword(&~"fn");
+        self.expect_keyword("fn");
+        let bounds = self.parse_optional_ty_param_bounds();
 
         if self.parse_fn_ty_sigil().is_some() {
-            self.obsolete(*self.span,
-                          ObsoletePostFnTySigil);
+            self.obsolete(*self.span, ObsoletePostFnTySigil);
         }
 
         let (decl, lifetimes) = self.parse_ty_fn_decl();
@@ -426,21 +428,26 @@ pub impl Parser {
             region: region,
             purity: purity,
             onceness: onceness,
+            bounds: bounds,
             decl: decl,
             lifetimes: lifetimes,
         });
 
-        fn parse_onceness(self: &Parser) -> Onceness {
-            if self.eat_keyword(&~"once") { Once } else { Many }
+        fn parse_onceness(this: &Parser) -> Onceness {
+            if this.eat_keyword(~"once") {
+                Once
+            } else {
+                Many
+            }
         }
     }
 
     // looks like this should be called parse_unsafety
     fn parse_unsafety(&self) -> purity {
-        if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("pure") {
             self.obsolete(*self.last_span, ObsoletePurity);
             return impure_fn;
-        } else if self.eat_keyword(&~"unsafe") {
+        } else if self.eat_keyword("unsafe") {
             return unsafe_fn;
         } else {
             return impure_fn;
@@ -500,7 +507,7 @@ pub impl Parser {
 
             let generics = p.parse_generics();
 
-            let (self_ty, d) = do self.parse_fn_decl_with_self() |p| {
+            let (explicit_self, d) = do self.parse_fn_decl_with_self() |p| {
                 // This is somewhat dubious; We don't want to allow argument
                 // names to be left off if there is a definition...
                 either::Left(p.parse_arg_general(false))
@@ -522,7 +529,7 @@ pub impl Parser {
                     purity: pur,
                     decl: d,
                     generics: generics,
-                    self_ty: self_ty,
+                    explicit_self: explicit_self,
                     id: p.get_id(),
                     span: mk_sp(lo, hi)
                 })
@@ -536,7 +543,7 @@ pub impl Parser {
                     ident: ident,
                     attrs: attrs,
                     generics: generics,
-                    self_ty: self_ty,
+                    explicit_self: explicit_self,
                     purity: pur,
                     decl: d,
                     body: body,
@@ -695,7 +702,7 @@ pub impl Parser {
             // BORROWED POINTER
             self.bump();
             self.parse_borrowed_pointee()
-        } else if self.eat_keyword(&~"extern") {
+        } else if self.eat_keyword("extern") {
             // EXTERN FUNCTION
             self.parse_ty_bare_fn()
         } else if self.token_is_closure_keyword(&copy *self.token) {
@@ -704,7 +711,7 @@ pub impl Parser {
             self.obsolete(*self.last_span, ObsoleteBareFnType);
             result
         } else if *self.token == token::MOD_SEP
-            || is_ident_or_path(&*self.token) {
+            || is_ident_or_path(self.token) {
             // NAMED TYPE
             let path = self.parse_path_with_tps(false);
             ty_path(path, self.get_id())
@@ -819,7 +826,7 @@ pub impl Parser {
         let mut is_mutbl = false;
         let pat = if require_name || self.is_named_argument() {
             self.parse_arg_mode();
-            is_mutbl = self.eat_keyword(&~"mut");
+            is_mutbl = self.eat_keyword("mut");
             let pat = self.parse_pat(false);
             self.expect(&token::COLON);
             pat
@@ -847,7 +854,7 @@ pub impl Parser {
     // parse an argument in a lambda header e.g. |arg, arg|
     fn parse_fn_block_arg(&self) -> arg_or_capture_item {
         self.parse_arg_mode();
-        let is_mutbl = self.eat_keyword(&~"mut");
+        let is_mutbl = self.eat_keyword("mut");
         let pat = self.parse_pat(false);
         let t = if self.eat(&token::COLON) {
             self.parse_ty(false)
@@ -898,9 +905,9 @@ pub impl Parser {
     // matches lit = true | false | token_lit
     fn parse_lit(&self) -> lit {
         let lo = self.span.lo;
-        let lit = if self.eat_keyword(&~"true") {
+        let lit = if self.eat_keyword("true") {
             lit_bool(true)
-        } else if self.eat_keyword(&~"false") {
+        } else if self.eat_keyword("false") {
             lit_bool(false)
         } else {
             // XXX: This is a really bad copy!
@@ -911,6 +918,24 @@ pub impl Parser {
         codemap::spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
     }
 
+    // matches '-' lit | lit
+    fn parse_literal_maybe_minus(&self) -> @expr {
+        let minus_lo = self.span.lo;
+        let minus_present = self.eat(&token::BINOP(token::MINUS));
+
+        let lo = self.span.lo;
+        let literal = @self.parse_lit();
+        let hi = self.span.hi;
+        let expr = self.mk_expr(lo, hi, expr_lit(literal));
+
+        if minus_present {
+            let minus_hi = self.span.hi;
+            self.mk_expr(minus_lo, minus_hi, expr_unary(neg, expr))
+        } else {
+            expr
+        }
+    }
+
     // parse a path into a vector of idents, whether the path starts
     // with ::, and a span.
     fn parse_path(&self) -> (~[ast::ident],bool,span) {
@@ -1118,15 +1143,15 @@ pub impl Parser {
     }
 
     fn token_is_mutability(&self, tok: &token::Token) -> bool {
-        self.token_is_keyword(&~"mut", tok) ||
-        self.token_is_keyword(&~"const", tok)
+        self.token_is_keyword("mut", tok) ||
+        self.token_is_keyword("const", tok)
     }
 
     // parse mutability declaration (mut/const/imm)
     fn parse_mutability(&self) -> mutability {
-        if self.eat_keyword(&~"mut") {
+        if self.eat_keyword("mut") {
             m_mutbl
-        } else if self.eat_keyword(&~"const") {
+        } else if self.eat_keyword("const") {
             m_const
         } else {
             m_imm
@@ -1224,27 +1249,30 @@ pub impl Parser {
                                  expr_block(blk));
         } else if token::is_bar(&*self.token) {
             return self.parse_lambda_expr();
-        } else if self.eat_keyword(&~"if") {
+        } else if self.eat_keyword("self") {
+            ex = expr_self;
+            hi = self.span.hi;
+        } else if self.eat_keyword("if") {
             return self.parse_if_expr();
-        } else if self.eat_keyword(&~"for") {
+        } else if self.eat_keyword("for") {
             return self.parse_sugary_call_expr(~"for", ForSugar,
                                                expr_loop_body);
-        } else if self.eat_keyword(&~"do") {
+        } else if self.eat_keyword("do") {
             return self.parse_sugary_call_expr(~"do", DoSugar,
                                                expr_do_body);
-        } else if self.eat_keyword(&~"while") {
+        } else if self.eat_keyword("while") {
             return self.parse_while_expr();
         } else if self.token_is_lifetime(&*self.token) {
             let lifetime = self.get_lifetime(&*self.token);
             self.bump();
             self.expect(&token::COLON);
-            self.expect_keyword(&~"loop");
+            self.expect_keyword("loop");
             return self.parse_loop_expr(Some(lifetime));
-        } else if self.eat_keyword(&~"loop") {
+        } else if self.eat_keyword("loop") {
             return self.parse_loop_expr(None);
-        } else if self.eat_keyword(&~"match") {
+        } else if self.eat_keyword("match") {
             return self.parse_match_expr();
-        } else if self.eat_keyword(&~"unsafe") {
+        } else if self.eat_keyword("unsafe") {
             return self.parse_block_expr(lo, unsafe_blk);
         } else if *self.token == token::LBRACKET {
             self.bump();
@@ -1284,7 +1312,7 @@ pub impl Parser {
                 }
             }
             hi = self.span.hi;
-        } else if self.eat_keyword(&~"__log") {
+        } else if self.eat_keyword("__log") {
             // LOG expression
             self.expect(&token::LPAREN);
             let lvl = self.parse_expr();
@@ -1293,14 +1321,14 @@ pub impl Parser {
             ex = expr_log(lvl, e);
             hi = self.span.hi;
             self.expect(&token::RPAREN);
-        } else if self.eat_keyword(&~"return") {
+        } else if self.eat_keyword("return") {
             // RETURN expression
             if can_begin_expr(&*self.token) {
                 let e = self.parse_expr();
                 hi = e.span.hi;
                 ex = expr_ret(Some(e));
             } else { ex = expr_ret(None); }
-        } else if self.eat_keyword(&~"break") {
+        } else if self.eat_keyword("break") {
             // BREAK expression
             if self.token_is_lifetime(&*self.token) {
                 let lifetime = self.get_lifetime(&*self.token);
@@ -1310,14 +1338,14 @@ pub impl Parser {
                 ex = expr_break(None);
             }
             hi = self.span.hi;
-        } else if self.eat_keyword(&~"copy") {
+        } else if self.eat_keyword("copy") {
             // COPY expression
             let e = self.parse_expr();
             ex = expr_copy(e);
             hi = e.span.hi;
         } else if *self.token == token::MOD_SEP ||
-                is_ident(&*self.token) && !self.is_keyword(&~"true") &&
-                !self.is_keyword(&~"false") {
+                is_ident(&*self.token) && !self.is_keyword("true") &&
+                !self.is_keyword("false") {
             let pth = self.parse_path_with_tps(true);
 
             // `!`, as an operator, is prefix, so we know this isn't that
@@ -1531,9 +1559,12 @@ pub impl Parser {
                         |p| p.parse_token_tree()
                     );
                     let (s, z) = p.parse_sep_and_zerok();
+                    let seq = match seq {
+                        spanned { node, _ } => node,
+                    };
                     tt_seq(
-                        mk_sp(sp.lo ,p.span.hi),
-                        seq.node,
+                        mk_sp(sp.lo, p.span.hi),
+                        seq,
                         s,
                         z
                     )
@@ -1599,9 +1630,9 @@ pub impl Parser {
             token::LBRACE | token::LPAREN | token::LBRACKET => {
                 self.parse_matcher_subseq(
                     name_idx,
-                    *self.token,
+                    copy *self.token,
                     // tjc: not sure why we need a copy
-                    token::flip_delimiter(&*self.token)
+                    token::flip_delimiter(self.token)
                 )
             }
             _ => self.fatal(~"expected open delimiter")
@@ -1794,7 +1825,7 @@ pub impl Parser {
                     }
                 }
                 None => {
-                    if as_prec > min_prec && self.eat_keyword(&~"as") {
+                    if as_prec > min_prec && self.eat_keyword("as") {
                         let rhs = self.parse_ty(true);
                         let _as = self.mk_expr(lhs.span.lo,
                                                rhs.span.hi,
@@ -1868,7 +1899,7 @@ pub impl Parser {
         let thn = self.parse_block();
         let mut els: Option<@expr> = None;
         let mut hi = thn.span.hi;
-        if self.eat_keyword(&~"else") {
+        if self.eat_keyword("else") {
             let elexpr = self.parse_else_expr();
             els = Some(elexpr);
             hi = elexpr.span.hi;
@@ -1935,7 +1966,7 @@ pub impl Parser {
     }
 
     fn parse_else_expr(&self) -> @expr {
-        if self.eat_keyword(&~"if") {
+        if self.eat_keyword("if") {
             return self.parse_if_expr();
         } else {
             let blk = self.parse_block();
@@ -1961,14 +1992,15 @@ pub impl Parser {
         // them as the lambda arguments
         let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
         match e.node {
-            expr_call(f, args, NoSugar) => {
+            expr_call(f, /*bad*/ copy args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 let args = vec::append(args, ~[last_arg]);
                 self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar))
             }
-            expr_method_call(f, i, tps, args, NoSugar) => {
+            expr_method_call(f, i, /*bad*/ copy tps,
+                             /*bad*/ copy args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
@@ -1976,7 +2008,7 @@ pub impl Parser {
                 self.mk_expr(lo.lo, block.span.hi,
                              expr_method_call(f, i, tps, args, sugar))
             }
-            expr_field(f, i, tps) => {
+            expr_field(f, i, /*bad*/ copy tps) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
@@ -2048,7 +2080,7 @@ pub impl Parser {
     fn looking_at_record_literal(&self) -> bool {
         let lookahead = self.look_ahead(1);
         *self.token == token::LBRACE &&
-            (self.token_is_keyword(&~"mut", &lookahead) ||
+            (self.token_is_keyword("mut", &lookahead) ||
              (is_plain_ident(&lookahead) &&
               self.look_ahead(2) == token::COLON))
     }
@@ -2061,7 +2093,7 @@ pub impl Parser {
         while *self.token != token::RBRACE {
             let pats = self.parse_pats();
             let mut guard = None;
-            if self.eat_keyword(&~"if") { guard = Some(self.parse_expr()); }
+            if self.eat_keyword("if") { guard = Some(self.parse_expr()); }
             self.expect(&token::FAT_ARROW);
             let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
 
@@ -2234,7 +2266,7 @@ pub impl Parser {
         let lo = self.span.lo;
         let mut hi = self.span.hi;
         let pat;
-        match *self.token {
+        match /*bad*/ copy *self.token {
             // parse _
           token::UNDERSCORE => { self.bump(); pat = pat_wild; }
             // parse @pat
@@ -2348,24 +2380,33 @@ pub impl Parser {
             self.expect(&token::RBRACKET);
             pat = ast::pat_vec(before, slice, after);
           }
-          tok => {
-            if !is_ident_or_path(&tok)
-                || self.is_keyword(&~"true")
-                || self.is_keyword(&~"false")
+          ref tok => {
+            if !is_ident_or_path(tok)
+                || self.is_keyword("true")
+                || self.is_keyword("false")
             {
-                // parse an expression pattern or exp .. exp
-                let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                // Parse an expression pattern or exp .. exp.
+                //
+                // These expressions are limited to literals (possibly
+                // preceded by unary-minus) or identifiers.
+                let val = self.parse_literal_maybe_minus();
                 if self.eat(&token::DOTDOT) {
-                    let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
+                    let end = if is_ident_or_path(tok) {
+                        let path = self.parse_path_with_tps(true);
+                        let hi = self.span.hi;
+                        self.mk_expr(lo, hi, expr_path(path))
+                    } else {
+                        self.parse_literal_maybe_minus()
+                    };
                     pat = pat_range(val, end);
                 } else {
                     pat = pat_lit(val);
                 }
-            } else if self.eat_keyword(&~"ref") {
+            } else if self.eat_keyword("ref") {
                 // parse ref pat
                 let mutbl = self.parse_mutability();
                 pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
-            } else if self.eat_keyword(&~"copy") {
+            } else if self.eat_keyword("copy") {
                 // parse copy pat
                 pat = self.parse_pat_ident(refutable, bind_by_copy);
             } else {
@@ -2433,7 +2474,7 @@ pub impl Parser {
                                   }
                               },
                               _ => {
-                                  if vec::len(enum_path.idents)==1u {
+                                  if enum_path.idents.len()==1u {
                                       // it could still be either an enum
                                       // or an identifier pattern, resolve
                                       // will sort it out:
@@ -2514,7 +2555,7 @@ pub impl Parser {
 
     // parse a "let" stmt
     fn parse_let(&self) -> @decl {
-        let is_mutbl = self.eat_keyword(&~"mut");
+        let is_mutbl = self.eat_keyword("mut");
         let lo = self.span.lo;
         let mut locals = ~[self.parse_local(is_mutbl)];
         while self.eat(&token::COMMA) {
@@ -2528,7 +2569,7 @@ pub impl Parser {
                          pr: visibility,
                          attrs: ~[attribute]) -> @struct_field {
         let lo = self.span.lo;
-        if self.eat_keyword(&~"mut") {
+        if self.eat_keyword("mut") {
             // Do nothing, for backwards compatibility.
             // XXX: Remove after snapshot.
         }
@@ -2558,9 +2599,9 @@ pub impl Parser {
         }
 
         let lo = self.span.lo;
-        if self.is_keyword(&~"let") {
+        if self.is_keyword("let") {
             check_expected_item(self, first_item_attrs);
-            self.expect_keyword(&~"let");
+            self.expect_keyword("let");
             let decl = self.parse_let();
             return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
         } else if is_ident(&*self.token)
@@ -2647,7 +2688,7 @@ pub impl Parser {
         maybe_whole!(self, nt_block);
 
         let lo = self.span.lo;
-        if self.eat_keyword(&~"unsafe") {
+        if self.eat_keyword("unsafe") {
             self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
         }
         self.expect(&token::LBRACE);
@@ -2662,7 +2703,7 @@ pub impl Parser {
         maybe_whole!(pair_empty self, nt_block);
 
         let lo = self.span.lo;
-        if self.eat_keyword(&~"unsafe") {
+        if self.eat_keyword("unsafe") {
             self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
         }
         self.expect(&token::LBRACE);
@@ -2796,10 +2837,10 @@ pub impl Parser {
     }
 
     fn parse_optional_purity(&self) -> ast::purity {
-        if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("pure") {
             self.obsolete(*self.last_span, ObsoletePurity);
             ast::impure_fn
-        } else if self.eat_keyword(&~"unsafe") {
+        } else if self.eat_keyword("unsafe") {
             ast::unsafe_fn
         } else {
             ast::impure_fn
@@ -2807,15 +2848,15 @@ pub impl Parser {
     }
 
     fn parse_optional_onceness(&self) -> ast::Onceness {
-        if self.eat_keyword(&~"once") { ast::Once } else { ast::Many }
+        if self.eat_keyword("once") { ast::Once } else { ast::Many }
     }
 
     // matches optbounds = ( ( : ( boundseq )? )? )
     // where   boundseq  = ( bound + boundseq ) | bound
     // and     bound     = 'static | ty
-    fn parse_optional_ty_param_bounds(&self) -> @OptVec<TyParamBound> {
+    fn parse_optional_ty_param_bounds(&self) -> OptVec<TyParamBound> {
         if !self.eat(&token::COLON) {
-            return @opt_vec::Empty;
+            return opt_vec::Empty;
         }
 
         let mut result = opt_vec::Empty;
@@ -2863,19 +2904,19 @@ pub impl Parser {
                 loop;
             }
 
-            if is_ident_or_path(&*self.token) {
+            if is_ident_or_path(self.token) {
                 self.obsolete(*self.span,
                               ObsoleteTraitBoundSeparator);
             }
         }
 
-        return @result;
+        return result;
     }
 
     // matches typaram = IDENT optbounds
     fn parse_ty_param(&self) -> TyParam {
         let ident = self.parse_ident();
-        let bounds = self.parse_optional_ty_param_bounds();
+        let bounds = @self.parse_optional_ty_param_bounds();
         ast::TyParam { ident: ident, id: self.get_id(), bounds: bounds }
     }
 
@@ -2964,16 +3005,16 @@ pub impl Parser {
         &self,
         parse_arg_fn:
         &fn(&Parser) -> arg_or_capture_item
-    ) -> (self_ty, fn_decl) {
-        fn maybe_parse_self_ty(
-            cnstr: &fn(v: mutability) -> ast::self_ty_,
+    ) -> (explicit_self, fn_decl) {
+        fn maybe_parse_explicit_self(
+            cnstr: &fn(v: mutability) -> ast::explicit_self_,
             p: &Parser
-        ) -> ast::self_ty_ {
+        ) -> ast::explicit_self_ {
             // We need to make sure it isn't a mode or a type
-            if p.token_is_keyword(&~"self", &p.look_ahead(1)) ||
-                ((p.token_is_keyword(&~"const", &p.look_ahead(1)) ||
-                  p.token_is_keyword(&~"mut", &p.look_ahead(1))) &&
-                 p.token_is_keyword(&~"self", &p.look_ahead(2))) {
+            if p.token_is_keyword("self", &p.look_ahead(1)) ||
+                ((p.token_is_keyword("const", &p.look_ahead(1)) ||
+                  p.token_is_keyword("mut", &p.look_ahead(1))) &&
+                 p.token_is_keyword("self", &p.look_ahead(2))) {
 
                 p.bump();
                 let mutability = p.parse_mutability();
@@ -2984,9 +3025,7 @@ pub impl Parser {
             }
         }
 
-        fn maybe_parse_borrowed_self_ty(
-            self: &Parser
-        ) -> ast::self_ty_ {
+        fn maybe_parse_borrowed_explicit_self(this: &Parser) -> ast::explicit_self_ {
             // The following things are possible to see here:
             //
             //     fn(&self)
@@ -2996,37 +3035,29 @@ pub impl Parser {
             //
             // We already know that the current token is `&`.
 
-            if (
-                self.token_is_keyword(&~"self", &self.look_ahead(1)))
-            {
-                self.bump();
-                self.expect_self_ident();
+            if (this.token_is_keyword("self", &this.look_ahead(1))) {
+                this.bump();
+                this.expect_self_ident();
                 sty_region(None, m_imm)
-            } else if (
-                self.token_is_mutability(&self.look_ahead(1)) &&
-                self.token_is_keyword(&~"self", &self.look_ahead(2)))
-            {
-                self.bump();
-                let mutability = self.parse_mutability();
-                self.expect_self_ident();
+            } else if (this.token_is_mutability(&this.look_ahead(1)) &&
+                       this.token_is_keyword("self", &this.look_ahead(2))) {
+                this.bump();
+                let mutability = this.parse_mutability();
+                this.expect_self_ident();
                 sty_region(None, mutability)
-            } else if (
-                self.token_is_lifetime(&self.look_ahead(1)) &&
-                self.token_is_keyword(&~"self", &self.look_ahead(2)))
-            {
-                self.bump();
-                let lifetime = @self.parse_lifetime();
-                self.expect_self_ident();
+            } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
+                       this.token_is_keyword("self", &this.look_ahead(2))) {
+                this.bump();
+                let lifetime = @this.parse_lifetime();
+                this.expect_self_ident();
                 sty_region(Some(lifetime), m_imm)
-            } else if (
-                self.token_is_lifetime(&self.look_ahead(1)) &&
-                self.token_is_mutability(&self.look_ahead(2)) &&
-                self.token_is_keyword(&~"self", &self.look_ahead(3)))
-            {
-                self.bump();
-                let lifetime = @self.parse_lifetime();
-                let mutability = self.parse_mutability();
-                self.expect_self_ident();
+            } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
+                       this.token_is_mutability(&this.look_ahead(2)) &&
+                       this.token_is_keyword("self", &this.look_ahead(3))) {
+                this.bump();
+                let lifetime = @this.parse_lifetime();
+                let mutability = this.parse_mutability();
+                this.expect_self_ident();
                 sty_region(Some(lifetime), mutability)
             } else {
                 sty_static
@@ -3038,15 +3069,15 @@ pub impl Parser {
         // A bit of complexity and lookahead is needed here in order to to be
         // backwards compatible.
         let lo = self.span.lo;
-        let self_ty = match *self.token {
+        let explicit_self = match *self.token {
           token::BINOP(token::AND) => {
-            maybe_parse_borrowed_self_ty(self)
+            maybe_parse_borrowed_explicit_self(self)
           }
           token::AT => {
-            maybe_parse_self_ty(sty_box, self)
+            maybe_parse_explicit_self(sty_box, self)
           }
           token::TILDE => {
-            maybe_parse_self_ty(sty_uniq, self)
+            maybe_parse_explicit_self(sty_uniq, self)
           }
           token::IDENT(*) if self.is_self_ident() => {
             self.bump();
@@ -3059,7 +3090,7 @@ pub impl Parser {
 
         // If we parsed a self type, expect a comma before the argument list.
         let args_or_capture_items;
-        if self_ty != sty_static {
+        if explicit_self != sty_static {
             match *self.token {
                 token::COMMA => {
                     self.bump();
@@ -3104,7 +3135,7 @@ pub impl Parser {
             cf: ret_style
         };
 
-        (spanned(lo, hi, self_ty), fn_decl)
+        (spanned(lo, hi, explicit_self), fn_decl)
     }
 
     // parse the |arg, arg| header on a lambda
@@ -3171,7 +3202,7 @@ pub impl Parser {
         let pur = self.parse_fn_purity();
         let ident = self.parse_ident();
         let generics = self.parse_generics();
-        let (self_ty, decl) = do self.parse_fn_decl_with_self() |p| {
+        let (explicit_self, decl) = do self.parse_fn_decl_with_self() |p| {
             p.parse_arg()
         };
 
@@ -3182,7 +3213,7 @@ pub impl Parser {
             ident: ident,
             attrs: attrs,
             generics: generics,
-            self_ty: self_ty,
+            explicit_self: explicit_self,
             purity: pur,
             decl: decl,
             body: body,
@@ -3231,7 +3262,7 @@ pub impl Parser {
         let mut ty = self.parse_ty(false);
 
         // Parse traits, if necessary.
-        let opt_trait = if could_be_trait && self.eat_keyword(&~"for") {
+        let opt_trait = if could_be_trait && self.eat_keyword("for") {
             // New-style trait. Reinterpret the type as a trait.
             let opt_trait_ref = match ty.node {
                 ty_path(path, node_id) => {
@@ -3406,11 +3437,11 @@ pub impl Parser {
             return ~[];
         }
 
-        if self.eat_keyword(&~"priv") {
+        if self.eat_keyword("priv") {
             return ~[self.parse_single_struct_field(private, attrs)]
         }
 
-        if self.eat_keyword(&~"pub") {
+        if self.eat_keyword("pub") {
            return ~[self.parse_single_struct_field(public, attrs)];
         }
 
@@ -3423,13 +3454,13 @@ pub impl Parser {
 
     // parse visiility: PUB, PRIV, or nothing
     fn parse_visibility(&self) -> visibility {
-        if self.eat_keyword(&~"pub") { public }
-        else if self.eat_keyword(&~"priv") { private }
+        if self.eat_keyword("pub") { public }
+        else if self.eat_keyword("priv") { private }
         else { inherited }
     }
 
     fn parse_staticness(&self) -> bool {
-        if self.eat_keyword(&~"static") {
+        if self.eat_keyword("static") {
             self.obsolete(*self.last_span, ObsoleteStaticMethod);
             true
         } else {
@@ -3507,6 +3538,7 @@ pub impl Parser {
     fn parse_item_mod(&self, outer_attrs: ~[ast::attribute]) -> item_info {
         let id_span = *self.span;
         let id = self.parse_ident();
+        let merge = ::attr::first_attr_value_str_by_name(outer_attrs, "merge");
         let info_ = if *self.token == token::SEMI {
             self.bump();
             // This mod is in an external file. Let's go get it!
@@ -3526,7 +3558,7 @@ pub impl Parser {
         // (int-template, iter-trait). If there's a 'merge' attribute
         // on the mod, then we'll go and suck in another file and merge
         // its contents
-        match ::attr::first_attr_value_str_by_name(outer_attrs, ~"merge") {
+        match merge {
             Some(path) => {
                 let prefix = Path(
                     self.sess.cm.span_to_filename(*self.span));
@@ -3612,10 +3644,7 @@ pub impl Parser {
             new_sub_parser_from_file(self.sess, copy self.cfg,
                                      &full_path, id_sp);
         let (inner, next) = p0.parse_inner_attrs_and_next();
-        let mod_attrs = vec::append(
-            /*bad*/ copy outer_attrs,
-            inner
-        );
+        let mod_attrs = vec::append(outer_attrs, inner);
         let first_item_outer_attrs = next;
         let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
         return (ast::item_mod(m0), mod_attrs);
@@ -3651,10 +3680,10 @@ pub impl Parser {
         let lo = self.span.lo;
 
         // XXX: Obsolete; remove after snap.
-        if self.eat_keyword(&~"const") {
+        if self.eat_keyword("const") {
             self.obsolete(*self.last_span, ObsoleteConstItem);
         } else {
-            self.expect_keyword(&~"static");
+            self.expect_keyword("static");
         }
 
         let ident = self.parse_ident();
@@ -3672,14 +3701,14 @@ pub impl Parser {
 
     // parse safe/unsafe and fn
     fn parse_fn_purity(&self) -> purity {
-        if self.eat_keyword(&~"fn") { impure_fn }
-        else if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("fn") { impure_fn }
+        else if self.eat_keyword("pure") {
             self.obsolete(*self.last_span, ObsoletePurity);
-            self.expect_keyword(&~"fn");
+            self.expect_keyword("fn");
             // NB: We parse this as impure for bootstrapping purposes.
             impure_fn
-        } else if self.eat_keyword(&~"unsafe") {
-            self.expect_keyword(&~"fn");
+        } else if self.eat_keyword("unsafe") {
+            self.expect_keyword("fn");
             unsafe_fn
         }
         else { self.unexpected(); }
@@ -3688,10 +3717,11 @@ pub impl Parser {
 
     // at this point, this is essentially a wrapper for
     // parse_foreign_items.
-    fn parse_foreign_mod_items(&self, sort: ast::foreign_mod_sort,
+    fn parse_foreign_mod_items(&self,
+                               sort: ast::foreign_mod_sort,
                                abis: AbiSet,
                                first_item_attrs: ~[attribute])
-                            -> foreign_mod {
+                               -> foreign_mod {
         let ParsedItemsAndViewItems {
             attrs_remaining: _,
             view_items: view_items,
@@ -3714,12 +3744,11 @@ pub impl Parser {
                               visibility: visibility,
                               attrs: ~[attribute],
                               items_allowed: bool)
-                           -> item_or_view_item
-    {
+                              -> item_or_view_item {
         let mut must_be_named_mod = false;
-        if self.is_keyword(&~"mod") {
+        if self.is_keyword("mod") {
             must_be_named_mod = true;
-            self.expect_keyword(&~"mod");
+            self.expect_keyword("mod");
         } else if *self.token != token::LBRACE {
             self.span_fatal(
                 copy *self.span,
@@ -3750,6 +3779,11 @@ pub impl Parser {
 
         // extern mod foo { ... } or extern { ... }
         if items_allowed && self.eat(&token::LBRACE) {
+            // `extern mod foo { ... }` is obsolete.
+            if sort == ast::named {
+                self.obsolete(*self.last_span, ObsoleteNamedExternModule);
+            }
+
             let abis = opt_abis.get_or_default(AbiSet::C());
 
             let (inner, next) = self.parse_inner_attrs_and_next();
@@ -3999,7 +4033,7 @@ pub impl Parser {
         let visibility = self.parse_visibility();
 
         // must be a view item:
-        if self.eat_keyword(&~"use") {
+        if self.eat_keyword("use") {
             // USE ITEM (iovi_view_item)
             let view_item = self.parse_use();
             self.expect(&token::SEMI);
@@ -4011,10 +4045,10 @@ pub impl Parser {
             });
         }
         // either a view item or an item:
-        if self.eat_keyword(&~"extern") {
+        if self.eat_keyword("extern") {
             let opt_abis = self.parse_opt_abis();
 
-            if self.eat_keyword(&~"fn") {
+            if self.eat_keyword("fn") {
                 // EXTERN FUNCTION ITEM
                 let abis = opt_abis.get_or_default(AbiSet::C());
                 let (ident, item_, extra_attrs) =
@@ -4030,11 +4064,11 @@ pub impl Parser {
             }
         }
         // the rest are all guaranteed to be items:
-        if (self.is_keyword(&~"const") ||
-            (self.is_keyword(&~"static") &&
-             !self.token_is_keyword(&~"fn", &self.look_ahead(1)))) {
+        if (self.is_keyword("const") ||
+            (self.is_keyword("static") &&
+             !self.token_is_keyword("fn", &self.look_ahead(1)))) {
             // CONST / STATIC ITEM
-            if self.is_keyword(&~"const") {
+            if self.is_keyword("const") {
                 self.obsolete(*self.span, ObsoleteConstItem);
             }
             self.bump();
@@ -4043,7 +4077,7 @@ pub impl Parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.is_keyword(&~"fn") &&
+        if self.is_keyword("fn") &&
             !self.fn_expr_lookahead(self.look_ahead(1u)) {
             // FUNCTION ITEM
             self.bump();
@@ -4053,56 +4087,57 @@ pub impl Parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"pure") {
+        if self.eat_keyword("pure") {
             // PURE FUNCTION ITEM (obsolete)
             self.obsolete(*self.last_span, ObsoletePurity);
-            self.expect_keyword(&~"fn");
+            self.expect_keyword("fn");
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(impure_fn, AbiSet::Rust());
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.is_keyword(&~"unsafe")
+        if self.is_keyword("unsafe")
             && self.look_ahead(1u) != token::LBRACE {
             // UNSAFE FUNCTION ITEM
             self.bump();
-            self.expect_keyword(&~"fn");
+            self.expect_keyword("fn");
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(unsafe_fn, AbiSet::Rust());
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"mod") {
+        if self.eat_keyword("mod") {
             // MODULE ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
+            let (ident, item_, extra_attrs) =
+                self.parse_item_mod(/*bad*/ copy attrs);
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"type") {
+        if self.eat_keyword("type") {
             // TYPE ITEM
             let (ident, item_, extra_attrs) = self.parse_item_type();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"enum") {
+        if self.eat_keyword("enum") {
             // ENUM ITEM
             let (ident, item_, extra_attrs) = self.parse_item_enum();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"trait") {
+        if self.eat_keyword("trait") {
             // TRAIT ITEM
             let (ident, item_, extra_attrs) = self.parse_item_trait();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"impl") {
+        if self.eat_keyword("impl") {
             // IMPL ITEM
             let (ident, item_, extra_attrs) =
                 self.parse_item_impl(visibility);
@@ -4110,7 +4145,7 @@ pub impl Parser {
                                           visibility,
                                           maybe_append(attrs, extra_attrs)));
         }
-        if self.eat_keyword(&~"struct") {
+        if self.eat_keyword("struct") {
             // STRUCT ITEM
             let (ident, item_, extra_attrs) = self.parse_item_struct();
             return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
@@ -4131,13 +4166,13 @@ pub impl Parser {
 
         let visibility = self.parse_visibility();
 
-        if (self.is_keyword(&~"const") || self.is_keyword(&~"static")) {
+        if (self.is_keyword("const") || self.is_keyword("static")) {
             // FOREIGN CONST ITEM
             let item = self.parse_item_foreign_const(visibility, attrs);
             return iovi_foreign_item(item);
         }
-        if (self.is_keyword(&~"fn") || self.is_keyword(&~"pure") ||
-             self.is_keyword(&~"unsafe")) {
+        if (self.is_keyword("fn") || self.is_keyword("pure") ||
+             self.is_keyword("unsafe")) {
             // FOREIGN FUNCTION ITEM
                 let item = self.parse_item_foreign_fn(attrs);
                 return iovi_foreign_item(item);
@@ -4305,7 +4340,7 @@ pub impl Parser {
           }
           _ => ()
         }
-        let last = path[vec::len(path) - 1u];
+        let last = path[path.len() - 1u];
         let path = @ast::Path { span: mk_sp(lo, self.span.hi),
                                 global: false,
                                 idents: path,
@@ -4328,16 +4363,16 @@ pub impl Parser {
 
     fn is_view_item(&self) -> bool {
         let tok, next_tok;
-        if !self.is_keyword(&~"pub") && !self.is_keyword(&~"priv") {
+        if !self.is_keyword("pub") && !self.is_keyword("priv") {
             tok = copy *self.token;
             next_tok = self.look_ahead(1);
         } else {
             tok = self.look_ahead(1);
             next_tok = self.look_ahead(2);
         };
-        self.token_is_keyword(&~"use", &tok)
-            || (self.token_is_keyword(&~"extern", &tok) &&
-                self.token_is_keyword(&~"mod", &next_tok))
+        self.token_is_keyword("use", &tok)
+            || (self.token_is_keyword("extern", &tok) &&
+                self.token_is_keyword("mod", &next_tok))
     }
 
     // parse a view item.
@@ -4347,10 +4382,10 @@ pub impl Parser {
         vis: visibility
     ) -> @view_item {
         let lo = self.span.lo;
-        let node = if self.eat_keyword(&~"use") {
+        let node = if self.eat_keyword("use") {
             self.parse_use()
-        } else if self.eat_keyword(&~"extern") {
-            self.expect_keyword(&~"mod");
+        } else if self.eat_keyword("extern") {
+            self.expect_keyword("mod");
             let ident = self.parse_ident();
             let metadata = self.parse_optional_meta();
             view_item_extern_mod(ident, metadata, self.get_id())
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 5688678b06a..36f241b6427 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -18,9 +18,7 @@ use core::cmp::Equiv;
 use core::hashmap::HashSet;
 use core::to_bytes;
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Encodable, Decodable, Eq)]
 pub enum binop {
     PLUS,
     MINUS,
@@ -34,9 +32,7 @@ pub enum binop {
     SHR,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Encodable, Decodable, Eq)]
 pub enum Token {
     /* Expression-operator symbols. */
     EQ,
@@ -97,9 +93,7 @@ pub enum Token {
     EOF,
 }
 
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
+#[deriving(Encodable, Decodable, Eq)]
 /// For interpolation during macro expansion.
 pub enum nonterminal {
     nt_item(@ast::item),
@@ -211,7 +205,7 @@ pub fn to_str(in: @ident_interner, t: &Token) -> ~str {
                       nt_block(*) => ~"block",
                       nt_stmt(*) => ~"statement",
                       nt_pat(*) => ~"pattern",
-                      nt_expr(*) => fail!(~"should have been handled above"),
+                      nt_expr(*) => fail!("should have been handled above"),
                       nt_ty(*) => ~"type",
                       nt_ident(*) => ~"identifier",
                       nt_path(*) => ~"path",
@@ -340,7 +334,7 @@ pub mod special_idents {
     pub static main : ident = ident { repr: 26, ctxt: 0};
     pub static opaque : ident = ident { repr: 27, ctxt: 0};
     pub static blk : ident = ident { repr: 28, ctxt: 0};
-    pub static static : ident = ident { repr: 29, ctxt: 0};
+    pub static statik : ident = ident { repr: 29, ctxt: 0};
     pub static intrinsic : ident = ident { repr: 30, ctxt: 0};
     pub static clownshoes_foreign_mod: ident = ident { repr: 31, ctxt: 0};
     pub static unnamed_field: ident = ident { repr: 32, ctxt: 0};
@@ -357,12 +351,14 @@ impl<'self> Equiv<@~str> for StringRef<'self> {
 
 #[cfg(stage0)]
 impl<'self> to_bytes::IterBytes for StringRef<'self> {
+    #[inline(always)]
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
         (**self).iter_bytes(lsb0, f);
     }
 }
 #[cfg(not(stage0))]
 impl<'self> to_bytes::IterBytes for StringRef<'self> {
+    #[inline(always)]
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
         (**self).iter_bytes(lsb0, f)
     }
@@ -504,26 +500,17 @@ pub fn mk_fake_ident_interner() -> @ident_interner {
  */
 pub fn keyword_table() -> HashSet<~str> {
     let mut keywords = HashSet::new();
-    let mut tmp = temporary_keyword_table();
     let mut strict = strict_keyword_table();
     let mut reserved = reserved_keyword_table();
 
-    do tmp.consume |word|      { keywords.insert(word); }
-    do strict.consume |word|   { keywords.insert(word); }
-    do reserved.consume |word| { keywords.insert(word); }
-    return keywords;
-}
-
-/// Keywords that may be used as identifiers
-pub fn temporary_keyword_table() -> HashSet<~str> {
-    let mut words = HashSet::new();
-    let keys = ~[
-        ~"self", ~"static",
-    ];
-    do vec::consume(keys) |_, s| {
-        words.insert(s);
+    do strict.consume |word| {
+        keywords.insert(word);
     }
-    return words;
+    do reserved.consume |word| {
+        keywords.insert(word);
+    }
+
+    keywords
 }
 
 /// Full keywords. May not appear anywhere else.
@@ -542,7 +529,7 @@ pub fn strict_keyword_table() -> HashSet<~str> {
         ~"once",
         ~"priv", ~"pub", ~"pure",
         ~"ref", ~"return",
-        ~"struct", ~"super",
+        ~"static", ~"self", ~"struct", ~"super",
         ~"true", ~"trait", ~"type",
         ~"unsafe", ~"use",
         ~"while"
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 43f62d72a9f..38c58612f43 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -110,8 +110,8 @@ pub fn tok_str(t: token) -> ~str {
 
 pub fn buf_str(toks: ~[token], szs: ~[int], left: uint, right: uint,
                lim: uint) -> ~str {
-    let n = vec::len(toks);
-    assert!(n == vec::len(szs));
+    let n = toks.len();
+    assert!(n == szs.len());
     let mut i = left;
     let mut L = lim;
     let mut s = ~"[";
@@ -457,9 +457,9 @@ pub impl Printer {
             }
         }
     }
-    fn print_str(&mut self, s: ~str) {
+    fn print_str(&mut self, s: &str) {
         while self.pending_indentation > 0 {
-            (*self.out).write_str(~" ");
+            (*self.out).write_str(" ");
             self.pending_indentation -= 1;
         }
         (*self.out).write_str(s);
@@ -562,16 +562,16 @@ pub fn end(p: @mut Printer) { p.pretty_print(END); }
 
 pub fn eof(p: @mut Printer) { p.pretty_print(EOF); }
 
-pub fn word(p: @mut Printer, wrd: ~str) {
-    p.pretty_print(STRING(@/*bad*/ copy wrd, wrd.len() as int));
+pub fn word(p: @mut Printer, wrd: &str) {
+    p.pretty_print(STRING(@/*bad*/ wrd.to_owned(), wrd.len() as int));
 }
 
-pub fn huge_word(p: @mut Printer, wrd: ~str) {
-    p.pretty_print(STRING(@/*bad*/ copy wrd, size_infinity));
+pub fn huge_word(p: @mut Printer, wrd: &str) {
+    p.pretty_print(STRING(@/*bad*/ wrd.to_owned(), size_infinity));
 }
 
-pub fn zero_word(p: @mut Printer, wrd: ~str) {
-    p.pretty_print(STRING(@/*bad*/ copy wrd, 0));
+pub fn zero_word(p: @mut Printer, wrd: &str) {
+    p.pretty_print(STRING(@/*bad*/ wrd.to_owned(), 0));
 }
 
 pub fn spaces(p: @mut Printer, n: uint) { break_offset(p, n, 0); }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 9d2927eb74f..ea1682978a4 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -156,7 +156,7 @@ pub fn lifetime_to_str(e: &ast::Lifetime, intr: @ident_interner) -> ~str {
 }
 
 pub fn tt_to_str(tt: ast::token_tree, intr: @ident_interner) -> ~str {
-    to_str(tt, print_tt, intr)
+    to_str(&tt, print_tt, intr)
 }
 
 pub fn tts_to_str(tts: &[ast::token_tree], intr: @ident_interner) -> ~str {
@@ -181,12 +181,12 @@ pub fn path_to_str(p: @ast::Path, intr: @ident_interner) -> ~str {
 }
 
 pub fn fun_to_str(decl: &ast::fn_decl, purity: ast::purity, name: ast::ident,
-                  opt_self_ty: Option<ast::self_ty_>,
+                  opt_explicit_self: Option<ast::explicit_self_>,
                   generics: &ast::Generics, intr: @ident_interner) -> ~str {
     do io::with_str_writer |wr| {
         let s = rust_printer(wr, intr);
         print_fn(s, decl, Some(purity), AbiSet::Rust(),
-                 name, generics, opt_self_ty, ast::inherited);
+                 name, generics, opt_explicit_self, ast::inherited);
         end(s); // Close the head box
         end(s); // Close the outer box
         eof(s.s);
@@ -213,7 +213,7 @@ pub fn attribute_to_str(attr: ast::attribute, intr: @ident_interner) -> ~str {
     to_str(attr, print_attribute, intr)
 }
 
-pub fn variant_to_str(var: ast::variant, intr: @ident_interner) -> ~str {
+pub fn variant_to_str(var: &ast::variant, intr: @ident_interner) -> ~str {
     to_str(var, print_variant, intr)
 }
 
@@ -229,9 +229,9 @@ pub fn box(s: @ps, u: uint, b: pp::breaks) {
 
 pub fn nbsp(s: @ps) { word(s.s, ~" "); }
 
-pub fn word_nbsp(s: @ps, w: ~str) { word(s.s, w); nbsp(s); }
+pub fn word_nbsp(s: @ps, w: &str) { word(s.s, w); nbsp(s); }
 
-pub fn word_space(s: @ps, w: ~str) { word(s.s, w); space(s.s); }
+pub fn word_space(s: @ps, w: &str) { word(s.s, w); space(s.s); }
 
 pub fn popen(s: @ps) { word(s.s, ~"("); }
 
@@ -346,7 +346,7 @@ pub fn commasep_exprs(s: @ps, b: breaks, exprs: &[@ast::expr]) {
     commasep_cmnt(s, b, exprs, print_expr, expr_span);
 }
 
-pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: ~[ast::attribute]) {
+pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: &[ast::attribute]) {
     print_inner_attributes(s, attrs);
     for _mod.view_items.each |vitem| {
         print_view_item(s, *vitem);
@@ -355,7 +355,7 @@ pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: ~[ast::attribute]) {
 }
 
 pub fn print_foreign_mod(s: @ps, nmod: &ast::foreign_mod,
-                         attrs: ~[ast::attribute]) {
+                         attrs: &[ast::attribute]) {
     print_inner_attributes(s, attrs);
     for nmod.view_items.each |vitem| {
         print_view_item(s, *vitem);
@@ -430,10 +430,10 @@ pub fn print_type(s: @ps, ty: @ast::Ty) {
         word(s.s, ~"]");
       }
       ast::ty_mac(_) => {
-          fail!(~"print_type doesn't know how to print a ty_mac");
+          fail!("print_type doesn't know how to print a ty_mac");
       }
       ast::ty_infer => {
-          fail!(~"print_type shouldn't see a ty_infer");
+          fail!("print_type shouldn't see a ty_infer");
       }
 
     }
@@ -539,7 +539,7 @@ pub fn print_item(s: @ps, item: @ast::item) {
       ast::item_enum(ref enum_definition, ref params) => {
         print_enum_def(
             s,
-            *enum_definition,
+            enum_definition,
             params,
             item.ident,
             item.span,
@@ -621,7 +621,7 @@ fn print_trait_ref(s: @ps, t: &ast::trait_ref) {
     print_path(s, t.path, false);
 }
 
-pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
+pub fn print_enum_def(s: @ps, enum_definition: &ast::enum_def,
                       generics: &ast::Generics, ident: ast::ident,
                       span: codemap::span, visibility: ast::visibility) {
     head(s, visibility_qualified(visibility, ~"enum"));
@@ -632,7 +632,7 @@ pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
 }
 
 pub fn print_variants(s: @ps,
-                      variants: ~[ast::variant],
+                      variants: &[ast::variant],
                       span: codemap::span) {
     bopen(s);
     for variants.each |v| {
@@ -640,7 +640,7 @@ pub fn print_variants(s: @ps,
         maybe_print_comment(s, v.span.lo);
         print_outer_attributes(s, v.node.attrs);
         ibox(s, indent_unit);
-        print_variant(s, *v);
+        print_variant(s, v);
         word(s.s, ~",");
         end(s);
         maybe_print_trailing_comment(s, v.span, None);
@@ -683,7 +683,7 @@ pub fn print_struct(s: @ps,
             popen(s);
             do commasep(s, inconsistent, struct_def.fields) |s, field| {
                 match field.node.kind {
-                    ast::named_field(*) => fail!(~"unexpected named field"),
+                    ast::named_field(*) => fail!("unexpected named field"),
                     ast::unnamed_field => {
                         maybe_print_comment(s, field.span.lo);
                         print_type(s, field.node.ty);
@@ -702,7 +702,7 @@ pub fn print_struct(s: @ps,
 
         for struct_def.fields.each |field| {
             match field.node.kind {
-                ast::unnamed_field => fail!(~"unexpected unnamed field"),
+                ast::unnamed_field => fail!("unexpected unnamed field"),
                 ast::named_field(ident, visibility) => {
                     hardbreak_if_not_bol(s);
                     maybe_print_comment(s, field.span.lo);
@@ -727,15 +727,15 @@ pub fn print_struct(s: @ps,
 /// appropriate macro, transcribe back into the grammar we just parsed from,
 /// and then pretty-print the resulting AST nodes (so, e.g., we print
 /// expression arguments as expressions). It can be done! I think.
-pub fn print_tt(s: @ps, tt: ast::token_tree) {
-    match tt {
+pub fn print_tt(s: @ps, tt: &ast::token_tree) {
+    match *tt {
       ast::tt_delim(ref tts) => print_tts(s, *tts),
       ast::tt_tok(_, ref tk) => {
           word(s.s, parse::token::to_str(s.intr, tk));
       }
       ast::tt_seq(_, ref tts, ref sep, zerok) => {
         word(s.s, ~"$(");
-        for (*tts).each() |tt_elt| { print_tt(s, *tt_elt); }
+        for (*tts).each() |tt_elt| { print_tt(s, tt_elt); }
         word(s.s, ~")");
         match (*sep) {
           Some(ref tk) => word(s.s, parse::token::to_str(s.intr, tk)),
@@ -756,12 +756,12 @@ pub fn print_tts(s: @ps, tts: &[ast::token_tree]) {
         if i != 0 {
             space(s.s);
         }
-        print_tt(s, *tt);
+        print_tt(s, tt);
     }
     end(s);
 }
 
-pub fn print_variant(s: @ps, v: ast::variant) {
+pub fn print_variant(s: @ps, v: &ast::variant) {
     print_visibility(s, v.node.vis);
     match v.node.kind {
         ast::tuple_variant_kind(ref args) => {
@@ -797,7 +797,7 @@ pub fn print_ty_method(s: @ps, m: &ast::ty_method) {
     print_outer_attributes(s, m.attrs);
     print_ty_fn(s, None, None, None, m.purity, ast::Many,
                 &m.decl, Some(m.ident), Some(&m.generics),
-                Some(/*bad*/ copy m.self_ty.node));
+                Some(/*bad*/ copy m.explicit_self.node));
     word(s.s, ~";");
 }
 
@@ -813,13 +813,13 @@ pub fn print_method(s: @ps, meth: @ast::method) {
     maybe_print_comment(s, meth.span.lo);
     print_outer_attributes(s, meth.attrs);
     print_fn(s, &meth.decl, Some(meth.purity), AbiSet::Rust(),
-             meth.ident, &meth.generics, Some(meth.self_ty.node),
+             meth.ident, &meth.generics, Some(meth.explicit_self.node),
              meth.vis);
     word(s.s, ~" ");
     print_block_with_attrs(s, &meth.body, meth.attrs);
 }
 
-pub fn print_outer_attributes(s: @ps, attrs: ~[ast::attribute]) {
+pub fn print_outer_attributes(s: @ps, attrs: &[ast::attribute]) {
     let mut count = 0;
     for attrs.each |attr| {
         match attr.node.style {
@@ -830,7 +830,7 @@ pub fn print_outer_attributes(s: @ps, attrs: ~[ast::attribute]) {
     if count > 0 { hardbreak_if_not_bol(s); }
 }
 
-pub fn print_inner_attributes(s: @ps, attrs: ~[ast::attribute]) {
+pub fn print_inner_attributes(s: @ps, attrs: &[ast::attribute]) {
     let mut count = 0;
     for attrs.each |attr| {
         match attr.node.style {
@@ -879,7 +879,7 @@ pub fn print_stmt(s: @ps, st: &ast::stmt) {
       }
       ast::stmt_mac(ref mac, semi) => {
         space_if_not_bol(s);
-        print_mac(s, (*mac));
+        print_mac(s, mac);
         if semi { word(s.s, ~";"); }
       }
     }
@@ -892,18 +892,18 @@ pub fn print_block(s: @ps, blk: &ast::blk) {
 }
 
 pub fn print_block_unclosed(s: @ps, blk: &ast::blk) {
-    print_possibly_embedded_block_(s, blk, block_normal, indent_unit, ~[],
+    print_possibly_embedded_block_(s, blk, block_normal, indent_unit, &[],
                                  false);
 }
 
 pub fn print_block_unclosed_indent(s: @ps, blk: &ast::blk, indented: uint) {
-    print_possibly_embedded_block_(s, blk, block_normal, indented, ~[],
+    print_possibly_embedded_block_(s, blk, block_normal, indented, &[],
                                    false);
 }
 
 pub fn print_block_with_attrs(s: @ps,
                               blk: &ast::blk,
-                              attrs: ~[ast::attribute]) {
+                              attrs: &[ast::attribute]) {
     print_possibly_embedded_block_(s, blk, block_normal, indent_unit, attrs,
                                   true);
 }
@@ -915,14 +915,14 @@ pub fn print_possibly_embedded_block(s: @ps,
                                      embedded: embed_type,
                                      indented: uint) {
     print_possibly_embedded_block_(
-        s, blk, embedded, indented, ~[], true);
+        s, blk, embedded, indented, &[], true);
 }
 
 pub fn print_possibly_embedded_block_(s: @ps,
                                       blk: &ast::blk,
                                       embedded: embed_type,
                                       indented: uint,
-                                      attrs: ~[ast::attribute],
+                                      attrs: &[ast::attribute],
                                       close_box: bool) {
     match blk.node.rules {
       ast::unsafe_blk => word_space(s, ~"unsafe"),
@@ -984,7 +984,7 @@ pub fn print_if(s: @ps, test: @ast::expr, blk: &ast::blk,
               }
               // BLEAH, constraints would be great here
               _ => {
-                  fail!(~"print_if saw if with weird alternative");
+                  fail!("print_if saw if with weird alternative");
               }
             }
           }
@@ -994,7 +994,7 @@ pub fn print_if(s: @ps, test: @ast::expr, blk: &ast::blk,
     do_else(s, elseopt);
 }
 
-pub fn print_mac(s: @ps, m: ast::mac) {
+pub fn print_mac(s: @ps, m: &ast::mac) {
     match m.node {
       ast::mac_invoc_tt(pth, ref tts) => {
         print_path(s, pth, false);
@@ -1352,6 +1352,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
         word(s.s, ~"]");
       }
       ast::expr_path(path) => print_path(s, path, true),
+      ast::expr_self => word(s.s, ~"self"),
       ast::expr_break(opt_ident) => {
         word(s.s, ~"break");
         space(s.s);
@@ -1386,7 +1387,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
         print_expr(s, expr);
         pclose(s);
       }
-      ast::expr_inline_asm(a) => {
+      ast::expr_inline_asm(ref a) => {
         if a.volatile {
             word(s.s, ~"__volatile__ asm!");
         } else {
@@ -1414,7 +1415,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) {
         print_string(s, *a.clobbers);
         pclose(s);
       }
-      ast::expr_mac(ref m) => print_mac(s, (*m)),
+      ast::expr_mac(ref m) => print_mac(s, m),
       ast::expr_paren(e) => {
           popen(s);
           print_expr(s, e);
@@ -1558,7 +1559,7 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) {
           }
         }
       }
-      ast::pat_struct(path, fields, etc) => {
+      ast::pat_struct(path, ref fields, etc) => {
         print_path(s, path, true);
         word(s.s, ~"{");
         fn print_field(s: @ps, f: ast::field_pat, refutable: bool) {
@@ -1569,18 +1570,18 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) {
             end(s);
         }
         fn get_span(f: ast::field_pat) -> codemap::span { return f.pat.span; }
-        commasep_cmnt(s, consistent, fields,
+        commasep_cmnt(s, consistent, *fields,
                       |s, f| print_field(s,f,refutable),
                       get_span);
         if etc {
-            if vec::len(fields) != 0u { word_space(s, ~","); }
+            if fields.len() != 0u { word_space(s, ~","); }
             word(s.s, ~"_");
         }
         word(s.s, ~"}");
       }
-      ast::pat_tup(elts) => {
+      ast::pat_tup(ref elts) => {
         popen(s);
-        commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
+        commasep(s, inconsistent, *elts, |s, p| print_pat(s, p, refutable));
         if elts.len() == 1 {
             word(s.s, ~",");
         }
@@ -1605,9 +1606,9 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) {
         word(s.s, ~"..");
         print_expr(s, end);
       }
-      ast::pat_vec(before, slice, after) => {
+      ast::pat_vec(ref before, slice, ref after) => {
         word(s.s, ~"[");
-        do commasep(s, inconsistent, before) |s, p| {
+        do commasep(s, inconsistent, *before) |s, p| {
             print_pat(s, p, refutable);
         }
         for slice.each |&p| {
@@ -1616,7 +1617,7 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) {
             print_pat(s, p, refutable);
             if !after.is_empty() { word_space(s, ~","); }
         }
-        do commasep(s, inconsistent, after) |s, p| {
+        do commasep(s, inconsistent, *after) |s, p| {
             print_pat(s, p, refutable);
         }
         word(s.s, ~"]");
@@ -1625,13 +1626,13 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) {
     (s.ann.post)(ann_node);
 }
 
-pub fn self_ty_to_str(self_ty: ast::self_ty_, intr: @ident_interner) -> ~str {
-    to_str(self_ty, |a, b| { print_self_ty(a, b); () }, intr)
+pub fn explicit_self_to_str(explicit_self: ast::explicit_self_, intr: @ident_interner) -> ~str {
+    to_str(explicit_self, |a, b| { print_explicit_self(a, b); () }, intr)
 }
 
 // Returns whether it printed anything
-pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool {
-    match self_ty {
+pub fn print_explicit_self(s: @ps, explicit_self: ast::explicit_self_) -> bool {
+    match explicit_self {
         ast::sty_static => { return false; }
         ast::sty_value => { word(s.s, ~"self"); }
         ast::sty_region(lt, m) => {
@@ -1656,24 +1657,24 @@ pub fn print_fn(s: @ps,
                 abis: AbiSet,
                 name: ast::ident,
                 generics: &ast::Generics,
-                opt_self_ty: Option<ast::self_ty_>,
+                opt_explicit_self: Option<ast::explicit_self_>,
                 vis: ast::visibility) {
     head(s, ~"");
-    print_fn_header_info(s, opt_self_ty, purity, abis, ast::Many, None, vis);
+    print_fn_header_info(s, opt_explicit_self, purity, abis, ast::Many, None, vis);
     nbsp(s);
     print_ident(s, name);
     print_generics(s, generics);
-    print_fn_args_and_ret(s, decl, opt_self_ty);
+    print_fn_args_and_ret(s, decl, opt_explicit_self);
 }
 
 pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
-                 opt_self_ty: Option<ast::self_ty_>) {
+                 opt_explicit_self: Option<ast::explicit_self_>) {
     // It is unfortunate to duplicate the commasep logic, but we we want the
     // self type and the args all in the same box.
     box(s, 0u, inconsistent);
     let mut first = true;
-    for opt_self_ty.each |self_ty| {
-        first = !print_self_ty(s, *self_ty);
+    for opt_explicit_self.each |explicit_self| {
+        first = !print_explicit_self(s, *explicit_self);
     }
 
     for decl.inputs.each |arg| {
@@ -1685,9 +1686,9 @@ pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
 }
 
 pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl,
-                             opt_self_ty: Option<ast::self_ty_>) {
+                             opt_explicit_self: Option<ast::explicit_self_>) {
     popen(s);
-    print_fn_args(s, decl, opt_self_ty);
+    print_fn_args(s, decl, opt_explicit_self);
     pclose(s);
 
     maybe_print_comment(s, decl.output.span.lo);
@@ -1797,7 +1798,7 @@ pub fn print_meta_item(s: @ps, item: @ast::meta_item) {
 pub fn print_view_path(s: @ps, vp: @ast::view_path) {
     match vp.node {
       ast::view_path_simple(ident, path, _) => {
-        if path.idents[vec::len(path.idents)-1u] != ident {
+        if path.idents[path.idents.len()-1u] != ident {
             print_ident(s, ident);
             space(s.s);
             word_space(s, ~"=");
@@ -1831,12 +1832,12 @@ pub fn print_view_item(s: @ps, item: @ast::view_item) {
     print_outer_attributes(s, item.attrs);
     print_visibility(s, item.vis);
     match item.node {
-        ast::view_item_extern_mod(id, mta, _) => {
+        ast::view_item_extern_mod(id, ref mta, _) => {
             head(s, ~"extern mod");
             print_ident(s, id);
             if !mta.is_empty() {
                 popen(s);
-                commasep(s, consistent, mta, print_meta_item);
+                commasep(s, consistent, *mta, print_meta_item);
                 pclose(s);
             }
         }
@@ -1899,7 +1900,7 @@ pub fn print_ty_fn(s: @ps,
                    decl: &ast::fn_decl,
                    id: Option<ast::ident>,
                    generics: Option<&ast::Generics>,
-                   opt_self_ty: Option<ast::self_ty_>) {
+                   opt_explicit_self: Option<ast::explicit_self_>) {
     ibox(s, indent_unit);
 
     // Duplicates the logic in `print_fn_header_info()`.  This is because that
@@ -1919,8 +1920,8 @@ pub fn print_ty_fn(s: @ps,
     // self type and the args all in the same box.
     box(s, 0u, inconsistent);
     let mut first = true;
-    for opt_self_ty.each |self_ty| {
-        first = !print_self_ty(s, *self_ty);
+    for opt_explicit_self.each |explicit_self| {
+        first = !print_explicit_self(s, *explicit_self);
     }
     for decl.inputs.each |arg| {
         if first { first = false; } else { word_space(s, ~","); }
@@ -1959,7 +1960,7 @@ pub fn maybe_print_trailing_comment(s: @ps, span: codemap::span,
         match next_pos { None => (), Some(p) => next = p }
         if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
                span_line.line == comment_line.line {
-            print_comment(s, (*cmnt));
+            print_comment(s, cmnt);
             s.cur_cmnt_and_lit.cur_cmnt += 1u;
         }
       }
@@ -1974,7 +1975,7 @@ pub fn print_remaining_comments(s: @ps) {
     loop {
         match next_comment(s) {
           Some(ref cmnt) => {
-            print_comment(s, (*cmnt));
+            print_comment(s, cmnt);
             s.cur_cmnt_and_lit.cur_cmnt += 1u;
           }
           _ => break
@@ -2054,7 +2055,7 @@ pub fn maybe_print_comment(s: @ps, pos: BytePos) {
         match next_comment(s) {
           Some(ref cmnt) => {
             if (*cmnt).pos < pos {
-                print_comment(s, (*cmnt));
+                print_comment(s, cmnt);
                 s.cur_cmnt_and_lit.cur_cmnt += 1u;
             } else { break; }
           }
@@ -2063,10 +2064,10 @@ pub fn maybe_print_comment(s: @ps, pos: BytePos) {
     }
 }
 
-pub fn print_comment(s: @ps, cmnt: comments::cmnt) {
+pub fn print_comment(s: @ps, cmnt: &comments::cmnt) {
     match cmnt.style {
       comments::mixed => {
-        assert!((vec::len(cmnt.lines) == 1u));
+        assert!(cmnt.lines.len() == 1u);
         zerobreak(s.s);
         word(s.s, cmnt.lines[0]);
         zerobreak(s.s);
@@ -2082,7 +2083,7 @@ pub fn print_comment(s: @ps, cmnt: comments::cmnt) {
       }
       comments::trailing => {
         word(s.s, ~" ");
-        if vec::len(cmnt.lines) == 1u {
+        if cmnt.lines.len() == 1u {
             word(s.s, cmnt.lines[0]);
             hardbreak(s.s);
         } else {
@@ -2162,7 +2163,7 @@ pub fn print_opt_sigil(s: @ps, opt_sigil: Option<ast::Sigil>) {
 }
 
 pub fn print_fn_header_info(s: @ps,
-                            _opt_sty: Option<ast::self_ty_>,
+                            _opt_explicit_self: Option<ast::explicit_self_>,
                             opt_purity: Option<ast::purity>,
                             abis: AbiSet,
                             onceness: ast::Onceness,
@@ -2236,7 +2237,7 @@ mod test {
 
     fn string_check<T:Eq> (given : &T, expected: &T) {
         if !(given == expected) {
-            fail!(fmt!("given %?, expected %?",given,expected));
+            fail!("given %?, expected %?", given, expected);
         }
     }
 
@@ -2273,7 +2274,7 @@ mod test {
             vis: ast::public,
         });
 
-        let varstr = variant_to_str(var,mock_interner);
+        let varstr = variant_to_str(&var,mock_interner);
         assert_eq!(&varstr,&~"pub principal_skinner");
     }
 }
diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc
index b8327de0f13..565a8a18c6f 100644
--- a/src/libsyntax/syntax.rc
+++ b/src/libsyntax/syntax.rc
@@ -20,7 +20,6 @@
 #[license = "MIT/ASL2"];
 #[crate_type = "lib"];
 
-#[allow(vecs_implicitly_copyable)];
 #[allow(non_camel_case_types)];
 #[deny(deprecated_pattern)];
 
@@ -79,6 +78,7 @@ pub mod ext {
 
     pub mod fmt;
     pub mod env;
+    pub mod bytes;
     pub mod concat_idents;
     pub mod log_syntax;
     pub mod auto_encode;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index dcc94c92a88..4cfd54256f8 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -179,7 +179,7 @@ pub fn visit_item<E: Copy>(i: @item, e: E, v: vt<E>) {
         item_enum(ref enum_definition, ref tps) => {
             (v.visit_generics)(tps, e, v);
             visit_enum_def(
-                *enum_definition,
+                enum_definition,
                 tps,
                 e,
                 v
@@ -206,11 +206,11 @@ pub fn visit_item<E: Copy>(i: @item, e: E, v: vt<E>) {
                 (v.visit_trait_method)(m, e, v);
             }
         }
-        item_mac(ref m) => visit_mac((*m), e, v)
+        item_mac(ref m) => visit_mac(m, e, v)
     }
 }
 
-pub fn visit_enum_def<E: Copy>(enum_definition: ast::enum_def,
+pub fn visit_enum_def<E: Copy>(enum_definition: &ast::enum_def,
                                tps: &Generics,
                                e: E,
                                v: vt<E>) {
@@ -422,7 +422,7 @@ pub fn visit_stmt<E>(s: @stmt, e: E, v: vt<E>) {
       stmt_decl(d, _) => (v.visit_decl)(d, e, v),
       stmt_expr(ex, _) => (v.visit_expr)(ex, e, v),
       stmt_semi(ex, _) => (v.visit_expr)(ex, e, v),
-      stmt_mac(ref mac, _) => visit_mac((*mac), e, v)
+      stmt_mac(ref mac, _) => visit_mac(mac, e, v)
     }
 }
 
@@ -445,7 +445,7 @@ pub fn visit_exprs<E: Copy>(exprs: &[@expr], e: E, v: vt<E>) {
     for exprs.each |ex| { (v.visit_expr)(*ex, e, v); }
 }
 
-pub fn visit_mac<E>(_m: mac, _e: E, _v: vt<E>) {
+pub fn visit_mac<E>(_m: &mac, _e: E, _v: vt<E>) {
     /* no user-serviceable parts inside */
 }
 
@@ -529,6 +529,7 @@ pub fn visit_expr<E: Copy>(ex: @expr, e: E, v: vt<E>) {
             (v.visit_expr)(b, e, v);
         }
         expr_path(p) => visit_path(p, e, v),
+        expr_self => (),
         expr_break(_) => (),
         expr_again(_) => (),
         expr_ret(eo) => visit_expr_opt(eo, e, v),
@@ -536,7 +537,7 @@ pub fn visit_expr<E: Copy>(ex: @expr, e: E, v: vt<E>) {
             (v.visit_expr)(lv, e, v);
             (v.visit_expr)(x, e, v);
         }
-        expr_mac(ref mac) => visit_mac((*mac), e, v),
+        expr_mac(ref mac) => visit_mac(mac, e, v),
         expr_paren(x) => (v.visit_expr)(x, e, v),
         expr_inline_asm(ref a) => {
             for a.inputs.each |&(_, in)| {
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 8c081858d60..9e44abe081c 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -553,7 +553,7 @@ extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
     li->setVolatile(true);
     li->setAtomic(order);
     li->setAlignment(sizeof(intptr_t));
-    return wrap(unwrap(B)->Insert(li));
+    return wrap(unwrap(B)->Insert(li, Name));
 }
 
 extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
diff --git a/src/test/auxiliary/cci_iter_lib.rs b/src/test/auxiliary/cci_iter_lib.rs
index e44267373ef..a264c7d238f 100644
--- a/src/test/auxiliary/cci_iter_lib.rs
+++ b/src/test/auxiliary/cci_iter_lib.rs
@@ -13,7 +13,7 @@
 #[inline]
 pub fn iter<T>(v: &[T], f: &fn(&T)) {
     let mut i = 0u;
-    let n = vec::len(v);
+    let n = v.len();
     while i < n {
         f(&v[i]);
         i += 1u;
diff --git a/src/test/auxiliary/cci_no_inline_lib.rs b/src/test/auxiliary/cci_no_inline_lib.rs
index f79227d87cd..fbdb7806b5e 100644
--- a/src/test/auxiliary/cci_no_inline_lib.rs
+++ b/src/test/auxiliary/cci_no_inline_lib.rs
@@ -13,7 +13,7 @@
 // same as cci_iter_lib, more-or-less, but not marked inline
 pub fn iter(v: ~[uint], f: &fn(uint)) {
     let mut i = 0u;
-    let n = vec::len(v);
+    let n = v.len();
     while i < n {
         f(v[i]);
         i += 1u;
diff --git a/src/test/auxiliary/static-methods-crate.rs b/src/test/auxiliary/static-methods-crate.rs
index 74c46a8b8c6..2ecd318db3c 100644
--- a/src/test/auxiliary/static-methods-crate.rs
+++ b/src/test/auxiliary/static-methods-crate.rs
@@ -36,6 +36,6 @@ impl read for bool {
 pub fn read<T:read + Copy>(s: ~str) -> T {
     match read::readMaybe(s) {
       Some(x) => x,
-      _ => fail!(~"read failed!")
+      _ => fail!("read failed!")
     }
 }
diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs
index fb276723543..ddf6f4bfc55 100644
--- a/src/test/bench/graph500-bfs.rs
+++ b/src/test/bench/graph500-bfs.rs
@@ -126,7 +126,7 @@ fn gen_search_keys(graph: &[~[node_id]], n: uint) -> ~[node_id] {
  */
 fn bfs(graph: graph, key: node_id) -> bfs_result {
     let mut marks : ~[node_id]
-        = vec::from_elem(vec::len(graph), -1i64);
+        = vec::from_elem(graph.len(), -1i64);
 
     let mut q = Deque::new();
 
@@ -217,7 +217,7 @@ fn bfs2(graph: graph, key: node_id) -> bfs_result {
         match *c {
           white => { -1i64 }
           black(parent) => { parent }
-          _ => { fail!(~"Found remaining gray nodes in BFS") }
+          _ => { fail!("Found remaining gray nodes in BFS") }
         }
     }
 }
@@ -305,7 +305,7 @@ fn pbfs(graph: &arc::ARC<graph>, key: node_id) -> bfs_result {
             match *c {
                 white => { -1i64 }
                 black(parent) => { parent }
-                _ => { fail!(~"Found remaining gray nodes in BFS") }
+                _ => { fail!("Found remaining gray nodes in BFS") }
             }
         };
         result
@@ -429,7 +429,7 @@ fn main() {
     let stop = time::precise_time_s();
 
     io::stdout().write_line(fmt!("Generated %? edges in %? seconds.",
-                                 vec::len(edges), stop - start));
+                                 edges.len(), stop - start));
 
     let start = time::precise_time_s();
     let graph = make_graph(1 << scale, copy edges);
diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs
index 5d893d4ec07..03d45252432 100644
--- a/src/test/bench/shootout-chameneos-redux.rs
+++ b/src/test/bench/shootout-chameneos-redux.rs
@@ -61,7 +61,7 @@ fn show_digit(nn: uint) -> ~str {
         7 => {~"seven"}
         8 => {~"eight"}
         9 => {~"nine"}
-        _ => {fail!(~"expected digits from 0 to 9...")}
+        _ => {fail!("expected digits from 0 to 9...")}
     }
 }
 
diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs
index 210bf5cb6de..3c32ec338b7 100644
--- a/src/test/bench/shootout-k-nucleotide-pipes.rs
+++ b/src/test/bench/shootout-k-nucleotide-pipes.rs
@@ -95,7 +95,7 @@ fn windows_with_carry(bb: &[u8], nn: uint,
                       it: &fn(window: &[u8])) -> ~[u8] {
    let mut ii = 0u;
 
-   let len = vec::len(bb);
+   let len = bb.len();
    while ii < len - (nn - 1u) {
       it(vec::slice(bb, ii, ii+nn));
       ii += 1u;
@@ -184,10 +184,10 @@ fn main() {
 
       if str::len(line) == 0u { loop; }
 
-      match (line[0], proc_mode) {
+      match (line[0] as char, proc_mode) {
 
          // start processing if this is the one
-         ('>' as u8, false) => {
+         ('>', false) => {
             match str::find_str_from(line, ~"THREE", 1u) {
                option::Some(_) => { proc_mode = true; }
                option::None    => { }
@@ -195,7 +195,7 @@ fn main() {
          }
 
          // break our processing
-         ('>' as u8, true) => { break; }
+         ('>', true) => { break; }
 
          // process the sequence for k-mers
          (_, true) => {
diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs
index 8afddd3a31e..c18c1eaedd6 100644
--- a/src/test/bench/sudoku.rs
+++ b/src/test/bench/sudoku.rs
@@ -70,13 +70,13 @@ pub impl Sudoku {
             let line = reader.read_line();
             let mut comps = ~[];
             for str::each_split_char(line.trim(), ',') |s| { comps.push(s.to_owned()) }
-            if vec::len(comps) == 3u {
+            if comps.len() == 3u {
                 let row     = uint::from_str(comps[0]).get() as u8;
                 let col     = uint::from_str(comps[1]).get() as u8;
                 g[row][col] = uint::from_str(comps[2]).get() as u8;
             }
             else {
-                fail!(~"Invalid sudoku file");
+                fail!("Invalid sudoku file");
             }
         }
         return Sudoku::new(g)
@@ -103,7 +103,7 @@ pub impl Sudoku {
         }
 
         let mut ptr = 0u;
-        let end = vec::len(work);
+        let end = work.len();
         while (ptr < end) {
             let (row, col) = work[ptr];
             // is there another color to try?
@@ -112,7 +112,7 @@ pub impl Sudoku {
                 ptr = ptr + 1u;
             } else {
                 // no: redo this field aft recoloring pred; unless there is none
-                if ptr == 0u { fail!(~"No solution found for this sudoku"); }
+                if ptr == 0u { fail!("No solution found for this sudoku"); }
                 ptr = ptr - 1u;
             }
         }
@@ -265,7 +265,7 @@ fn check_default_sudoku_solution() {
 
 fn main() {
     let args        = os::args();
-    let use_default = vec::len(args) == 1u;
+    let use_default = args.len() == 1u;
     let mut sudoku = if use_default {
         Sudoku::from_vec(&default_sudoku)
     } else {
diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs
index 17b7d1d2948..a6eaf892310 100644
--- a/src/test/bench/task-perf-jargon-metal-smoke.rs
+++ b/src/test/bench/task-perf-jargon-metal-smoke.rs
@@ -50,6 +50,6 @@ fn main() {
     let (p,c) = comm::stream();
     child_generation(uint::from_str(args[1]).get(), c);
     if p.try_recv().is_none() {
-        fail!(~"it happened when we slumbered");
+        fail!("it happened when we slumbered");
     }
 }
diff --git a/src/test/compile-fail/borrowck-rvalues-mutable-bad.rs b/src/test/compile-fail/borrowck-rvalues-mutable-bad.rs
new file mode 100644
index 00000000000..10bef907a28
--- /dev/null
+++ b/src/test/compile-fail/borrowck-rvalues-mutable-bad.rs
@@ -0,0 +1,38 @@
+// 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 rvalue lifetimes is limited to the enclosing trans
+// cleanup scope. It is unclear that this is the correct lifetime for
+// rvalues, but that's what it is right now.
+
+struct Counter {
+    value: uint
+}
+
+impl Counter {
+    fn new(v: uint) -> Counter {
+        Counter {value: v}
+    }
+
+    fn inc<'a>(&'a mut self) -> &'a mut Counter {
+        self.value += 1;
+        self
+    }
+
+    fn get(&self) -> uint {
+        self.value
+    }
+}
+
+pub fn main() {
+    let v = Counter::new(22).inc().inc().get();
+    //~^ ERROR borrowed value does not live long enough
+    assert_eq!(v, 24);;
+}
diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
index 0c21b64bb0f..7f98eba5996 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
@@ -2,7 +2,7 @@ fn a() -> &[int] {
     let vec = [1, 2, 3, 4];
     let tail = match vec {
         [_, ..tail] => tail, //~ ERROR does not live long enough
-        _ => fail!(~"a")
+        _ => fail!("a")
     };
     tail
 }
@@ -11,7 +11,7 @@ fn b() -> &[int] {
     let vec = [1, 2, 3, 4];
     let init = match vec {
         [..init, _] => init, //~ ERROR does not live long enough
-        _ => fail!(~"b")
+        _ => fail!("b")
     };
     init
 }
@@ -20,7 +20,7 @@ fn c() -> &[int] {
     let vec = [1, 2, 3, 4];
     let slice = match vec {
         [_, ..slice, _] => slice, //~ ERROR does not live long enough
-        _ => fail!(~"c")
+        _ => fail!("c")
     };
     slice
 }
diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
index 941455d086c..81f052918ed 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
@@ -4,7 +4,7 @@ fn a() {
         [~ref _a] => {
             vec[0] = ~4; //~ ERROR cannot assign to `vec[]` because it is borrowed
         }
-        _ => fail!(~"foo")
+        _ => fail!("foo")
     }
 }
 
diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
index dbdd8f0809a..6f669e67ec7 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
@@ -2,7 +2,7 @@ fn a() -> &int {
     let vec = [1, 2, 3, 4];
     let tail = match vec {
         [_a, ..tail] => &tail[0], //~ ERROR borrowed value does not live long enough
-        _ => fail!(~"foo")
+        _ => fail!("foo")
     };
     tail
 }
diff --git a/src/test/compile-fail/closure-bounds-not-builtin.rs b/src/test/compile-fail/closure-bounds-not-builtin.rs
new file mode 100644
index 00000000000..a3484cb33dc
--- /dev/null
+++ b/src/test/compile-fail/closure-bounds-not-builtin.rs
@@ -0,0 +1,8 @@
+
+trait Foo {}
+
+fn take(f: &fn:Foo()) {
+    //~^ ERROR only the builtin traits can be used as closure or object bounds
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/closure-bounds-subtype.rs b/src/test/compile-fail/closure-bounds-subtype.rs
new file mode 100644
index 00000000000..ebec113cedc
--- /dev/null
+++ b/src/test/compile-fail/closure-bounds-subtype.rs
@@ -0,0 +1,34 @@
+fn take_any(_: &fn()) {
+}
+
+fn take_copyable(_: &fn:Copy()) {
+}
+
+fn take_copyable_owned(_: &fn:Copy+Owned()) {
+}
+
+fn give_any(f: &fn()) {
+    take_any(f);
+    take_copyable(f); //~ ERROR expected bounds `Copy` but found no bounds
+    take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found no bounds
+}
+
+fn give_copyable(f: &fn:Copy()) {
+    take_any(f);
+    take_copyable(f);
+    take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found bounds `Copy`
+}
+
+fn give_owned(f: &fn:Owned()) {
+    take_any(f);
+    take_copyable(f); //~ ERROR expected bounds `Copy` but found bounds `Owned`
+    take_copyable_owned(f); //~ ERROR expected bounds `Copy+Owned` but found bounds `Owned`
+}
+
+fn give_copyable_owned(f: &fn:Copy+Owned()) {
+    take_any(f);
+    take_copyable(f);
+    take_copyable_owned(f);
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/deriving-obsolete.rs b/src/test/compile-fail/deprecated-auto-code.rs
index 298dced1e21..1f7cbfe9807 100644
--- a/src/test/compile-fail/deriving-obsolete.rs
+++ b/src/test/compile-fail/deprecated-auto-code.rs
@@ -8,10 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[deriving_clone] //~ ERROR `#[deriving_clone]` is obsolete; use `#[deriving(Clone)]` instead
-#[deriving_eq] //~ ERROR `#[deriving_eq]` is obsolete; use `#[deriving(Eq)]` instead
-#[deriving_iter_bytes]
-//~^ ERROR `#[deriving_iter_bytes]` is obsolete; use `#[deriving(IterBytes)]` instead
-struct Foo;
+#[auto_encode] //~ ERROR: `#[auto_encode]` is deprecated
+#[auto_decode] //~ ERROR: `#[auto_decode]` is deprecated
+struct A;
 
-pub fn main() { }
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/import2.rs b/src/test/compile-fail/import2.rs
index 5ee4a01f2b9..7cb017091e0 100644
--- a/src/test/compile-fail/import2.rs
+++ b/src/test/compile-fail/import2.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use baz::zed::bar;  //~ ERROR unresolved name
+use baz::zed::bar;  //~ ERROR unresolved import
 //~^ ERROR failed to resolve import
 
 mod baz {}
diff --git a/src/test/compile-fail/issue-2123.rs b/src/test/compile-fail/issue-2123.rs
index 56f0c5e3dd0..6d617d338ed 100644
--- a/src/test/compile-fail/issue-2123.rs
+++ b/src/test/compile-fail/issue-2123.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use x = m::f; //~ ERROR failed to resolve import
+              //~^ unresolved import: there is no `f` in `m`
 
 mod m {
 }
diff --git a/src/test/compile-fail/issue-2937.rs b/src/test/compile-fail/issue-2937.rs
index 56f0c5e3dd0..b225c5496e2 100644
--- a/src/test/compile-fail/issue-2937.rs
+++ b/src/test/compile-fail/issue-2937.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use x = m::f; //~ ERROR failed to resolve import
+              //~^ ERROR unresolved import: there is no `f` in `m`
 
 mod m {
 }
diff --git a/src/test/compile-fail/issue-3601.rs b/src/test/compile-fail/issue-3601.rs
index e0adf9eca51..c37c5a3e5af 100644
--- a/src/test/compile-fail/issue-3601.rs
+++ b/src/test/compile-fail/issue-3601.rs
@@ -37,6 +37,6 @@ fn main() {
         ~Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
             ~HTMLImageElement(ref d) if d.image.is_some() => { true }
         },
-        _ => fail!(~"WAT") //~ ERROR unreachable pattern
+        _ => fail!("WAT") //~ ERROR unreachable pattern
     };
 }
diff --git a/src/test/compile-fail/issue-3993-2.rs b/src/test/compile-fail/issue-3993-2.rs
index 1293dc8a875..2ca871cd11c 100644
--- a/src/test/compile-fail/issue-3993-2.rs
+++ b/src/test/compile-fail/issue-3993-2.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use zoo::{duck, goose}; //~ ERROR failed to resolve import
+                        //~^ ERROR unresolved import: found `goose` in `zoo` but it is private
 
 mod zoo {
     pub enum bird {
diff --git a/src/test/compile-fail/issue-3993-3.rs b/src/test/compile-fail/issue-3993-3.rs
index 1ccf019a7c1..ccda6f158ed 100644
--- a/src/test/compile-fail/issue-3993-3.rs
+++ b/src/test/compile-fail/issue-3993-3.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use zoo::fly; //~ ERROR failed to resolve import
+              //~^ ERROR unresolved import: found `fly` in `zoo` but it is private
 
 mod zoo {
     priv type fly = ();
diff --git a/src/test/compile-fail/issue-3993.rs b/src/test/compile-fail/issue-3993.rs
index 5b47c3e2406..450ea023bcb 100644
--- a/src/test/compile-fail/issue-3993.rs
+++ b/src/test/compile-fail/issue-3993.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use zoo::fly; //~ ERROR failed to resolve import
+              //~^ ERROR unresolved import: found `fly` in `zoo` but it is private
 
 mod zoo {
     priv fn fly() {}
diff --git a/src/test/compile-fail/issue-5099.rs b/src/test/compile-fail/issue-5099.rs
index 80720f9e863..c2e1fc615cc 100644
--- a/src/test/compile-fail/issue-5099.rs
+++ b/src/test/compile-fail/issue-5099.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 
-trait B < A > { fn a() -> A { self.a} } //~ ERROR unresolved name
+trait B < A > { fn a() -> A { this.a } } //~ ERROR unresolved name
 
 fn main() {}
diff --git a/src/test/compile-fail/lint-impl-fn.rs b/src/test/compile-fail/lint-impl-fn.rs
new file mode 100644
index 00000000000..3cc0495206d
--- /dev/null
+++ b/src/test/compile-fail/lint-impl-fn.rs
@@ -0,0 +1,37 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(while_true)];
+
+struct A(int);
+
+impl A {
+    fn foo(&self) { while true {} }
+
+    #[deny(while_true)]
+    fn bar(&self) { while true {} } //~ ERROR: infinite loops
+}
+
+#[deny(while_true)]
+mod foo {
+    struct B(int);
+
+    impl B {
+        fn foo(&self) { while true {} } //~ ERROR: infinite loops
+
+        #[allow(while_true)]
+        fn bar(&self) { while true {} }
+    }
+}
+
+#[deny(while_true)]
+fn main() {
+    while true {} //~ ERROR: infinite loops
+}
diff --git a/src/test/compile-fail/unused-imports-warn.rs b/src/test/compile-fail/lint-unused-imports.rs
index f3b0a1f73f9..f3b0a1f73f9 100644
--- a/src/test/compile-fail/unused-imports-warn.rs
+++ b/src/test/compile-fail/lint-unused-imports.rs
diff --git a/src/test/compile-fail/unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs
index d1223cd8893..d1223cd8893 100644
--- a/src/test/compile-fail/unused-mut-variables.rs
+++ b/src/test/compile-fail/lint-unused-mut-variables.rs
diff --git a/src/test/compile-fail/unused-unsafe.rs b/src/test/compile-fail/lint-unused-unsafe.rs
index 9552badb57f..465e5548f67 100644
--- a/src/test/compile-fail/unused-unsafe.rs
+++ b/src/test/compile-fail/lint-unused-unsafe.rs
@@ -12,8 +12,10 @@
 
 #[deny(unused_unsafe)];
 
-extern mod foo {
-    fn bar();
+mod foo {
+    pub extern {
+        pub fn bar();
+    }
 }
 
 fn callback<T>(_f: &fn() -> T) -> T { fail!() }
diff --git a/src/test/compile-fail/liveness-dead.rs b/src/test/compile-fail/liveness-dead.rs
index 1d6a7426045..2ab3cb4568a 100644
--- a/src/test/compile-fail/liveness-dead.rs
+++ b/src/test/compile-fail/liveness-dead.rs
@@ -8,12 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[deny(dead_assignment)];
+
 fn f1(x: &mut int) {
     *x = 1; // no error
 }
 
 fn f2() {
-    let mut x = 3; //~ WARNING value assigned to `x` is never read
+    let mut x = 3; //~ ERROR: value assigned to `x` is never read
     x = 4;
     copy x;
 }
@@ -21,10 +23,7 @@ fn f2() {
 fn f3() {
     let mut x = 3;
     copy x;
-    x = 4; //~ WARNING value assigned to `x` is never read
+    x = 4; //~ ERROR: value assigned to `x` is never read
 }
 
-fn main() { // leave this in here just to trigger compile-fail:
-    let x: int;
-    copy x; //~ ERROR use of possibly uninitialized variable: `x`
-}
+fn main() {}
diff --git a/src/test/compile-fail/non-exhaustive-match-nested.rs b/src/test/compile-fail/non-exhaustive-match-nested.rs
index 34fe6b0f678..b87b3c5245a 100644
--- a/src/test/compile-fail/non-exhaustive-match-nested.rs
+++ b/src/test/compile-fail/non-exhaustive-match-nested.rs
@@ -16,7 +16,7 @@ enum u { c, d }
 fn main() {
   let x = a(c);
   match x {
-      a(d) => { fail!(~"hello"); }
-      b => { fail!(~"goodbye"); }
+      a(d) => { fail!("hello"); }
+      b => { fail!("goodbye"); }
     }
 }
diff --git a/src/test/compile-fail/noncopyable-match-pattern.rs b/src/test/compile-fail/noncopyable-match-pattern.rs
index e8b01765a44..155b3981483 100644
--- a/src/test/compile-fail/noncopyable-match-pattern.rs
+++ b/src/test/compile-fail/noncopyable-match-pattern.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let x = Some(unstable::exclusive(false));
+    let x = Some(unstable::sync::exclusive(false));
     match x {
         Some(copy z) => { //~ ERROR copying a value of non-copyable type
             do z.with |b| { assert!(!*b); }
diff --git a/src/test/compile-fail/super-at-top-level.rs b/src/test/compile-fail/super-at-top-level.rs
index f1064a62905..9ec92e6dbfa 100644
--- a/src/test/compile-fail/super-at-top-level.rs
+++ b/src/test/compile-fail/super-at-top-level.rs
@@ -1,5 +1,4 @@
-use super::f;   //~ ERROR unresolved name
-//~^ ERROR failed to resolve import
+use super::f; //~ ERROR failed to resolve import
 
 fn main() {
 }
diff --git a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
index af99c0e5f29..22f6a34a181 100644
--- a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
+++ b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
@@ -15,7 +15,7 @@
 
 extern mod core;
 
-fn last<T>(v: ~[&T]) -> core::Option<T> {
+fn last<T>(v: ~[&T]) -> core::option::Option<T> {
     fail!();
 }
 
diff --git a/src/test/compile-fail/unresolved-import.rs b/src/test/compile-fail/unresolved-import.rs
index 1bd3efeadcb..fc69c34c118 100644
--- a/src/test/compile-fail/unresolved-import.rs
+++ b/src/test/compile-fail/unresolved-import.rs
@@ -8,5 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use foo::bar; //~ ERROR unresolved import. maybe a missing
-              //~^ ERROR failed to resolve import
+use foo::bar; //~ ERROR unresolved import. maybe a missing `extern mod foo`?
+              //~^ ERROR failed to resolve import `foo::bar`
+use x = bar::baz; //~ ERROR unresolved import: there is no `baz` in `bar`
+                  //~^ ERROR failed to resolve import `bar::baz`
+
+mod bar {
+    struct bar;
+}
diff --git a/src/test/compile-fail/unsafe-fn-autoderef.rs b/src/test/compile-fail/unsafe-fn-autoderef.rs
index b602d1717be..82efd579518 100644
--- a/src/test/compile-fail/unsafe-fn-autoderef.rs
+++ b/src/test/compile-fail/unsafe-fn-autoderef.rs
@@ -9,9 +9,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
-type rec = {f: int};
-fn f(p: *rec) -> int {
+struct Rec {
+    f: int
+}
+
+fn f(p: *Rec) -> int {
 
     // Test that * ptrs do not autoderef.  There is a deeper reason for
     // prohibiting this, beyond making unsafe things annoying (which doesn't
@@ -25,7 +27,7 @@ fn f(p: *rec) -> int {
     // are prohibited by various checks, such as that the enum is
     // instantiable and so forth).
 
-    return p.f; //~ ERROR attempted access of field `f` on type `*rec`
+    return p.f; //~ ERROR attempted access of field `f` on type `*Rec`
 }
 
 fn main() {
diff --git a/src/test/compile-fail/use-after-move-self-based-on-type.rs b/src/test/compile-fail/use-after-move-self-based-on-type.rs
index 627b8924b67..d19b4dfbd57 100644
--- a/src/test/compile-fail/use-after-move-self-based-on-type.rs
+++ b/src/test/compile-fail/use-after-move-self-based-on-type.rs
@@ -9,7 +9,7 @@ impl Drop for S {
 pub impl S {
     fn foo(self) -> int {
         self.bar();
-        return self.x;  //~ ERROR use of moved value
+        return self.x;  //~ ERROR use of partially moved value
     }
 
     fn bar(self) {}
diff --git a/src/test/compile-fail/use-after-move-self.rs b/src/test/compile-fail/use-after-move-self.rs
index 11f37df4541..b2eaffdd066 100644
--- a/src/test/compile-fail/use-after-move-self.rs
+++ b/src/test/compile-fail/use-after-move-self.rs
@@ -5,7 +5,7 @@ struct S {
 pub impl S {
     fn foo(self) -> int {
         self.bar();
-        return *self.x;  //~ ERROR use of moved value
+        return *self.x;  //~ ERROR use of partially moved value
     }
 
     fn bar(self) {}
diff --git a/src/test/run-fail/alt-disc-bot.rs b/src/test/run-fail/alt-disc-bot.rs
index afe2735e67d..13ccd118c61 100644
--- a/src/test/run-fail/alt-disc-bot.rs
+++ b/src/test/run-fail/alt-disc-bot.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 // error-pattern:quux
-fn f() -> ! { fail!(~"quux") }
+fn f() -> ! { fail!("quux") }
 fn g() -> int { match f() { true => { 1 } false => { 0 } } }
 fn main() { g(); }
diff --git a/src/test/run-fail/alt-wildcards.rs b/src/test/run-fail/alt-wildcards.rs
index 8aead798d5d..306357b0001 100644
--- a/src/test/run-fail/alt-wildcards.rs
+++ b/src/test/run-fail/alt-wildcards.rs
@@ -11,9 +11,9 @@
 // error-pattern:squirrelcupcake
 fn cmp() -> int {
     match (option::Some('a'), option::None::<char>) {
-        (option::Some(_), _) => { fail!(~"squirrelcupcake"); }
+        (option::Some(_), _) => { fail!("squirrelcupcake"); }
         (_, option::Some(_)) => { fail!(); }
-        _                    => { fail!(~"wat"); }
+        _                    => { fail!("wat"); }
     }
 }
 
diff --git a/src/test/run-fail/args-fail.rs b/src/test/run-fail/args-fail.rs
index 5cdddb0cda8..911409b6898 100644
--- a/src/test/run-fail/args-fail.rs
+++ b/src/test/run-fail/args-fail.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 // error-pattern:meep
-fn f(a: int, b: int, c: @int) { fail!(~"moop"); }
+fn f(a: int, b: int, c: @int) { fail!("moop"); }
 
-fn main() { f(1, fail!(~"meep"), @42); }
+fn main() { f(1, fail!("meep"), @42); }
diff --git a/src/test/run-fail/assert-eq-macro-fail.rs b/src/test/run-fail/assert-eq-macro-fail.rs
index 7d98d0dccde..facfb89409c 100644
--- a/src/test/run-fail/assert-eq-macro-fail.rs
+++ b/src/test/run-fail/assert-eq-macro-fail.rs
@@ -1,4 +1,4 @@
-// error-pattern:left: 14 != right: 15
+// error-pattern:left: 14 does not equal right: 15
 
 #[deriving(Eq)]
 struct Point { x : int }
diff --git a/src/test/run-fail/binop-fail-2.rs b/src/test/run-fail/binop-fail-2.rs
index 2668570e6fb..a49f96fced5 100644
--- a/src/test/run-fail/binop-fail-2.rs
+++ b/src/test/run-fail/binop-fail-2.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 // error-pattern:quux
-fn my_err(s: ~str) -> ! { error!(s); fail!(~"quux"); }
+fn my_err(s: ~str) -> ! { error!(s); fail!("quux"); }
 fn main() { 3u == my_err(~"bye"); }
diff --git a/src/test/run-fail/binop-fail.rs b/src/test/run-fail/binop-fail.rs
index 2668570e6fb..a49f96fced5 100644
--- a/src/test/run-fail/binop-fail.rs
+++ b/src/test/run-fail/binop-fail.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 // error-pattern:quux
-fn my_err(s: ~str) -> ! { error!(s); fail!(~"quux"); }
+fn my_err(s: ~str) -> ! { error!(s); fail!("quux"); }
 fn main() { 3u == my_err(~"bye"); }
diff --git a/src/test/run-fail/bug-811.rs b/src/test/run-fail/bug-811.rs
index d3d13f6b5fe..b497b0224b9 100644
--- a/src/test/run-fail/bug-811.rs
+++ b/src/test/run-fail/bug-811.rs
@@ -21,4 +21,4 @@ struct chan_t<T> {
 
 fn send<T:Owned>(ch: chan_t<T>, data: T) { fail!(); }
 
-fn main() { fail!(~"quux"); }
+fn main() { fail!("quux"); }
diff --git a/src/test/run-fail/die-macro-expr.rs b/src/test/run-fail/die-macro-expr.rs
index 06365ed989a..cf6f5a009d5 100644
--- a/src/test/run-fail/die-macro-expr.rs
+++ b/src/test/run-fail/die-macro-expr.rs
@@ -1,5 +1,5 @@
 // error-pattern:test
 
 fn main() {
-    let i: int = fail!(~"test");
+    let i: int = fail!("test");
 }
diff --git a/src/test/run-fail/die-macro-pure.rs b/src/test/run-fail/die-macro-pure.rs
index 296fba2ae9b..bb62a7e8bef 100644
--- a/src/test/run-fail/die-macro-pure.rs
+++ b/src/test/run-fail/die-macro-pure.rs
@@ -1,7 +1,7 @@
 // error-pattern:test
 
 fn f() {
-    fail!(~"test");
+    fail!("test");
 }
 
 fn main() {
diff --git a/src/test/run-fail/die-macro.rs b/src/test/run-fail/die-macro.rs
index 3fa3d69441a..71cc7317e6e 100644
--- a/src/test/run-fail/die-macro.rs
+++ b/src/test/run-fail/die-macro.rs
@@ -1,5 +1,5 @@
 // error-pattern:test
 
 fn main() {
-    fail!(~"test");
+    fail!("test");
 }
diff --git a/src/test/run-fail/doublefail.rs b/src/test/run-fail/doublefail.rs
index ce9678aa5eb..ccf7aa57019 100644
--- a/src/test/run-fail/doublefail.rs
+++ b/src/test/run-fail/doublefail.rs
@@ -10,6 +10,6 @@
 
 //error-pattern:One
 fn main() {
-    fail!(~"One");
-    fail!(~"Two");
+    fail!("One");
+    fail!("Two");
 }
diff --git a/src/test/run-fail/explicit-fail-msg.rs b/src/test/run-fail/explicit-fail-msg.rs
index 17fb14881a5..28fd9aff009 100644
--- a/src/test/run-fail/explicit-fail-msg.rs
+++ b/src/test/run-fail/explicit-fail-msg.rs
@@ -10,5 +10,5 @@
 
 // error-pattern:wooooo
 fn main() {
-    let mut a = 1; if 1 == 1 { a = 2; } fail!(~"woooo" + ~"o");
+    let mut a = 1; if 1 == 1 { a = 2; } fail!(~"woooo" + "o");
 }
diff --git a/src/test/run-fail/fail-arg.rs b/src/test/run-fail/fail-arg.rs
index f1a26df924b..f0d9b5a3178 100644
--- a/src/test/run-fail/fail-arg.rs
+++ b/src/test/run-fail/fail-arg.rs
@@ -11,4 +11,4 @@
 // error-pattern:woe
 fn f(a: int) { debug!(a); }
 
-fn main() { f(fail!(~"woe")); }
+fn main() { f(fail!("woe")); }
diff --git a/src/test/run-fail/fail-macro-owned.rs b/src/test/run-fail/fail-macro-owned.rs
index 6bed79a885f..e424647569a 100644
--- a/src/test/run-fail/fail-macro-owned.rs
+++ b/src/test/run-fail/fail-macro-owned.rs
@@ -11,5 +11,5 @@
 // error-pattern:task failed at 'test-fail-owned'
 
 fn main() {
-    fail!(~"test-fail-owned");
+    fail!("test-fail-owned");
 }
diff --git a/src/test/run-fail/fail-main.rs b/src/test/run-fail/fail-main.rs
index 50031261bfc..beb0d38ea47 100644
--- a/src/test/run-fail/fail-main.rs
+++ b/src/test/run-fail/fail-main.rs
@@ -10,4 +10,4 @@
 
 // error-pattern:moop
 extern mod std;
-fn main() { fail!(~"moop"); }
+fn main() { fail!("moop"); }
diff --git a/src/test/run-fail/fail-parens.rs b/src/test/run-fail/fail-parens.rs
index 5ba907b0eb6..90a44e42759 100644
--- a/src/test/run-fail/fail-parens.rs
+++ b/src/test/run-fail/fail-parens.rs
@@ -13,7 +13,7 @@
 // error-pattern:oops
 
 fn bigfail() {
-    while (fail!(~"oops")) { if (fail!()) {
+    while (fail!("oops")) { if (fail!()) {
         match (fail!()) { () => {
         }
                      }
diff --git a/src/test/run-fail/for-each-loop-fail.rs b/src/test/run-fail/for-each-loop-fail.rs
index fa62a9c5c34..3ae387952a2 100644
--- a/src/test/run-fail/for-each-loop-fail.rs
+++ b/src/test/run-fail/for-each-loop-fail.rs
@@ -10,4 +10,4 @@
 
 // error-pattern:moop
 extern mod std;
-fn main() { for uint::range(0u, 10u) |_i| { fail!(~"moop"); } }
+fn main() { for uint::range(0u, 10u) |_i| { fail!("moop"); } }
diff --git a/src/test/run-fail/if-check-fail.rs b/src/test/run-fail/if-check-fail.rs
index a77d520b07e..72a89c22dc5 100644
--- a/src/test/run-fail/if-check-fail.rs
+++ b/src/test/run-fail/if-check-fail.rs
@@ -19,7 +19,7 @@ fn foo(x: uint) {
     if even(x) {
         debug!(x);
     } else {
-        fail!(~"Number is odd");
+        fail!("Number is odd");
     }
 }
 
diff --git a/src/test/run-fail/if-cond-bot.rs b/src/test/run-fail/if-cond-bot.rs
index 92063e76c34..9a36681da5f 100644
--- a/src/test/run-fail/if-cond-bot.rs
+++ b/src/test/run-fail/if-cond-bot.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 // error-pattern:quux
-fn my_err(s: ~str) -> ! { error!(s); fail!(~"quux"); }
+fn my_err(s: ~str) -> ! { error!(s); fail!("quux"); }
 fn main() { if my_err(~"bye") { } }
diff --git a/src/test/run-fail/issue-3029.rs b/src/test/run-fail/issue-3029.rs
index 3ae6eccd5e2..1743d9a6d40 100644
--- a/src/test/run-fail/issue-3029.rs
+++ b/src/test/run-fail/issue-3029.rs
@@ -11,7 +11,7 @@
 // error-pattern:so long
 fn main() {
     let x = ~[], y = ~[3];
-    fail!(~"so long");
+    fail!("so long");
     x += y;
     ~"good" + ~"bye";
 }
diff --git a/src/test/run-fail/issue-948.rs b/src/test/run-fail/issue-948.rs
index 2f9a1e8a058..1ad4422e1a9 100644
--- a/src/test/run-fail/issue-948.rs
+++ b/src/test/run-fail/issue-948.rs
@@ -14,5 +14,5 @@ struct Point { x: int, y: int }
 
 fn main() {
     let origin = Point {x: 0, y: 0};
-    let f: Point = Point {x: (fail!(~"beep boop")),.. origin};
+    let f: Point = Point {x: (fail!("beep boop")),.. origin};
 }
diff --git a/src/test/run-fail/linked-failure3.rs b/src/test/run-fail/linked-failure3.rs
index c2c97662b6c..4b09cb75324 100644
--- a/src/test/run-fail/linked-failure3.rs
+++ b/src/test/run-fail/linked-failure3.rs
@@ -12,7 +12,7 @@
 
 // error-pattern:fail
 
-fn grandchild() { fail!(~"grandchild dies"); }
+fn grandchild() { fail!("grandchild dies"); }
 
 fn child() {
     let (p, _c) = comm::stream::<int>();
diff --git a/src/test/run-fail/rhs-type.rs b/src/test/run-fail/rhs-type.rs
index f432abe85ab..444c899188f 100644
--- a/src/test/run-fail/rhs-type.rs
+++ b/src/test/run-fail/rhs-type.rs
@@ -14,4 +14,4 @@
 
 struct T { t: ~str }
 
-fn main() { let pth = fail!(~"bye"); let rs: T = T {t: pth}; }
+fn main() { let pth = fail!("bye"); let rs: T = T {t: pth}; }
diff --git a/src/test/run-fail/rt-log-trunc.rs b/src/test/run-fail/rt-log-trunc.rs
index 07cf24e2feb..1dd27d7d3ae 100644
--- a/src/test/run-fail/rt-log-trunc.rs
+++ b/src/test/run-fail/rt-log-trunc.rs
@@ -12,7 +12,7 @@
 // error-pattern:[...]
 
 fn main() {
-    fail!(~"\
+    fail!("\
           aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
           aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
           aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs
index fd898e31347..b055bf4ed95 100644
--- a/src/test/run-fail/run-unexported-tests.rs
+++ b/src/test/run-fail/run-unexported-tests.rs
@@ -17,5 +17,5 @@ mod m {
     pub fn exported() { }
 
     #[test]
-    fn unexported() { fail!(~"runned an unexported test"); }
+    fn unexported() { fail!("runned an unexported test"); }
 }
diff --git a/src/test/run-fail/task-comm-recv-block.rs b/src/test/run-fail/task-comm-recv-block.rs
index a0896ea7bab..ca411872b61 100644
--- a/src/test/run-fail/task-comm-recv-block.rs
+++ b/src/test/run-fail/task-comm-recv-block.rs
@@ -12,7 +12,7 @@
 
 fn goodfail() {
     task::yield();
-    fail!(~"goodfail");
+    fail!("goodfail");
 }
 
 fn main() {
@@ -21,5 +21,5 @@ fn main() {
     // We shouldn't be able to get past this recv since there's no
     // message available
     let i: int = po.recv();
-    fail!(~"badfail");
+    fail!("badfail");
 }
diff --git a/src/test/run-fail/unwind-alt.rs b/src/test/run-fail/unwind-alt.rs
index 41cf92d92b8..d7e079ad907 100644
--- a/src/test/run-fail/unwind-alt.rs
+++ b/src/test/run-fail/unwind-alt.rs
@@ -15,7 +15,7 @@ fn test_box() {
 }
 fn test_str() {
   let res = match false { true => { ~"happy" },
-     _ => fail!(~"non-exhaustive match failure") };
+     _ => fail!("non-exhaustive match failure") };
   assert!(res == ~"happy");
 }
 fn main() {
diff --git a/src/test/run-fail/unwind-lambda.rs b/src/test/run-fail/unwind-lambda.rs
index f92f7874fc3..75c3638a99d 100644
--- a/src/test/run-fail/unwind-lambda.rs
+++ b/src/test/run-fail/unwind-lambda.rs
@@ -22,7 +22,7 @@ fn main() {
         let cheese = copy cheese;
         let f: &fn() = || {
             let chew = mush + cheese;
-            fail!(~"so yummy")
+            fail!("so yummy")
         };
         f();
     });
diff --git a/src/test/run-fail/unwind-resource-fail.rs b/src/test/run-fail/unwind-resource-fail.rs
index d60e575bac4..486c2dd3b36 100644
--- a/src/test/run-fail/unwind-resource-fail.rs
+++ b/src/test/run-fail/unwind-resource-fail.rs
@@ -15,7 +15,7 @@ struct r {
 }
 
 impl Drop for r {
-    fn finalize(&self) { fail!(~"squirrel") }
+    fn finalize(&self) { fail!("squirrel") }
 }
 
 fn r(i: int) -> r { r { i: i } }
diff --git a/src/test/run-fail/unwind-resource-fail2.rs b/src/test/run-fail/unwind-resource-fail2.rs
index e276f2065f7..ca98a61f234 100644
--- a/src/test/run-fail/unwind-resource-fail2.rs
+++ b/src/test/run-fail/unwind-resource-fail2.rs
@@ -16,7 +16,7 @@ struct r {
 }
 
 impl Drop for r {
-    fn finalize(&self) { fail!(~"wombat") }
+    fn finalize(&self) { fail!("wombat") }
 }
 
 fn r(i: int) -> r { r { i: i } }
diff --git a/src/test/run-fail/unwind-resource-fail3.rs b/src/test/run-fail/unwind-resource-fail3.rs
index bfbad0b5aea..9d6f877293b 100644
--- a/src/test/run-fail/unwind-resource-fail3.rs
+++ b/src/test/run-fail/unwind-resource-fail3.rs
@@ -20,7 +20,7 @@ fn faily_box(i: @int) -> faily_box { faily_box { i: i } }
 #[unsafe_destructor]
 impl Drop for faily_box {
     fn finalize(&self) {
-        fail!(~"quux");
+        fail!("quux");
     }
 }
 
diff --git a/src/test/run-fail/while-body-fails.rs b/src/test/run-fail/while-body-fails.rs
index 73718b0d0b6..836ed9c0155 100644
--- a/src/test/run-fail/while-body-fails.rs
+++ b/src/test/run-fail/while-body-fails.rs
@@ -9,4 +9,4 @@
 // except according to those terms.
 
 // error-pattern:quux
-fn main() { let x: int = { while true { fail!(~"quux"); } ; 8 } ; }
+fn main() { let x: int = { while true { fail!("quux"); } ; 8 } ; }
diff --git a/src/test/run-fail/while-fail.rs b/src/test/run-fail/while-fail.rs
index 22cbf215e9e..db04026ed97 100644
--- a/src/test/run-fail/while-fail.rs
+++ b/src/test/run-fail/while-fail.rs
@@ -10,5 +10,5 @@
 
 // error-pattern:giraffe
 fn main() {
-    fail!({ while true { fail!(~"giraffe")}; ~"clandestine" });
+    fail!({ while true { fail!("giraffe") }; "clandestine" });
 }
diff --git a/src/test/run-fail/zip-different-lengths.rs b/src/test/run-fail/zip-different-lengths.rs
index 87bb8669046..ae76c4ba603 100644
--- a/src/test/run-fail/zip-different-lengths.rs
+++ b/src/test/run-fail/zip-different-lengths.rs
@@ -37,5 +37,5 @@ fn main() {
 
     assert!(same_length(chars, ints));
     let ps = zip(chars, ints);
-    fail!(~"the impossible happened");
+    fail!("the impossible happened");
 }
diff --git a/src/test/run-pass/alt-pattern-lit.rs b/src/test/run-pass/alt-pattern-lit.rs
index d6a8afbc4e7..3e01253094b 100644
--- a/src/test/run-pass/alt-pattern-lit.rs
+++ b/src/test/run-pass/alt-pattern-lit.rs
@@ -14,7 +14,7 @@ fn altlit(f: int) -> int {
     match f {
       10 => { debug!("case 10"); return 20; }
       11 => { debug!("case 11"); return 22; }
-      _  => fail!(~"the impossible happened")
+      _  => fail!("the impossible happened")
     }
 }
 
diff --git a/src/test/run-pass/alt-range.rs b/src/test/run-pass/alt-range.rs
index b3634b498b1..6b02b21a084 100644
--- a/src/test/run-pass/alt-range.rs
+++ b/src/test/run-pass/alt-range.rs
@@ -11,31 +11,31 @@
 pub fn main() {
     match 5u {
       1u..5u => {}
-      _ => fail!(~"should match range"),
+      _ => fail!("should match range"),
     }
     match 5u {
-      6u..7u => fail!(~"shouldn't match range"),
+      6u..7u => fail!("shouldn't match range"),
       _ => {}
     }
     match 5u {
-      1u => fail!(~"should match non-first range"),
+      1u => fail!("should match non-first range"),
       2u..6u => {}
-      _ => fail!(~"math is broken")
+      _ => fail!("math is broken")
     }
     match 'c' {
       'a'..'z' => {}
-      _ => fail!(~"should suppport char ranges")
+      _ => fail!("should suppport char ranges")
     }
     match -3 {
       -7..5 => {}
-      _ => fail!(~"should match signed range")
+      _ => fail!("should match signed range")
     }
     match 3.0 {
       1.0..5.0 => {}
-      _ => fail!(~"should match float range")
+      _ => fail!("should match float range")
     }
     match -1.5 {
       -3.6..3.6 => {}
-      _ => fail!(~"should match negative float range")
+      _ => fail!("should match negative float range")
     }
 }
diff --git a/src/test/run-pass/alt-ref-binding-in-guard-3256.rs b/src/test/run-pass/alt-ref-binding-in-guard-3256.rs
index 1ece3b5fd93..ed7a6316374 100644
--- a/src/test/run-pass/alt-ref-binding-in-guard-3256.rs
+++ b/src/test/run-pass/alt-ref-binding-in-guard-3256.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = Some(unstable::exclusive(true));
+    let x = Some(unstable::sync::exclusive(true));
     match x {
         Some(ref z) if z.with(|b| *b) => {
             do z.with |b| { assert!(*b); }
diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs
index 6946ed3fbcf..b21213bb221 100644
--- a/src/test/run-pass/assignability-trait.rs
+++ b/src/test/run-pass/assignability-trait.rs
@@ -39,15 +39,15 @@ pub fn main() {
     // Call a method
     for x.iterate() |y| { assert!(x[*y] == *y); }
     // Call a parameterized function
-    assert!(length(x.clone()) == vec::len(x));
+    assert!(length(x.clone()) == x.len());
     // Call a parameterized function, with type arguments that require
     // a borrow
-    assert!(length::<int, &[int]>(x) == vec::len(x));
+    assert!(length::<int, &[int]>(x) == x.len());
 
     // Now try it with a type that *needs* to be borrowed
     let z = [0,1,2,3];
     // Call a method
     for z.iterate() |y| { assert!(z[*y] == *y); }
     // Call a parameterized function
-    assert!(length::<int, &[int]>(z) == vec::len(z));
+    assert!(length::<int, &[int]>(z) == z.len());
 }
diff --git a/src/test/run-pass/binary-minus-without-space.rs b/src/test/run-pass/binary-minus-without-space.rs
index 50dbefdd086..93f57c6722f 100644
--- a/src/test/run-pass/binary-minus-without-space.rs
+++ b/src/test/run-pass/binary-minus-without-space.rs
@@ -11,6 +11,6 @@
 // Check that issue #954 stays fixed
 
 pub fn main() {
-    match -1 { -1 => {}, _ => fail!(~"wat") }
+    match -1 { -1 => {}, _ => fail!("wat") }
     assert!(1-1 == 0);
 }
diff --git a/src/test/run-pass/block-arg.rs b/src/test/run-pass/block-arg.rs
index 93c44b8faa1..04032900c51 100644
--- a/src/test/run-pass/block-arg.rs
+++ b/src/test/run-pass/block-arg.rs
@@ -35,14 +35,14 @@ pub fn main() {
         assert!(false);
     }
     match do vec::all(v) |e| { e.is_negative() } {
-        true => { fail!(~"incorrect answer."); }
+        true => { fail!("incorrect answer."); }
         false => { }
     }
     match 3 {
       _ if do vec::any(v) |e| { e.is_negative() } => {
       }
       _ => {
-        fail!(~"wrong answer.");
+        fail!("wrong answer.");
       }
     }
 
diff --git a/src/test/run-pass/borrowck-rvalues-mutable.rs b/src/test/run-pass/borrowck-rvalues-mutable.rs
new file mode 100644
index 00000000000..cf5a9341c9d
--- /dev/null
+++ b/src/test/run-pass/borrowck-rvalues-mutable.rs
@@ -0,0 +1,30 @@
+// 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.
+
+struct Counter {
+    value: uint
+}
+
+impl Counter {
+    fn new(v: uint) -> Counter {
+        Counter {value: v}
+    }
+
+    fn get_and_inc(&mut self) -> uint {
+        let v = self.value;
+        self.value += 1;
+        v
+    }
+}
+
+pub fn main() {
+    let v = Counter::new(22).get_and_inc();
+    assert_eq!(v, 22);
+}
diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs
index 39d4b25f262..f7d526cde91 100644
--- a/src/test/run-pass/class-impl-very-parameterized-trait.rs
+++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs
@@ -79,7 +79,7 @@ impl<T> Map<int, T> for cat<T> {
     }
 
     fn mutate_values(&mut self, _f: &fn(&int, &mut T) -> bool) -> bool {
-        fail!(~"nope")
+        fail!("nope")
     }
 
     fn insert(&mut self, k: int, _: T) -> bool {
@@ -114,7 +114,7 @@ pub impl<T> cat<T> {
     fn get<'a>(&'a self, k: &int) -> &'a T {
         match self.find(k) {
           Some(v) => { v }
-          None    => { fail!(~"epic fail"); }
+          None    => { fail!("epic fail"); }
         }
     }
 
diff --git a/src/test/run-pass/class-implements-multiple-traits.rs b/src/test/run-pass/class-implements-multiple-traits.rs
index 3a5bd648639..61dfcfed7bd 100644
--- a/src/test/run-pass/class-implements-multiple-traits.rs
+++ b/src/test/run-pass/class-implements-multiple-traits.rs
@@ -103,7 +103,7 @@ fn annoy_neighbors<T:noisy>(critter: T) {
 
 fn bite_everything<T:bitey>(critter: T) -> bool {
   let mut left : ~[body_part] = ~[finger, toe, nose, ear];
-  while vec::len(left) > 0u {
+  while left.len() > 0u {
     let part = critter.bite();
     debug!("%? %?", left, part);
     if vec_includes(left, part) {
diff --git a/src/test/run-pass/cond-macro-no-default.rs b/src/test/run-pass/cond-macro-no-default.rs
new file mode 100644
index 00000000000..6b90308f8a8
--- /dev/null
+++ b/src/test/run-pass/cond-macro-no-default.rs
@@ -0,0 +1,23 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn clamp<T:Copy + Ord + Signed>(x: T, mn: T, mx: T) -> T {
+    cond!(
+        (x > mx) { return mx; }
+        (x < mn) { return mn; }
+    )
+    return x;
+}
+
+fn main() {
+    assert_eq!(clamp(1, 2, 4), 2);
+    assert_eq!(clamp(8, 2, 4), 4);
+    assert_eq!(clamp(3, 2, 4), 3);
+}
diff --git a/src/test/run-pass/cond-macro.rs b/src/test/run-pass/cond-macro.rs
new file mode 100644
index 00000000000..929752b3f1a
--- /dev/null
+++ b/src/test/run-pass/cond-macro.rs
@@ -0,0 +1,23 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn clamp<T:Copy + Ord + Signed>(x: T, mn: T, mx: T) -> T {
+    cond!(
+        (x > mx) { mx }
+        (x < mn) { mn }
+        _        { x  }
+    )
+}
+
+fn main() {
+    assert_eq!(clamp(1, 2, 4), 2);
+    assert_eq!(clamp(8, 2, 4), 4);
+    assert_eq!(clamp(3, 2, 4), 3);
+}
diff --git a/src/test/run-pass/deriving-clone-enum.rs b/src/test/run-pass/deriving-clone-enum.rs
index 969e1fb5dd6..9ce965aa49f 100644
--- a/src/test/run-pass/deriving-clone-enum.rs
+++ b/src/test/run-pass/deriving-clone-enum.rs
@@ -8,11 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[deriving(Clone)]
+#[deriving(Clone, DeepClone)]
 enum E {
     A,
     B(()),
     C
 }
 
-pub fn main() {}
+pub fn main() {
+    let _ = A.clone();
+    let _ = B(()).deep_clone();
+}
diff --git a/src/test/run-pass/deriving-clone-generic-enum.rs b/src/test/run-pass/deriving-clone-generic-enum.rs
index 23841017e93..78abbf504f3 100644
--- a/src/test/run-pass/deriving-clone-generic-enum.rs
+++ b/src/test/run-pass/deriving-clone-generic-enum.rs
@@ -1,8 +1,21 @@
-#[deriving(Clone)]
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving(Clone, DeepClone)]
 enum E<T,U> {
     A(T),
     B(T,U),
     C
 }
 
-fn main() {}
+fn main() {
+    let _ = A::<int, int>(1i).clone();
+    let _ = B(1i, 1.234).deep_clone();
+}
diff --git a/src/test/run-pass/deriving-clone-generic-struct.rs b/src/test/run-pass/deriving-clone-generic-struct.rs
index 0a7a5a3aa75..fd300cbc8b7 100644
--- a/src/test/run-pass/deriving-clone-generic-struct.rs
+++ b/src/test/run-pass/deriving-clone-generic-struct.rs
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[deriving(Clone)]
+#[deriving(Clone, DeepClone)]
 struct S<T> {
     foo: (),
     bar: (),
     baz: T,
 }
 
-pub fn main() {}
+pub fn main() {
+    let _ = S { foo: (), bar: (), baz: 1i }.clone().deep_clone();
+}
diff --git a/src/test/run-pass/deriving-clone-generic-tuple-struct.rs b/src/test/run-pass/deriving-clone-generic-tuple-struct.rs
index d6a69e8e6ac..c082a11eab8 100644
--- a/src/test/run-pass/deriving-clone-generic-tuple-struct.rs
+++ b/src/test/run-pass/deriving-clone-generic-tuple-struct.rs
@@ -1,4 +1,16 @@
-#[deriving(Clone)]
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving(Clone, DeepClone)]
 struct S<T>(T, ());
 
-fn main() {}
+fn main() {
+    let _ = S(1i, ()).clone().deep_clone();
+}
diff --git a/src/test/run-pass/deriving-clone-struct.rs b/src/test/run-pass/deriving-clone-struct.rs
index 4dcbadbb3ef..d540b047af7 100644
--- a/src/test/run-pass/deriving-clone-struct.rs
+++ b/src/test/run-pass/deriving-clone-struct.rs
@@ -1,4 +1,14 @@
-#[deriving(Clone)]
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving(Clone, DeepClone)]
 struct S {
     _int: int,
     _i8: i8,
diff --git a/src/test/run-pass/expr-alt-box.rs b/src/test/run-pass/expr-alt-box.rs
index 5439d13fed8..2e65bb86655 100644
--- a/src/test/run-pass/expr-alt-box.rs
+++ b/src/test/run-pass/expr-alt-box.rs
@@ -15,13 +15,13 @@
 
 // Tests for match as expressions resulting in boxed types
 fn test_box() {
-    let res = match true { true => { @100 } _ => fail!(~"wat") };
+    let res = match true { true => { @100 } _ => fail!("wat") };
     assert!((*res == 100));
 }
 
 fn test_str() {
     let res = match true { true => { ~"happy" },
-                         _ => fail!(~"not happy at all") };
+                         _ => fail!("not happy at all") };
     assert!((res == ~"happy"));
 }
 
diff --git a/src/test/run-pass/expr-alt-generic-box2.rs b/src/test/run-pass/expr-alt-generic-box2.rs
index 02227bbc700..c5c89b42825 100644
--- a/src/test/run-pass/expr-alt-generic-box2.rs
+++ b/src/test/run-pass/expr-alt-generic-box2.rs
@@ -14,7 +14,7 @@
 type compare<T> = @fn(T, T) -> bool;
 
 fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-    let actual: T = match true { true => { expected }, _ => fail!(~"wat") };
+    let actual: T = match true { true => { expected }, _ => fail!("wat") };
     assert!((eq(expected, actual)));
 }
 
diff --git a/src/test/run-pass/expr-alt-generic-unique1.rs b/src/test/run-pass/expr-alt-generic-unique1.rs
index 037cda85499..085d52d6d7f 100644
--- a/src/test/run-pass/expr-alt-generic-unique1.rs
+++ b/src/test/run-pass/expr-alt-generic-unique1.rs
@@ -16,7 +16,7 @@ type compare<T> = @fn(~T, ~T) -> bool;
 fn test_generic<T:Copy+Clone>(expected: ~T, eq: compare<T>) {
     let actual: ~T = match true {
         true => { expected.clone() },
-        _ => fail!(~"wat")
+        _ => fail!("wat")
     };
     assert!((eq(expected, actual)));
 }
diff --git a/src/test/run-pass/expr-alt-generic-unique2.rs b/src/test/run-pass/expr-alt-generic-unique2.rs
index 2d470cd6fcc..7ef1fb8cab8 100644
--- a/src/test/run-pass/expr-alt-generic-unique2.rs
+++ b/src/test/run-pass/expr-alt-generic-unique2.rs
@@ -16,7 +16,7 @@ type compare<T> = @fn(T, T) -> bool;
 fn test_generic<T:Copy+Clone>(expected: T, eq: compare<T>) {
     let actual: T = match true {
         true => expected.clone(),
-        _ => fail!(~"wat")
+        _ => fail!("wat")
     };
     assert!((eq(expected, actual)));
 }
diff --git a/src/test/run-pass/expr-alt-generic.rs b/src/test/run-pass/expr-alt-generic.rs
index 0fcca32cde0..04a229f2280 100644
--- a/src/test/run-pass/expr-alt-generic.rs
+++ b/src/test/run-pass/expr-alt-generic.rs
@@ -14,7 +14,7 @@
 type compare<T> = @fn(T, T) -> bool;
 
 fn test_generic<T:Copy>(expected: T, eq: compare<T>) {
-  let actual: T = match true { true => { expected }, _ => fail!(~"wat") };
+  let actual: T = match true { true => { expected }, _ => fail!("wat") };
     assert!((eq(expected, actual)));
 }
 
diff --git a/src/test/run-pass/for-loop-fail.rs b/src/test/run-pass/for-loop-fail.rs
index f885d8120e0..cf69d754f37 100644
--- a/src/test/run-pass/for-loop-fail.rs
+++ b/src/test/run-pass/for-loop-fail.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub fn main() { let x: ~[int] = ~[]; for x.each |_i| { fail!(~"moop"); } }
+pub fn main() { let x: ~[int] = ~[]; for x.each |_i| { fail!("moop"); } }
diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs
index bca4cbafc6c..c6ae2047147 100644
--- a/src/test/run-pass/hashmap-memory.rs
+++ b/src/test/run-pass/hashmap-memory.rs
@@ -71,7 +71,7 @@ mod map_reduce {
 
         start_mappers(ctrl_chan, inputs.clone());
 
-        let mut num_mappers = vec::len(inputs) as int;
+        let mut num_mappers = inputs.len() as int;
 
         while num_mappers > 0 {
             match ctrl_port.recv() {
diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs
index 60daaea57d7..e46d2a923a8 100644
--- a/src/test/run-pass/issue-2718.rs
+++ b/src/test/run-pass/issue-2718.rs
@@ -85,7 +85,7 @@ pub mod pipes {
             // The receiver will eventually clean this up.
             unsafe { forget(p); }
           }
-          full => { fail!(~"duplicate send") }
+          full => { fail!("duplicate send") }
           blocked => {
 
             // The receiver will eventually clean this up.
@@ -127,7 +127,7 @@ pub mod pipes {
           }
           full => {
             // This is impossible
-            fail!(~"you dun goofed")
+            fail!("you dun goofed")
           }
           terminated => {
             // I have to clean up, use drop_glue
@@ -144,7 +144,7 @@ pub mod pipes {
           }
           blocked => {
             // this shouldn't happen.
-            fail!(~"terminating a blocked packet")
+            fail!("terminating a blocked packet")
           }
           terminated | full => {
             // I have to clean up, use drop_glue
@@ -269,7 +269,7 @@ pub mod pingpong {
         pub fn do_pong(c: pong) -> (ping, ()) {
             let packet = ::pipes::recv(c);
             if packet.is_none() {
-                fail!(~"sender closed the connection")
+                fail!("sender closed the connection")
             }
             (pingpong::liberate_pong(packet.unwrap()), ())
         }
@@ -284,7 +284,7 @@ pub mod pingpong {
         pub fn do_ping(c: ping) -> (pong, ()) {
             let packet = ::pipes::recv(c);
             if packet.is_none() {
-                fail!(~"sender closed the connection")
+                fail!("sender closed the connection")
             }
             (pingpong::liberate_ping(packet.unwrap()), ())
         }
diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs
index 206381bcef7..6ec20549963 100644
--- a/src/test/run-pass/nullable-pointer-iotareduction.rs
+++ b/src/test/run-pass/nullable-pointer-iotareduction.rs
@@ -28,7 +28,7 @@ impl<T> E<T> {
     }
     fn get_ref<'r>(&'r self) -> (int, &'r T) {
         match *self {
-            Nothing(*) => fail!(fmt!("E::get_ref(Nothing::<%s>)",  stringify!($T))),
+            Nothing(*) => fail!("E::get_ref(Nothing::<%s>)",  stringify!($T)),
             Thing(x, ref y) => (x, y)
         }
     }
@@ -57,8 +57,8 @@ macro_rules! check_fancy {
         let t_ = Thing::<$T>(23, $e);
         match t_.get_ref() {
             (23, $v) => { $chk }
-            _ => fail!(fmt!("Thing::<%s>(23, %s).get_ref() != (23, _)",
-                            stringify!($T), stringify!($e)))
+            _ => fail!("Thing::<%s>(23, %s).get_ref() != (23, _)",
+                       stringify!($T), stringify!($e))
         }
     }}
 }
diff --git a/src/test/run-pass/option_addition.rs b/src/test/run-pass/option_addition.rs
index 0bd61d1a67d..10b8c92e7d6 100644
--- a/src/test/run-pass/option_addition.rs
+++ b/src/test/run-pass/option_addition.rs
@@ -20,7 +20,7 @@ pub fn main() {
 
     match nope {
         None => (),
-        Some(foo) => fail!(fmt!("expected None, but found %?", foo))
+        Some(foo) => fail!("expected None, but found %?", foo)
     }
     assert!(foo == somefoo.get());
     assert!(bar == somebar.get());
diff --git a/src/test/run-pass/overload-index-operator.rs b/src/test/run-pass/overload-index-operator.rs
index 3030bedcccc..497c17d0459 100644
--- a/src/test/run-pass/overload-index-operator.rs
+++ b/src/test/run-pass/overload-index-operator.rs
@@ -35,7 +35,7 @@ impl<K:Eq,V:Copy> Index<K,V> for AssociationList<K,V> {
                 return copy pair.value;
             }
         }
-        fail!(fmt!("No value found for key: %?", index));
+        fail!("No value found for key: %?", index);
     }
 }
 
@@ -52,4 +52,4 @@ pub fn main() {
 
     assert!(list[foo] == 22)
     assert!(list[bar] == 44)
-}
\ No newline at end of file
+}
diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs
index 5e2be7e6d08..26395e7307f 100644
--- a/src/test/run-pass/pipe-bank-proto.rs
+++ b/src/test/run-pass/pipe-bank-proto.rs
@@ -74,7 +74,7 @@ fn client_follow(bank: bank::client::login) {
     let bank = client::login(bank, ~"theincredibleholk", ~"1234");
     let bank = switch(bank, follow! (
         ok -> connected { connected }
-        invalid -> _next { fail!(~"bank closed the connected") }
+        invalid -> _next { fail!("bank closed the connected") }
     ));
 
     let bank = client::deposit(bank, 100.00);
@@ -84,7 +84,7 @@ fn client_follow(bank: bank::client::login) {
             io::println(~"Yay! I got money!");
         }
         insufficient_funds -> _next {
-            fail!(~"someone stole my money")
+            fail!("someone stole my money")
         }
     ));
 }
@@ -97,8 +97,8 @@ fn bank_client(bank: bank::client::login) {
       Some(ok(connected)) => {
         move_it!(connected)
       }
-      Some(invalid(_)) => { fail!(~"login unsuccessful") }
-      None => { fail!(~"bank closed the connection") }
+      Some(invalid(_)) => { fail!("login unsuccessful") }
+      None => { fail!("bank closed the connection") }
     };
 
     let bank = client::deposit(bank, 100.00);
@@ -108,10 +108,10 @@ fn bank_client(bank: bank::client::login) {
         io::println(~"Yay! I got money!");
       }
       Some(insufficient_funds(_)) => {
-        fail!(~"someone stole my money")
+        fail!("someone stole my money")
       }
       None => {
-        fail!(~"bank closed the connection")
+        fail!("bank closed the connection")
       }
     }
 }
diff --git a/src/test/run-pass/region-return-interior-of-option.rs b/src/test/run-pass/region-return-interior-of-option.rs
index 45090e908bb..8bb069990ee 100644
--- a/src/test/run-pass/region-return-interior-of-option.rs
+++ b/src/test/run-pass/region-return-interior-of-option.rs
@@ -11,7 +11,7 @@
 fn get<'r, T>(opt: &'r Option<T>) -> &'r T {
     match *opt {
       Some(ref v) => v,
-      None => fail!(~"none")
+      None => fail!("none")
     }
 }
 
diff --git a/src/test/run-pass/syntax-extension-bytes.rs b/src/test/run-pass/syntax-extension-bytes.rs
new file mode 100644
index 00000000000..9249267355d
--- /dev/null
+++ b/src/test/run-pass/syntax-extension-bytes.rs
@@ -0,0 +1,16 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let vec = bytes!("abc");
+    assert_eq!(vec[0], 97);
+    assert_eq!(vec[1], 98);
+    assert_eq!(vec[2], 99);
+}
diff --git a/src/test/run-pass/vec-each2_mut.rs b/src/test/run-pass/vec-each2_mut.rs
new file mode 100644
index 00000000000..3c6b7da9f14
--- /dev/null
+++ b/src/test/run-pass/vec-each2_mut.rs
@@ -0,0 +1,38 @@
+// 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.
+
+// -*- rust -*-
+fn main(){
+    let mut t1 = ~[];
+    t1.push('a');
+
+    let mut t2 = ~[];
+    t2.push('b');
+
+    for vec::each2_mut(t1, t2) | i1, i2 | {
+        assert!(*i1 == 'a');
+        assert!(*i2 == 'b');
+    }
+
+    for vec::each2(t1, t2) | i1, i2 | {
+        io::println(fmt!("after t1: %?, t2: %?", i1, i2));
+    }
+
+    for vec::each2_mut(t1, t2) | i1, i2 | {
+        *i1 = 'b';
+        *i2 = 'a';
+        assert!(*i1 == 'b');
+        assert!(*i2 == 'a');
+    }
+
+    for vec::each2(t1, t2) | i1, i2 | {
+        io::println(fmt!("before t1: %?, t2: %?", i1, i2));
+    }
+}
diff --git a/src/test/run-pass/vec-self-append.rs b/src/test/run-pass/vec-self-append.rs
index acd9cf6f01b..7507a78378e 100644
--- a/src/test/run-pass/vec-self-append.rs
+++ b/src/test/run-pass/vec-self-append.rs
@@ -14,7 +14,7 @@ fn test_heap_to_heap() {
     // a spills onto the heap
     let mut a = ~[0, 1, 2, 3, 4];
     a = a + a; // FIXME(#3387)---can't write a += a
-    assert!((vec::len(a) == 10u));
+    assert!(a.len() == 10u);
     assert!((a[0] == 0));
     assert!((a[1] == 1));
     assert!((a[2] == 2));
@@ -32,7 +32,7 @@ fn test_stack_to_heap() {
     let mut a = ~[0, 1, 2];
     // a spills to the heap
     a = a + a; // FIXME(#3387)---can't write a += a
-    assert!((vec::len(a) == 6u));
+    assert!(a.len() == 6u);
     assert!((a[0] == 0));
     assert!((a[1] == 1));
     assert!((a[2] == 2));
@@ -47,8 +47,8 @@ fn test_loop() {
     let mut i = 20;
     let mut expected_len = 1u;
     while i > 0 {
-        error!(vec::len(a));
-        assert!((vec::len(a) == expected_len));
+        error!(a.len());
+        assert!(a.len() == expected_len);
         a = a + a; // FIXME(#3387)---can't write a += a
         i -= 1;
         expected_len *= 2u;
diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs
index 38aa56b6512..f226f315ff9 100644
--- a/src/test/run-pass/weird-exprs.rs
+++ b/src/test/run-pass/weird-exprs.rs
@@ -67,7 +67,7 @@ fn canttouchthis() -> uint {
 fn angrydome() {
     loop { if break { } }
     let mut i = 0;
-    loop { i += 1; if i == 1 { match (loop) { 1 => { }, _ => fail!(~"wat") } }
+    loop { i += 1; if i == 1 { match (loop) { 1 => { }, _ => fail!("wat") } }
       break; }
 }