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.rs2
-rw-r--r--src/compiletest/errors.rs2
-rw-r--r--src/compiletest/runtest.rs11
-rw-r--r--src/etc/pkg/rust.iss3
-rw-r--r--src/etc/zsh/_rust71
-rw-r--r--src/libextra/arc.rs32
-rw-r--r--src/libextra/arena.rs41
-rw-r--r--src/libextra/bitv.rs12
-rw-r--r--src/libextra/c_vec.rs3
-rw-r--r--src/libextra/comm.rs14
-rw-r--r--src/libextra/crypto/digest.rs4
-rw-r--r--src/libextra/crypto/sha2.rs79
-rw-r--r--src/libextra/deque.rs13
-rw-r--r--src/libextra/dlist.rs2
-rw-r--r--src/libextra/ebml.rs42
-rw-r--r--src/libextra/flatpipes.rs24
-rw-r--r--src/libextra/fun_treemap.rs4
-rw-r--r--src/libextra/future.rs4
-rw-r--r--src/libextra/getopts.rs50
-rw-r--r--src/libextra/json.rs22
-rw-r--r--src/libextra/md4.rs9
-rw-r--r--src/libextra/net_tcp.rs24
-rw-r--r--src/libextra/net_url.rs12
-rw-r--r--src/libextra/num/bigint.rs27
-rw-r--r--src/libextra/par.rs10
-rw-r--r--src/libextra/priority_queue.rs6
-rw-r--r--src/libextra/rc.rs20
-rw-r--r--src/libextra/rope.rs4
-rw-r--r--src/libextra/sort.rs33
-rw-r--r--src/libextra/sync.rs29
-rw-r--r--src/libextra/term.rs13
-rw-r--r--src/libextra/terminfo/parm.rs3
-rw-r--r--src/libextra/test.rs249
-rw-r--r--src/libextra/time.rs2
-rw-r--r--src/libextra/timer.rs7
-rw-r--r--src/libextra/treemap.rs15
-rw-r--r--src/libextra/uv_global_loop.rs34
-rw-r--r--src/libextra/uv_ll.rs4
-rw-r--r--src/libextra/workcache.rs12
-rw-r--r--src/librust/rust.rs6
-rw-r--r--src/librustc/back/link.rs44
-rw-r--r--src/librustc/back/passes.rs155
-rw-r--r--src/librustc/back/rpath.rs2
-rw-r--r--src/librustc/driver/driver.rs18
-rw-r--r--src/librustc/driver/session.rs63
-rw-r--r--src/librustc/lib/llvm.rs23
-rw-r--r--src/librustc/metadata/common.rs4
-rw-r--r--src/librustc/metadata/csearch.rs16
-rw-r--r--src/librustc/metadata/decoder.rs330
-rw-r--r--src/librustc/metadata/encoder.rs275
-rw-r--r--src/librustc/metadata/filesearch.rs2
-rw-r--r--src/librustc/metadata/tydecode.rs53
-rw-r--r--src/librustc/metadata/tyencode.rs5
-rw-r--r--src/librustc/middle/astencode.rs59
-rw-r--r--src/librustc/middle/borrowck/doc.rs8
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs23
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs2
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs4
-rw-r--r--src/librustc/middle/borrowck/move_data.rs2
-rw-r--r--src/librustc/middle/dataflow.rs22
-rw-r--r--src/librustc/middle/kind.rs66
-rw-r--r--src/librustc/middle/lang_items.rs28
-rw-r--r--src/librustc/middle/mem_categorization.rs77
-rw-r--r--src/librustc/middle/moves.rs23
-rw-r--r--src/librustc/middle/reachable.rs438
-rw-r--r--src/librustc/middle/resolve.rs275
-rw-r--r--src/librustc/middle/trans/_match.rs14
-rw-r--r--src/librustc/middle/trans/asm.rs13
-rw-r--r--src/librustc/middle/trans/base.rs101
-rw-r--r--src/librustc/middle/trans/build.rs27
-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.rs11
-rw-r--r--src/librustc/middle/trans/callee.rs139
-rw-r--r--src/librustc/middle/trans/closure.rs1
-rw-r--r--src/librustc/middle/trans/common.rs145
-rw-r--r--src/librustc/middle/trans/context.rs21
-rw-r--r--src/librustc/middle/trans/debuginfo.rs255
-rw-r--r--src/librustc/middle/trans/expr.rs5
-rw-r--r--src/librustc/middle/trans/foreign.rs2
-rw-r--r--src/librustc/middle/trans/inline.rs1
-rw-r--r--src/librustc/middle/trans/meth.rs149
-rw-r--r--src/librustc/middle/trans/mod.rs1
-rw-r--r--src/librustc/middle/trans/monomorphize.rs40
-rw-r--r--src/librustc/middle/trans/reachable.rs246
-rw-r--r--src/librustc/middle/ty.rs350
-rw-r--r--src/librustc/middle/typeck/astconv.rs16
-rw-r--r--src/librustc/middle/typeck/check/_match.rs8
-rw-r--r--src/librustc/middle/typeck/check/method.rs22
-rw-r--r--src/librustc/middle/typeck/check/mod.rs76
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs19
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs12
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs49
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs15
-rw-r--r--src/librustc/middle/typeck/coherence.rs163
-rw-r--r--src/librustc/middle/typeck/collect.rs18
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs3
-rw-r--r--src/librustc/middle/typeck/infer/lattice.rs116
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs4
-rw-r--r--src/librustc/middle/typeck/infer/region_inference.rs27
-rw-r--r--src/librustc/middle/typeck/infer/resolve.rs2
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs1
-rw-r--r--src/librustc/middle/typeck/infer/unify.rs95
-rw-r--r--src/librustc/middle/typeck/mod.rs13
-rw-r--r--src/librustc/rustc.rs1
-rw-r--r--src/librustc/util/ppaux.rs12
-rw-r--r--src/librustdoc/astsrv.rs2
-rw-r--r--src/librustdoc/attr_pass.rs2
-rw-r--r--src/librustdoc/markdown_pass.rs10
-rw-r--r--src/librustdoc/markdown_writer.rs4
-rw-r--r--src/librustdoc/page_pass.rs2
-rw-r--r--src/librusti/rusti.rc666
-rw-r--r--src/librusti/rusti.rs7
-rw-r--r--src/librustpkg/package_source.rs5
-rw-r--r--src/librustpkg/path_util.rs34
-rw-r--r--src/librustpkg/rustpkg.rs16
-rw-r--r--src/librustpkg/tests.rs67
-rw-r--r--src/librustpkg/util.rs6
-rw-r--r--src/libstd/cell.rs3
-rw-r--r--src/libstd/char.rs1
-rw-r--r--src/libstd/clone.rs14
-rw-r--r--src/libstd/comm.rs100
-rw-r--r--src/libstd/hash.rs7
-rw-r--r--src/libstd/hashmap.rs5
-rw-r--r--src/libstd/io.rs20
-rw-r--r--src/libstd/iterator.rs7
-rw-r--r--src/libstd/kinds.rs27
-rw-r--r--src/libstd/libc.rs1
-rw-r--r--src/libstd/local_data.rs25
-rw-r--r--src/libstd/num/int_macros.rs3
-rw-r--r--src/libstd/num/num.rs2
-rw-r--r--src/libstd/num/uint_macros.rs3
-rw-r--r--src/libstd/option.rs2
-rw-r--r--src/libstd/os.rs17
-rw-r--r--src/libstd/path.rs89
-rw-r--r--src/libstd/pipes.rs34
-rw-r--r--src/libstd/prelude.rs3
-rw-r--r--src/libstd/rand.rs4
-rw-r--r--src/libstd/rand/distributions.rs3
-rw-r--r--src/libstd/rt/comm.rs10
-rw-r--r--src/libstd/rt/io/extensions.rs11
-rw-r--r--src/libstd/rt/io/mem.rs2
-rw-r--r--src/libstd/rt/message_queue.rs4
-rw-r--r--src/libstd/rt/uv/timer.rs4
-rw-r--r--src/libstd/rt/work_queue.rs4
-rw-r--r--src/libstd/str.rs116
-rw-r--r--src/libstd/task/mod.rs22
-rw-r--r--src/libstd/task/spawn.rs7
-rw-r--r--src/libstd/to_bytes.rs9
-rw-r--r--src/libstd/to_str.rs15
-rw-r--r--src/libstd/trie.rs6
-rw-r--r--src/libstd/unstable/atomics.rs2
-rw-r--r--src/libstd/unstable/extfmt.rs1
-rw-r--r--src/libstd/unstable/global.rs14
-rw-r--r--src/libstd/unstable/sync.rs12
-rw-r--r--src/libstd/util.rs54
-rw-r--r--src/libstd/vec.rs855
-rw-r--r--src/libsyntax/ast.rs272
-rw-r--r--src/libsyntax/ast_util.rs32
-rw-r--r--src/libsyntax/codemap.rs53
-rw-r--r--src/libsyntax/diagnostic.rs30
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/ext/concat_idents.rs3
-rw-r--r--src/libsyntax/ext/deriving/iter_bytes.rs12
-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.rs6
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs57
-rw-r--r--src/libsyntax/opt_vec.rs2
-rw-r--r--src/libsyntax/parse/attr.rs16
-rw-r--r--src/libsyntax/parse/comments.rs6
-rw-r--r--src/libsyntax/parse/common.rs248
-rw-r--r--src/libsyntax/parse/lexer.rs8
-rw-r--r--src/libsyntax/parse/obsolete.rs32
-rw-r--r--src/libsyntax/parse/parser.rs281
-rw-r--r--src/libsyntax/parse/token.rs12
-rw-r--r--src/libsyntax/print/pp.rs8
-rw-r--r--src/libsyntax/util/interner.rs2
-rw-r--r--src/test/auxiliary/cci_capture_clause.rs2
-rw-r--r--src/test/auxiliary/issue-2526.rs6
-rw-r--r--src/test/bench/core-std.rs7
-rw-r--r--src/test/bench/noise.rs8
-rw-r--r--src/test/bench/pingpong.rs6
-rw-r--r--src/test/bench/shootout-chameneos-redux.rs4
-rw-r--r--src/test/bench/shootout-fasta-redux.rs2
-rw-r--r--src/test/bench/shootout-fasta.rs2
-rw-r--r--src/test/bench/shootout-k-nucleotide-pipes.rs8
-rw-r--r--src/test/bench/shootout-k-nucleotide.rs10
-rw-r--r--src/test/bench/shootout-mandelbrot.rs5
-rw-r--r--src/test/bench/shootout-pfib.rs3
-rw-r--r--src/test/bench/shootout-reverse-complement.rs7
-rw-r--r--src/test/bench/shootout-threadring.rs4
-rw-r--r--src/test/bench/sudoku.rs4
-rw-r--r--src/test/compile-fail/closure-bounds-subtype.rs18
-rw-r--r--src/test/compile-fail/impl-bounds-checking.rs24
-rw-r--r--src/test/compile-fail/impl-duplicate-methods.rs2
-rw-r--r--src/test/compile-fail/issue-2149.rs2
-rw-r--r--src/test/compile-fail/issue-2611-4.rs2
-rw-r--r--src/test/compile-fail/issue-2766-a.rs6
-rw-r--r--src/test/compile-fail/issue-3177-mutable-struct.rs2
-rw-r--r--src/test/compile-fail/kindck-destructor-owned.rs2
-rw-r--r--src/test/compile-fail/kindck-nonsendable-1.rs6
-rw-r--r--src/test/compile-fail/kindck-owned.rs2
-rw-r--r--src/test/compile-fail/liveness-use-after-send.rs2
-rw-r--r--src/test/compile-fail/mutable-enum.rs6
-rw-r--r--src/test/compile-fail/mutable-struct.rs6
-rw-r--r--src/test/compile-fail/no-send-res-ports.rs2
-rw-r--r--src/test/compile-fail/non_owned-enum.rs6
-rw-r--r--src/test/compile-fail/non_owned-struct.rs6
-rw-r--r--src/test/compile-fail/once-cant-call-twice-on-heap.rs29
-rw-r--r--src/test/compile-fail/once-cant-call-twice-on-stack.rs30
-rw-r--r--src/test/compile-fail/once-cant-copy-stack-once-fn-copy.rs20
-rw-r--r--src/test/compile-fail/once-cant-move-out-of-non-once-on-heap.rs29
-rw-r--r--src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs29
-rw-r--r--src/test/compile-fail/rcmut-not-const-and-not-owned.rs8
-rw-r--r--src/test/compile-fail/regions-creating-enums.rs4
-rw-r--r--src/test/compile-fail/the-case-of-the-recurring-closure-2.rs44
-rw-r--r--src/test/compile-fail/the-case-of-the-recurring-closure.rs44
-rw-r--r--src/test/compile-fail/trait-bounds-cant-coerce.rs8
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-bare-trait.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-struct.rs2
-rw-r--r--src/test/compile-fail/trait-bounds-sugar.rs10
-rw-r--r--src/test/compile-fail/trait-duplicate-methods.rs2
-rw-r--r--src/test/compile-fail/trait-or-new-type-instead.rs2
-rw-r--r--src/test/compile-fail/unique-unique-kind.rs4
-rw-r--r--src/test/compile-fail/unsendable-class.rs4
-rw-r--r--src/test/debug-info/basic-types.rs8
-rw-r--r--src/test/debug-info/destructured-local.rs (renamed from src/test/debug-info/tuple.rs)23
-rw-r--r--src/test/debug-info/function-arguments.rs51
-rw-r--r--src/test/debug-info/reference-to-basic.rs116
-rw-r--r--src/test/debug-info/reference-to-managed-basic.rs114
-rw-r--r--src/test/debug-info/reference-to-struct.rs78
-rw-r--r--src/test/debug-info/reference-to-tuple.rs47
-rw-r--r--src/test/debug-info/reference-to-unique-basic.rs115
-rw-r--r--src/test/debug-info/simple-struct.rs84
-rw-r--r--src/test/debug-info/simple-tuple.rs51
-rw-r--r--src/test/debug-info/struct-in-struct.rs145
-rw-r--r--src/test/debug-info/struct-with-destructor.rs88
-rw-r--r--src/test/debug-info/tuple-in-struct.rs151
-rw-r--r--src/test/debug-info/tuple-in-tuple.rs50
-rw-r--r--src/test/debug-info/variable-scope.rs (renamed from src/test/debug-info/struct.rs)48
-rw-r--r--src/test/run-fail/bug-811.rs2
-rw-r--r--src/test/run-fail/issue-3029.rs4
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-2.rs2
-rw-r--r--src/test/run-pass/attr-no-drop-flag-size.rs2
-rw-r--r--src/test/run-pass/bug-7183-generics.rs45
-rw-r--r--src/test/run-pass/closure-bounds-can-capture-chan.rs2
-rw-r--r--src/test/run-pass/const-bound.rs2
-rw-r--r--src/test/run-pass/fixed-point-bind-unique.rs4
-rw-r--r--src/test/run-pass/fn-bare-spawn.rs2
-rw-r--r--src/test/run-pass/generic-alias-unique.rs2
-rw-r--r--src/test/run-pass/issue-2611-3.rs2
-rw-r--r--src/test/run-pass/issue-2718.rs24
-rw-r--r--src/test/run-pass/issue-2834.rs2
-rw-r--r--src/test/run-pass/issue-2930.rs2
-rw-r--r--src/test/run-pass/issue-3888-2.rs6
-rw-r--r--src/test/run-pass/issue-5321-immediates-with-bare-self.rs25
-rw-r--r--src/test/run-pass/istr.rs8
-rw-r--r--src/test/run-pass/let-destruct-fresh-mem.rs4
-rw-r--r--src/test/run-pass/liveness-move-in-loop.rs2
-rw-r--r--src/test/run-pass/match-join.rs2
-rw-r--r--src/test/run-pass/monad.rs4
-rw-r--r--src/test/run-pass/mutable-alias-vec.rs4
-rw-r--r--src/test/run-pass/once-move-out-on-heap.rs29
-rw-r--r--src/test/run-pass/once-move-out-on-stack.rs30
-rw-r--r--src/test/run-pass/operator-overloading.rs2
-rw-r--r--src/test/run-pass/pipe-bank-proto.rs4
-rw-r--r--src/test/run-pass/pipe-peek.rs4
-rw-r--r--src/test/run-pass/pipe-select.rs4
-rw-r--r--src/test/run-pass/pipe-sleep.rs2
-rw-r--r--src/test/run-pass/send-type-inference.rs2
-rw-r--r--src/test/run-pass/shadow.rs2
-rw-r--r--src/test/run-pass/static-impl.rs4
-rw-r--r--src/test/run-pass/str-append.rs2
-rw-r--r--src/test/run-pass/str-growth.rs6
-rw-r--r--src/test/run-pass/trait-bounds-basic.rs6
-rw-r--r--src/test/run-pass/trait-bounds-in-arc.rs16
-rw-r--r--src/test/run-pass/trait-default-method-xc.rs8
-rw-r--r--src/test/run-pass/trait-generic.rs2
-rw-r--r--src/test/run-pass/trait-with-bounds-default.rs41
-rw-r--r--src/test/run-pass/type-param-constraints.rs2
-rw-r--r--src/test/run-pass/unfoldr-cross-crate.rs2
-rw-r--r--src/test/run-pass/uniq-cc-generic.rs2
-rw-r--r--src/test/run-pass/unique-kinds.rs4
-rw-r--r--src/test/run-pass/vec-growth.rs8
-rw-r--r--src/test/run-pass/vec-slice.rs4
-rw-r--r--src/test/run-pass/while-prelude-drop.rs2
287 files changed, 6791 insertions, 3758 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index 683d5fecc34..d858003c353 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -75,7 +75,7 @@ pub fn parse_config(args: ~[~str]) -> config {
          ];
 
     assert!(!args.is_empty());
-    let args_ = vec::tail(args);
+    let args_ = args.tail();
     let matches =
         &match getopts::getopts(args_, opts) {
           Ok(m) => m,
diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs
index cdc0defcbca..4649d4dfc3c 100644
--- a/src/compiletest/errors.rs
+++ b/src/compiletest/errors.rs
@@ -21,7 +21,7 @@ pub fn load_errors(testfile: &Path) -> ~[ExpectedError] {
     let mut line_num = 1u;
     while !rdr.eof() {
         let ln = rdr.read_line();
-        error_patterns += parse_expected(line_num, ln);
+        error_patterns.push_all_move(parse_expected(line_num, ln));
         line_num += 1u;
     }
     return error_patterns;
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 3e2f484ee53..0e04be34c79 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -226,8 +226,8 @@ actual:\n\
                          ~"-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);
+        args.push_all_move(split_maybe_args(&config.rustcflags));
+        args.push_all_move(split_maybe_args(&props.compile_flags));
         return ProcArgs {prog: config.rustc_path.to_str(), args: args};
     }
 }
@@ -321,8 +321,7 @@ fn check_error_patterns(props: &TestProps,
     if done { return; }
 
     let missing_patterns =
-        vec::slice(props.error_patterns, next_err_idx,
-                   props.error_patterns.len());
+        props.error_patterns.slice(next_err_idx, props.error_patterns.len());
     if missing_patterns.len() == 1u {
         fatal_ProcRes(fmt!("error pattern '%s' not found!",
                            missing_patterns[0]), ProcRes);
@@ -582,8 +581,8 @@ fn make_compile_args(config: &config, props: &TestProps, extras: ~[~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);
+    args.push_all_move(split_maybe_args(&config.rustcflags));
+    args.push_all_move(split_maybe_args(&props.compile_flags));
     return ProcArgs {prog: config.rustc_path.to_str(), args: args};
 }
 
diff --git a/src/etc/pkg/rust.iss b/src/etc/pkg/rust.iss
index 18f358a9893..0375a041a39 100644
--- a/src/etc/pkg/rust.iss
+++ b/src/etc/pkg/rust.iss
@@ -1,4 +1,5 @@
 #define CFG_VERSION GetEnv("CFG_VERSION")
+#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
 
 [Setup]
 
@@ -8,7 +9,7 @@ AppVersion={#CFG_VERSION}
 AppCopyright=Copyright (C) 2006-2013 Mozilla Foundation, MIT license
 AppPublisher=Mozilla Foundation
 AppPublisherURL=http://www.rust-lang.org
-VersionInfoVersion={#CFG_VERSION}
+VersionInfoVersion={#CFG_VERSION_WIN}
 LicenseFile=LICENSE.txt
 
 DisableWelcomePage=true
diff --git a/src/etc/zsh/_rust b/src/etc/zsh/_rust
index faa21a29616..86dcbab93fd 100644
--- a/src/etc/zsh/_rust
+++ b/src/etc/zsh/_rust
@@ -29,36 +29,30 @@ _rustc_opts_switches=(
     --target'[Target triple cpu-manufacturer-kernel\[-os\] to compile]'
     --target-feature'[Target specific attributes (llc -mattr=help for detail)]'
     --android-cross-path'[The path to the Android NDK]'
-    {-W,--warn}'[Set lint warnings]'
-    {-A,--allow}'[Set lint allowed]'
-    {-D,--deny}'[Set lint denied]'
-    {-F,--forbid}'[Set lint forbidden]'
-    -Z'[Set internal debugging options]'
     {-v,--version}'[Print version info and exit]'
 )
-
 _rustc_opts_lint=(
-    'path-statement:path statements with no effect'
-    'deprecated-pattern:warn about deprecated uses of pattern bindings'
-    'non-implicitly-copyable-typarams:passing non implicitly copyable types as copy type params'
-    'missing-trait-doc:detects missing documentation for traits'
-    'missing-struct-doc:detects missing documentation for structs'
-    'ctypes:proper use of core::libc types in foreign modules'
-    'implicit-copies:implicit copies of non implicitly copyable data'
-    "unused-mut:detect mut variables which don't need to be mutable"
-    'unused-imports:imports that are never used'
-    'heap-memory:use of any (~ type or @ type) heap memory'
-    'default-methods:allow default methods'
-    'unused-variable:detect variables which are not used in any way'
-    'dead-assignment:detect assignments that will never be read'
-    'unrecognized-lint:unrecognized lint attribute'
-    'type-limits:comparisons made useless by limits of the types involved'
-    'unused-unsafe:unnecessary use of an `unsafe` block'
-    'while-true:suggest using loop { } instead of while(true) { }'
-    'non-camel-case-types:types, variants and traits should have camel case names'
-    'managed-heap-memory:use of managed (@ type) heap memory'
-    'unnecessary-allocation:detects unnecessary allocations that can be eliminated'
-    'owned-heap-memory:use of owned (~ type) heap memory'
+    'path-statement[path statements with no effect]'
+    'deprecated-pattern[warn about deprecated uses of pattern bindings]'
+    'non-implicitly-copyable-typarams[passing non implicitly copyable types as copy type params]'
+    'missing-trait-doc[detects missing documentation for traits]'
+    'missing-struct-doc[detects missing documentation for structs]'
+    'ctypes[proper use of core::libc types in foreign modules]'
+    'implicit-copies[implicit copies of non implicitly copyable data]'
+    "unused-mut[detect mut variables which don't need to be mutable]"
+    'unused-imports[imports that are never used]'
+    'heap-memory[use of any (~ type or @ type) heap memory]'
+    'default-methods[allow default methods]'
+    'unused-variable[detect variables which are not used in any way]'
+    'dead-assignment[detect assignments that will never be read]'
+    'unrecognized-lint[unrecognized lint attribute]'
+    'type-limits[comparisons made useless by limits of the types involved]'
+    'unused-unsafe[unnecessary use of an `unsafe` block]'
+    'while-true[suggest using loop { } instead of while(true) { }]'
+    'non-camel-case-types[types, variants and traits should have camel case names]'
+    'managed-heap-memory[use of managed (@ type) heap memory]'
+    'unnecessary-allocation[detects unnecessary allocations that can be eliminated]'
+    'owned-heap-memory[use of owned (~ type) heap memory]'
 )
 
 _rustc_opts_debug=(
@@ -90,13 +84,20 @@ _rustc_opts_debug=(
     'lint-llvm:Run the LLVM lint pass on the pre-optimization IR'
 )
 
-_rustc() {
-    case $words[2] in
-        -[WADF]) _describe 'options' _rustc_opts_lint ;;
-        -Z) _describe 'options' _rustc_opts_debug ;;
-        -)  _arguments -s -w : "$_rustc_opts_switches[@]" ;;
-        *) _files -g "*.rs" ;;
-  esac
+_rustc_opts_fun_lint(){
+    _values -s , 'options' \
+        "$_rustc_opts_lint[@]"
+}
+
+_rustc_opts_fun_debug(){
+    _describe 'options' _rustc_opts_debug
 }
 
-_rustc "$@"
+_arguments -s :  \
+    '(-W --warn)'{-W,--warn}'[Set lint warnings]:lint options:_rustc_opts_fun_lint' \
+    '(-A --allow)'{-A,--allow}'[Set lint allowed]:lint options:_rustc_opts_fun_lint' \
+    '(-D --deny)'{-D,--deny}'[Set lint denied]:lint options:_rustc_opts_fun_lint' \
+    '(-F --forbid)'{-F,--forbid}'[Set lint forbidden]:lint options:_rustc_opts_fun_lint' \
+    '*-Z[Set internal debugging options]:debug options:_rustc_opts_fun_debug' \
+    "$_rustc_opts_switches[@]" \
+    '*::files:_files -g "*.rs"'
diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs
index c04ee63880e..30067c92300 100644
--- a/src/libextra/arc.rs
+++ b/src/libextra/arc.rs
@@ -112,7 +112,7 @@ impl<'self> Condvar<'self> {
 pub struct ARC<T> { x: UnsafeAtomicRcBox<T> }
 
 /// Create an atomically reference counted wrapper.
-pub fn ARC<T:Const + Owned>(data: T) -> ARC<T> {
+pub fn ARC<T:Freeze + Send>(data: T) -> ARC<T> {
     ARC { x: UnsafeAtomicRcBox::new(data) }
 }
 
@@ -120,7 +120,7 @@ pub fn ARC<T:Const + Owned>(data: T) -> ARC<T> {
  * Access the underlying data in an atomically reference counted
  * wrapper.
  */
-impl<T:Const+Owned> ARC<T> {
+impl<T:Freeze+Send> ARC<T> {
     pub fn get<'a>(&'a self) -> &'a T {
         unsafe { &*self.x.get_immut() }
     }
@@ -133,7 +133,7 @@ impl<T:Const+Owned> ARC<T> {
  * object. However, one of the `arc` objects can be sent to another task,
  * allowing them to share the underlying data.
  */
-impl<T:Const + Owned> Clone for ARC<T> {
+impl<T:Freeze + Send> Clone for ARC<T> {
     fn clone(&self) -> ARC<T> {
         ARC { x: self.x.clone() }
     }
@@ -149,14 +149,14 @@ struct MutexARCInner<T> { lock: Mutex, failed: bool, data: 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> {
+pub fn MutexARC<T:Send>(user_data: T) -> MutexARC<T> {
     mutex_arc_with_condvars(user_data, 1)
 }
 /**
  * Create a mutex-protected ARC with the supplied data and a specified number
  * of condvars (as sync::mutex_with_condvars).
  */
-pub fn mutex_arc_with_condvars<T:Owned>(user_data: T,
+pub fn mutex_arc_with_condvars<T:Send>(user_data: T,
                                     num_condvars: uint) -> MutexARC<T> {
     let data =
         MutexARCInner { lock: mutex_with_condvars(num_condvars),
@@ -164,7 +164,7 @@ pub fn mutex_arc_with_condvars<T:Owned>(user_data: T,
     MutexARC { x: UnsafeAtomicRcBox::new(data) }
 }
 
-impl<T:Owned> Clone for MutexARC<T> {
+impl<T:Send> Clone for MutexARC<T> {
     /// Duplicate a mutex-protected ARC, as arc::clone.
     fn clone(&self) -> MutexARC<T> {
         // NB: Cloning the underlying mutex is not necessary. Its reference
@@ -173,7 +173,7 @@ impl<T:Owned> Clone for MutexARC<T> {
     }
 }
 
-impl<T:Owned> MutexARC<T> {
+impl<T:Send> MutexARC<T> {
 
     /**
      * Access the underlying mutable data with mutual exclusion from other
@@ -276,20 +276,21 @@ struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
  *
  * Unlike mutex_arcs, rw_arcs are safe, because they cannot be nested.
  */
-#[mutable]
+#[mutable] // XXX remove after snap
+#[no_freeze]
 struct RWARC<T> {
     x: UnsafeAtomicRcBox<RWARCInner<T>>,
 }
 
 /// Create a reader/writer ARC with the supplied data.
-pub fn RWARC<T:Const + Owned>(user_data: T) -> RWARC<T> {
+pub fn RWARC<T:Freeze + Send>(user_data: T) -> RWARC<T> {
     rw_arc_with_condvars(user_data, 1)
 }
 /**
  * Create a reader/writer ARC with the supplied data and a specified number
  * of condvars (as sync::rwlock_with_condvars).
  */
-pub fn rw_arc_with_condvars<T:Const + Owned>(
+pub fn rw_arc_with_condvars<T:Freeze + Send>(
     user_data: T,
     num_condvars: uint) -> RWARC<T>
 {
@@ -299,7 +300,7 @@ pub fn rw_arc_with_condvars<T:Const + Owned>(
     RWARC { x: UnsafeAtomicRcBox::new(data), }
 }
 
-impl<T:Const + Owned> RWARC<T> {
+impl<T:Freeze + Send> RWARC<T> {
     /// Duplicate a rwlock-protected ARC, as arc::clone.
     pub fn clone(&self) -> RWARC<T> {
         RWARC {
@@ -309,7 +310,7 @@ impl<T:Const + Owned> RWARC<T> {
 
 }
 
-impl<T:Const + Owned> RWARC<T> {
+impl<T:Freeze + Send> RWARC<T> {
     /**
      * Access the underlying data mutably. Locks the rwlock in write mode;
      * other readers and writers will block.
@@ -435,7 +436,7 @@ impl<T:Const + Owned> RWARC<T> {
 // lock it. This wraps the unsafety, with the justification that the 'lock'
 // field is never overwritten; only 'failed' and 'data'.
 #[doc(hidden)]
-fn borrow_rwlock<T:Const + Owned>(state: *const RWARCInner<T>) -> *RWlock {
+fn borrow_rwlock<T:Freeze + Send>(state: *const RWARCInner<T>) -> *RWlock {
     unsafe { cast::transmute(&const (*state).lock) }
 }
 
@@ -452,7 +453,7 @@ pub struct RWReadMode<'self, T> {
     token: sync::RWlockReadMode<'self>,
 }
 
-impl<'self, T:Const + Owned> RWWriteMode<'self, T> {
+impl<'self, T:Freeze + Send> RWWriteMode<'self, T> {
     /// Access the pre-downgrade RWARC in write mode.
     pub fn write<U>(&mut self, blk: &fn(x: &mut T) -> U) -> U {
         match *self {
@@ -493,7 +494,7 @@ impl<'self, T:Const + Owned> RWWriteMode<'self, T> {
     }
 }
 
-impl<'self, T:Const + Owned> RWReadMode<'self, T> {
+impl<'self, T:Freeze + Send> RWReadMode<'self, T> {
     /// Access the post-downgrade rwlock in read mode.
     pub fn read<U>(&self, blk: &fn(x: &T) -> U) -> U {
         match *self {
@@ -517,7 +518,6 @@ mod tests {
 
     use arc::*;
 
-    use core::vec;
     use core::cell::Cell;
     use core::comm;
     use core::task;
diff --git a/src/libextra/arena.rs b/src/libextra/arena.rs
index 604d9ba7373..2c6e7a30448 100644
--- a/src/libextra/arena.rs
+++ b/src/libextra/arena.rs
@@ -65,7 +65,8 @@ struct Chunk {
     is_pod: bool,
 }
 
-#[mutable]
+#[mutable] // XXX remove after snap
+#[no_freeze]
 pub struct Arena {
     // The head is separated out from the list as a unbenchmarked
     // microoptimization, to avoid needing to case on the list to
@@ -186,20 +187,18 @@ impl Arena {
     #[inline]
     fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 {
         unsafe {
-            // XXX: Borrow check
-            let head = transmute_mut_region(&mut self.pod_head);
-
-            let start = round_up_to(head.fill, align);
+            let this = transmute_mut_region(self);
+            let start = round_up_to(this.pod_head.fill, align);
             let end = start + n_bytes;
-            if end > at_vec::capacity(head.data) {
-                return self.alloc_pod_grow(n_bytes, align);
+            if end > at_vec::capacity(this.pod_head.data) {
+                return this.alloc_pod_grow(n_bytes, align);
             }
-            head.fill = end;
+            this.pod_head.fill = end;
 
             //debug!("idx = %u, size = %u, align = %u, fill = %u",
             //       start, n_bytes, align, head.fill);
 
-            ptr::offset(vec::raw::to_ptr(head.data), start)
+            ptr::offset(vec::raw::to_ptr(this.pod_head.data), start)
         }
     }
 
@@ -231,21 +230,31 @@ impl Arena {
     fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint)
                           -> (*u8, *u8) {
         unsafe {
-            let head = transmute_mut_region(&mut self.head);
+            let start;
+            let end;
+            let tydesc_start;
+            let after_tydesc;
+
+            {
+                let head = transmute_mut_region(&mut self.head);
+
+                tydesc_start = head.fill;
+                after_tydesc = head.fill + sys::size_of::<*TyDesc>();
+                start = round_up_to(after_tydesc, align);
+                end = start + n_bytes;
+            }
 
-            let tydesc_start = head.fill;
-            let after_tydesc = head.fill + sys::size_of::<*TyDesc>();
-            let start = round_up_to(after_tydesc, align);
-            let end = start + n_bytes;
-            if end > at_vec::capacity(head.data) {
+            if end > at_vec::capacity(self.head.data) {
                 return self.alloc_nonpod_grow(n_bytes, align);
             }
+
+            let head = transmute_mut_region(&mut self.head);
             head.fill = round_up_to(end, sys::pref_align_of::<*TyDesc>());
 
             //debug!("idx = %u, size = %u, align = %u, fill = %u",
             //       start, n_bytes, align, head.fill);
 
-            let buf = vec::raw::to_ptr(head.data);
+            let buf = vec::raw::to_ptr(self.head.data);
             return (ptr::offset(buf, tydesc_start), ptr::offset(buf, start));
         }
     }
diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs
index 6e4507d4277..4fe7761bf18 100644
--- a/src/libextra/bitv.rs
+++ b/src/libextra/bitv.rs
@@ -476,9 +476,15 @@ impl Bitv {
      * character is either '0' or '1'.
      */
      pub fn to_str(&self) -> ~str {
-       let mut rs = ~"";
-       for self.each() |i| { if i { rs += "1"; } else { rs += "0"; } };
-       rs
+        let mut rs = ~"";
+        for self.each() |i| {
+            if i {
+                rs.push_char('1');
+            } else {
+                rs.push_char('0');
+            }
+        };
+        rs
      }
 
 
diff --git a/src/libextra/c_vec.rs b/src/libextra/c_vec.rs
index 84593630cab..79ef5bf2b7e 100644
--- a/src/libextra/c_vec.rs
+++ b/src/libextra/c_vec.rs
@@ -159,8 +159,7 @@ mod tests {
 
             assert!(mem as int != 0);
 
-            return c_vec_with_dtor(mem as *mut u8, n as uint,
-                                   || unsafe { free(mem) });
+            c_vec_with_dtor(mem as *mut u8, n as uint, || free(mem))
         }
     }
 
diff --git a/src/libextra/comm.rs b/src/libextra/comm.rs
index 1001d4f6ac9..2cb2128db5f 100644
--- a/src/libextra/comm.rs
+++ b/src/libextra/comm.rs
@@ -30,7 +30,7 @@ pub struct DuplexStream<T, U> {
 }
 
 // Allow these methods to be used without import:
-impl<T:Owned,U:Owned> DuplexStream<T, U> {
+impl<T:Send,U:Send> DuplexStream<T, U> {
     pub fn send(&self, x: T) {
         self.chan.send(x)
     }
@@ -48,19 +48,19 @@ impl<T:Owned,U:Owned> DuplexStream<T, U> {
     }
 }
 
-impl<T:Owned,U:Owned> GenericChan<T> for DuplexStream<T, U> {
+impl<T:Send,U:Send> GenericChan<T> for DuplexStream<T, U> {
     fn send(&self, x: T) {
         self.chan.send(x)
     }
 }
 
-impl<T:Owned,U:Owned> GenericSmartChan<T> for DuplexStream<T, U> {
+impl<T:Send,U:Send> GenericSmartChan<T> for DuplexStream<T, U> {
     fn try_send(&self, x: T) -> bool {
         self.chan.try_send(x)
     }
 }
 
-impl<T:Owned,U:Owned> GenericPort<U> for DuplexStream<T, U> {
+impl<T:Send,U:Send> GenericPort<U> for DuplexStream<T, U> {
     fn recv(&self) -> U {
         self.port.recv()
     }
@@ -70,20 +70,20 @@ impl<T:Owned,U:Owned> GenericPort<U> for DuplexStream<T, U> {
     }
 }
 
-impl<T:Owned,U:Owned> Peekable<U> for DuplexStream<T, U> {
+impl<T:Send,U:Send> Peekable<U> for DuplexStream<T, U> {
     fn peek(&self) -> bool {
         self.port.peek()
     }
 }
 
-impl<T:Owned,U:Owned> Selectable for DuplexStream<T, U> {
+impl<T:Send,U:Send> Selectable for DuplexStream<T, U> {
     fn header(&mut self) -> *mut pipes::PacketHeader {
         self.port.header()
     }
 }
 
 /// Creates a bidirectional stream.
-pub fn DuplexStream<T:Owned,U:Owned>()
+pub fn DuplexStream<T:Send,U:Send>()
     -> (DuplexStream<T, U>, DuplexStream<U, T>)
 {
     let (p1, c2) = comm::stream();
diff --git a/src/libextra/crypto/digest.rs b/src/libextra/crypto/digest.rs
index 8fd44bfc9ab..c4fb03a7a7d 100644
--- a/src/libextra/crypto/digest.rs
+++ b/src/libextra/crypto/digest.rs
@@ -49,9 +49,9 @@ fn to_hex(rr: &[u8]) -> ~str {
     for rr.iter().advance() |b| {
         let hex = uint::to_str_radix(*b as uint, 16u);
         if hex.len() == 1 {
-            s += "0";
+            s.push_char('0');
         }
-        s += hex;
+        s.push_str(hex);
     }
     return s;
 }
diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs
index dd179fde70f..e9c6ac72212 100644
--- a/src/libextra/crypto/sha2.rs
+++ b/src/libextra/crypto/sha2.rs
@@ -11,7 +11,6 @@
 use core::prelude::*;
 
 use core::uint;
-use core::vec;
 
 use digest::Digest;
 
@@ -118,7 +117,7 @@ impl Engine512 {
         }
 
         while in.len() - i >= 8 {
-            let w = to_u64(vec::slice(in, i, i + 8));
+            let w = to_u64(in.slice(i, i + 8));
             self.process_word(w);
             self.bit_counter.add_bytes(8);
             i += 8;
@@ -274,43 +273,43 @@ impl Engine512 {
     fn result_512(&mut self, out: &mut [u8]) {
         self.finish();
 
-        from_u64(self.H0, vec::mut_slice(out, 0, 8));
-        from_u64(self.H1, vec::mut_slice(out, 8, 16));
-        from_u64(self.H2, vec::mut_slice(out, 16, 24));
-        from_u64(self.H3, vec::mut_slice(out, 24, 32));
-        from_u64(self.H4, vec::mut_slice(out, 32, 40));
-        from_u64(self.H5, vec::mut_slice(out, 40, 48));
-        from_u64(self.H6, vec::mut_slice(out, 48, 56));
-        from_u64(self.H7, vec::mut_slice(out, 56, 64));
+        from_u64(self.H0, out.mut_slice(0, 8));
+        from_u64(self.H1, out.mut_slice(8, 16));
+        from_u64(self.H2, out.mut_slice(16, 24));
+        from_u64(self.H3, out.mut_slice(24, 32));
+        from_u64(self.H4, out.mut_slice(32, 40));
+        from_u64(self.H5, out.mut_slice(40, 48));
+        from_u64(self.H6, out.mut_slice(48, 56));
+        from_u64(self.H7, out.mut_slice(56, 64));
     }
 
     fn result_384(&mut self, out: &mut [u8]) {
         self.finish();
 
-        from_u64(self.H0, vec::mut_slice(out, 0, 8));
-        from_u64(self.H1, vec::mut_slice(out, 8, 16));
-        from_u64(self.H2, vec::mut_slice(out, 16, 24));
-        from_u64(self.H3, vec::mut_slice(out, 24, 32));
-        from_u64(self.H4, vec::mut_slice(out, 32, 40));
-        from_u64(self.H5, vec::mut_slice(out, 40, 48));
+        from_u64(self.H0, out.mut_slice(0, 8));
+        from_u64(self.H1, out.mut_slice(8, 16));
+        from_u64(self.H2, out.mut_slice(16, 24));
+        from_u64(self.H3, out.mut_slice(24, 32));
+        from_u64(self.H4, out.mut_slice(32, 40));
+        from_u64(self.H5, out.mut_slice(40, 48));
     }
 
     fn result_256(&mut self, out: &mut [u8]) {
         self.finish();
 
-        from_u64(self.H0, vec::mut_slice(out, 0, 8));
-        from_u64(self.H1, vec::mut_slice(out, 8, 16));
-        from_u64(self.H2, vec::mut_slice(out, 16, 24));
-        from_u64(self.H3, vec::mut_slice(out, 24, 32));
+        from_u64(self.H0, out.mut_slice(0, 8));
+        from_u64(self.H1, out.mut_slice(8, 16));
+        from_u64(self.H2, out.mut_slice(16, 24));
+        from_u64(self.H3, out.mut_slice(24, 32));
     }
 
     fn result_224(&mut self, out: &mut [u8]) {
         self.finish();
 
-        from_u64(self.H0, vec::mut_slice(out, 0, 8));
-        from_u64(self.H1, vec::mut_slice(out, 8, 16));
-        from_u64(self.H2, vec::mut_slice(out, 16, 24));
-        from_u32((self.H3 >> 32) as u32, vec::mut_slice(out, 24, 28));
+        from_u64(self.H0, out.mut_slice(0, 8));
+        from_u64(self.H1, out.mut_slice(8, 16));
+        from_u64(self.H2, out.mut_slice(16, 24));
+        from_u32((self.H3 >> 32) as u32, out.mut_slice(24, 28));
     }
 }
 
@@ -400,7 +399,7 @@ impl Engine256 {
         }
 
         while in.len() - i >= 4 {
-            let w = to_u32(vec::slice(in, i, i + 4));
+            let w = to_u32(in.slice(i, i + 4));
             self.process_word(w);
             self.length_bytes += 4;
             i += 4;
@@ -556,26 +555,26 @@ impl Engine256 {
     fn result_256(&mut self, out: &mut [u8]) {
         self.finish();
 
-        from_u32(self.H0, vec::mut_slice(out, 0, 4));
-        from_u32(self.H1, vec::mut_slice(out, 4, 8));
-        from_u32(self.H2, vec::mut_slice(out, 8, 12));
-        from_u32(self.H3, vec::mut_slice(out, 12, 16));
-        from_u32(self.H4, vec::mut_slice(out, 16, 20));
-        from_u32(self.H5, vec::mut_slice(out, 20, 24));
-        from_u32(self.H6, vec::mut_slice(out, 24, 28));
-        from_u32(self.H7, vec::mut_slice(out, 28, 32));
+        from_u32(self.H0, out.mut_slice(0, 4));
+        from_u32(self.H1, out.mut_slice(4, 8));
+        from_u32(self.H2, out.mut_slice(8, 12));
+        from_u32(self.H3, out.mut_slice(12, 16));
+        from_u32(self.H4, out.mut_slice(16, 20));
+        from_u32(self.H5, out.mut_slice(20, 24));
+        from_u32(self.H6, out.mut_slice(24, 28));
+        from_u32(self.H7, out.mut_slice(28, 32));
     }
 
     fn result_224(&mut self, out: &mut [u8]) {
         self.finish();
 
-        from_u32(self.H0, vec::mut_slice(out, 0, 4));
-        from_u32(self.H1, vec::mut_slice(out, 4, 8));
-        from_u32(self.H2, vec::mut_slice(out, 8, 12));
-        from_u32(self.H3, vec::mut_slice(out, 12, 16));
-        from_u32(self.H4, vec::mut_slice(out, 16, 20));
-        from_u32(self.H5, vec::mut_slice(out, 20, 24));
-        from_u32(self.H6, vec::mut_slice(out, 24, 28));
+        from_u32(self.H0, out.mut_slice(0, 4));
+        from_u32(self.H1, out.mut_slice(4, 8));
+        from_u32(self.H2, out.mut_slice(8, 12));
+        from_u32(self.H3, out.mut_slice(12, 16));
+        from_u32(self.H4, out.mut_slice(16, 20));
+        from_u32(self.H5, out.mut_slice(20, 24));
+        from_u32(self.H6, out.mut_slice(24, 28));
     }
 }
 
diff --git a/src/libextra/deque.rs b/src/libextra/deque.rs
index e6a7dd64837..c70c87b6ea1 100644
--- a/src/libextra/deque.rs
+++ b/src/libextra/deque.rs
@@ -137,7 +137,7 @@ impl<T> Deque<T> {
     ///
     /// * n - The number of elements to reserve space for
     pub fn reserve(&mut self, n: uint) {
-        vec::reserve(&mut self.elts, n);
+        self.elts.reserve(n);
     }
 
     /// Reserve capacity for at least `n` elements in the given deque,
@@ -151,7 +151,7 @@ impl<T> Deque<T> {
     ///
     /// * n - The number of elements to reserve space for
     pub fn reserve_at_least(&mut self, n: uint) {
-        vec::reserve_at_least(&mut self.elts, n);
+        self.elts.reserve_at_least(n);
     }
 
     /// Front-to-back iterator.
@@ -256,7 +256,6 @@ mod tests {
     use super::*;
     use core::cmp::Eq;
     use core::kinds::Copy;
-    use core::vec::capacity;
     use core;
 
     #[test]
@@ -442,11 +441,11 @@ mod tests {
         let mut d = Deque::new();
         d.add_back(0u64);
         d.reserve(50);
-        assert_eq!(capacity(&mut d.elts), 50);
+        assert_eq!(d.elts.capacity(), 50);
         let mut d = Deque::new();
         d.add_back(0u32);
         d.reserve(50);
-        assert_eq!(capacity(&mut d.elts), 50);
+        assert_eq!(d.elts.capacity(), 50);
     }
 
     #[test]
@@ -454,11 +453,11 @@ mod tests {
         let mut d = Deque::new();
         d.add_back(0u64);
         d.reserve_at_least(50);
-        assert_eq!(capacity(&mut d.elts), 64);
+        assert_eq!(d.elts.capacity(), 64);
         let mut d = Deque::new();
         d.add_back(0u32);
         d.reserve_at_least(50);
-        assert_eq!(capacity(&mut d.elts), 64);
+        assert_eq!(d.elts.capacity(), 64);
     }
 
     #[test]
diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs
index 1767aa8c397..ee86340e47b 100644
--- a/src/libextra/dlist.rs
+++ b/src/libextra/dlist.rs
@@ -526,8 +526,6 @@ mod tests {
 
     use super::*;
 
-    use core::vec;
-
     #[test]
     fn test_dlist_concat() {
         let a = from_vec([1,2]);
diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs
index dd08f23a7a1..4634a7db05e 100644
--- a/src/libextra/ebml.rs
+++ b/src/libextra/ebml.rs
@@ -12,6 +12,8 @@
 
 use core::prelude::*;
 
+use core::str;
+
 // Simple Extensible Binary Markup Language (ebml) reader and writer on a
 // cursor model. See the specification here:
 //     http://www.matroska.org/technical/specs/rfc/index.html
@@ -34,6 +36,20 @@ pub struct Doc {
     end: uint,
 }
 
+impl Doc {
+    pub fn get(&self, tag: uint) -> Doc {
+        reader::get_doc(*self, tag)
+    }
+
+    pub fn as_str_slice<'a>(&'a self) -> &'a str {
+        str::from_bytes_slice(self.data.slice(self.start, self.end))
+    }
+
+    pub fn as_str(&self) -> ~str {
+        self.as_str_slice().to_owned()
+    }
+}
+
 pub struct TaggedDoc {
     tag: uint,
     doc: Doc,
@@ -78,31 +94,21 @@ pub mod reader {
 
     use serialize;
 
-    use core::prelude::*;
     use core::cast::transmute;
     use core::int;
     use core::io;
+    use core::option::{None, Option, Some};
+
+    #[cfg(target_arch = "x86")]
+    #[cfg(target_arch = "x86_64")]
     use core::ptr::offset;
-    use core::str;
+
+    #[cfg(target_arch = "x86")]
+    #[cfg(target_arch = "x86_64")]
     use core::unstable::intrinsics::bswap32;
-    use core::vec;
 
     // ebml reading
 
-    impl Doc {
-        pub fn get(&self, tag: uint) -> Doc {
-            get_doc(*self, tag)
-        }
-
-        pub fn as_str_slice<'a>(&'a self) -> &'a str {
-            str::from_bytes_slice(self.data.slice(self.start, self.end))
-        }
-
-        pub fn as_str(&self) -> ~str {
-            self.as_str_slice().to_owned()
-        }
-    }
-
     struct Res {
         val: uint,
         next: uint
@@ -248,7 +254,7 @@ pub mod reader {
     }
 
     pub fn with_doc_data<T>(d: Doc, f: &fn(x: &[u8]) -> T) -> T {
-        f(vec::slice(*d.data, d.start, d.end))
+        f(d.data.slice(d.start, d.end))
     }
 
 
diff --git a/src/libextra/flatpipes.rs b/src/libextra/flatpipes.rs
index 60fbfdeb62c..d5e43e85a14 100644
--- a/src/libextra/flatpipes.rs
+++ b/src/libextra/flatpipes.rs
@@ -166,8 +166,8 @@ Constructors for flat pipes that send POD types using memcpy.
 
 # Safety Note
 
-This module is currently unsafe because it uses `Copy Owned` as a type
-parameter bounds meaning POD (plain old data), but `Copy Owned` and
+This module is currently unsafe because it uses `Copy Send` as a type
+parameter bounds meaning POD (plain old data), but `Copy Send` and
 POD are not equivelant.
 
 */
@@ -191,7 +191,7 @@ pub mod pod {
     pub type PipeChan<T> = FlatChan<T, PodFlattener<T>, PipeByteChan>;
 
     /// Create a `FlatPort` from a `Reader`
-    pub fn reader_port<T:Copy + Owned,R:Reader>(
+    pub fn reader_port<T:Copy + Send,R:Reader>(
         reader: R
     ) -> ReaderPort<T, R> {
         let unflat: PodUnflattener<T> = PodUnflattener::new();
@@ -200,7 +200,7 @@ pub mod pod {
     }
 
     /// Create a `FlatChan` from a `Writer`
-    pub fn writer_chan<T:Copy + Owned,W:Writer>(
+    pub fn writer_chan<T:Copy + Send,W:Writer>(
         writer: W
     ) -> WriterChan<T, W> {
         let flat: PodFlattener<T> = PodFlattener::new();
@@ -209,21 +209,21 @@ pub mod pod {
     }
 
     /// Create a `FlatPort` from a `Port<~[u8]>`
-    pub fn pipe_port<T:Copy + Owned>(port: Port<~[u8]>) -> PipePort<T> {
+    pub fn pipe_port<T:Copy + Send>(port: Port<~[u8]>) -> PipePort<T> {
         let unflat: PodUnflattener<T> = PodUnflattener::new();
         let byte_port = PipeBytePort::new(port);
         FlatPort::new(unflat, byte_port)
     }
 
     /// Create a `FlatChan` from a `Chan<~[u8]>`
-    pub fn pipe_chan<T:Copy + Owned>(chan: Chan<~[u8]>) -> PipeChan<T> {
+    pub fn pipe_chan<T:Copy + Send>(chan: Chan<~[u8]>) -> PipeChan<T> {
         let flat: PodFlattener<T> = PodFlattener::new();
         let byte_chan = PipeByteChan::new(chan);
         FlatChan::new(flat, byte_chan)
     }
 
     /// Create a pair of `FlatChan` and `FlatPort`, backed by pipes
-    pub fn pipe_stream<T:Copy + Owned>() -> (PipePort<T>, PipeChan<T>) {
+    pub fn pipe_stream<T:Copy + Send>() -> (PipePort<T>, PipeChan<T>) {
         let (port, chan) = comm::stream();
         return (pipe_port(port), pipe_chan(chan));
     }
@@ -352,7 +352,7 @@ pub mod flatteners {
     use core::sys::size_of;
     use core::vec;
 
-    // FIXME #4074: Copy + Owned != POD
+    // FIXME #4074: Copy + Send != POD
     pub struct PodUnflattener<T> {
         bogus: ()
     }
@@ -361,7 +361,7 @@ pub mod flatteners {
         bogus: ()
     }
 
-    impl<T:Copy + Owned> Unflattener<T> for PodUnflattener<T> {
+    impl<T:Copy + Send> Unflattener<T> for PodUnflattener<T> {
         fn unflatten(&self, buf: ~[u8]) -> T {
             assert!(size_of::<T>() != 0);
             assert_eq!(size_of::<T>(), buf.len());
@@ -371,7 +371,7 @@ pub mod flatteners {
         }
     }
 
-    impl<T:Copy + Owned> Flattener<T> for PodFlattener<T> {
+    impl<T:Copy + Send> Flattener<T> for PodFlattener<T> {
         fn flatten(&self, val: T) -> ~[u8] {
             assert!(size_of::<T>() != 0);
             let val: *T = ptr::to_unsafe_ptr(&val);
@@ -380,7 +380,7 @@ pub mod flatteners {
         }
     }
 
-    impl<T:Copy + Owned> PodUnflattener<T> {
+    impl<T:Copy + Send> PodUnflattener<T> {
         pub fn new() -> PodUnflattener<T> {
             PodUnflattener {
                 bogus: ()
@@ -388,7 +388,7 @@ pub mod flatteners {
         }
     }
 
-    impl<T:Copy + Owned> PodFlattener<T> {
+    impl<T:Copy + Send> PodFlattener<T> {
         pub fn new() -> PodFlattener<T> {
             PodFlattener {
                 bogus: ()
diff --git a/src/libextra/fun_treemap.rs b/src/libextra/fun_treemap.rs
index eb8c27e9902..5906e809c98 100644
--- a/src/libextra/fun_treemap.rs
+++ b/src/libextra/fun_treemap.rs
@@ -66,9 +66,9 @@ pub fn traverse<K, V: Copy>(m: Treemap<K, V>, f: &fn(&K, &V)) {
         // 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);
+            traverse(left, |k,v| f(k,v));
             f(k, v);
-            traverse(right, f);
+            traverse(right, |k,v| f(k,v));
         }
     }
 }
diff --git a/src/libextra/future.rs b/src/libextra/future.rs
index f2cd64085ef..00f4cc3989b 100644
--- a/src/libextra/future.rs
+++ b/src/libextra/future.rs
@@ -101,7 +101,7 @@ pub fn from_value<A>(val: A) -> Future<A> {
     Future {state: Forced(val)}
 }
 
-pub fn from_port<A:Owned>(port: PortOne<A>) -> Future<A> {
+pub fn from_port<A:Send>(port: PortOne<A>) -> Future<A> {
     /*!
      * Create a future from a port
      *
@@ -127,7 +127,7 @@ pub fn from_fn<A>(f: ~fn() -> A) -> Future<A> {
     Future {state: Pending(f)}
 }
 
-pub fn spawn<A:Owned>(blk: ~fn() -> A) -> Future<A> {
+pub fn spawn<A:Send>(blk: ~fn() -> A) -> Future<A> {
     /*!
      * Create a future from a unique closure.
      *
diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs
index 9c416550eb7..fa064e6330e 100644
--- a/src/libextra/getopts.rs
+++ b/src/libextra/getopts.rs
@@ -606,33 +606,47 @@ pub mod groups {
             let mut row = " ".repeat(4);
 
             // short option
-            row += match short_name.len() {
-                0 => ~"",
-                1 => ~"-" + short_name + " ",
+            match short_name.len() {
+                0 => {}
+                1 => {
+                    row.push_char('-');
+                    row.push_str(short_name);
+                    row.push_char(' ');
+                }
                 _ => fail!("the short name should only be 1 ascii char long"),
-            };
+            }
 
             // long option
-            row += match long_name.len() {
-                0 => ~"",
-                _ => ~"--" + long_name + " ",
-            };
+            match long_name.len() {
+                0 => {}
+                _ => {
+                    row.push_str("--");
+                    row.push_str(long_name);
+                    row.push_char(' ');
+                }
+            }
 
             // arg
-            row += match hasarg {
-                No    => ~"",
-                Yes   => hint,
-                Maybe => ~"[" + hint + "]",
-            };
+            match hasarg {
+                No => {}
+                Yes => row.push_str(hint),
+                Maybe => {
+                    row.push_char('[');
+                    row.push_str(hint);
+                    row.push_char(']');
+                }
+            }
 
             // FIXME: #5516
             // here we just need to indent the start of the description
             let rowlen = row.len();
-            row += if rowlen < 24 {
-                " ".repeat(24 - rowlen)
+            if rowlen < 24 {
+                for (24 - rowlen).times {
+                    row.push_char(' ')
+                }
             } else {
-                copy desc_sep
-            };
+                row.push_str(desc_sep)
+            }
 
             // Normalize desc to contain words separated by one space character
             let mut desc_normalized_whitespace = ~"";
@@ -649,7 +663,7 @@ pub mod groups {
 
             // FIXME: #5516
             // wrapped description
-            row += desc_rows.connect(desc_sep);
+            row.push_str(desc_rows.connect(desc_sep));
 
             row
         });
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index 15553b035f6..a71be18174a 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -60,25 +60,27 @@ fn escape_str(s: &str) -> ~str {
     let mut escaped = ~"\"";
     for s.iter().advance |c| {
         match c {
-          '"' => escaped += "\\\"",
-          '\\' => escaped += "\\\\",
-          '\x08' => escaped += "\\b",
-          '\x0c' => escaped += "\\f",
-          '\n' => escaped += "\\n",
-          '\r' => escaped += "\\r",
-          '\t' => escaped += "\\t",
-          _ => escaped += str::from_char(c)
+          '"' => escaped.push_str("\\\""),
+          '\\' => escaped.push_str("\\\\"),
+          '\x08' => escaped.push_str("\\b"),
+          '\x0c' => escaped.push_str("\\f"),
+          '\n' => escaped.push_str("\\n"),
+          '\r' => escaped.push_str("\\r"),
+          '\t' => escaped.push_str("\\t"),
+          _ => escaped.push_char(c),
         }
     };
 
-    escaped += "\"";
+    escaped.push_char('"');
 
     escaped
 }
 
 fn spaces(n: uint) -> ~str {
     let mut ss = ~"";
-    for n.times { ss.push_str(" "); }
+    for n.times {
+        ss.push_str(" ");
+    }
     return ss;
 }
 
diff --git a/src/libextra/md4.rs b/src/libextra/md4.rs
index 6c972a313c4..3be7394b46d 100644
--- a/src/libextra/md4.rs
+++ b/src/libextra/md4.rs
@@ -59,7 +59,8 @@ pub fn md4(msg: &[u8]) -> Quad {
     while i < e {
         let (aa, bb, cc, dd) = (a, b, c, d);
 
-        let mut (j, base) = (0u, i);
+        let mut j = 0u;
+        let mut base = i;
         while j < 16u {
             x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) +
                 (msg[base + 2u] as u32 << 16u32) +
@@ -118,8 +119,10 @@ pub fn md4_str(msg: &[u8]) -> ~str {
         let mut i = 0u32;
         while i < 4u32 {
             let byte = (u >> (i * 8u32)) as u8;
-            if byte <= 16u8 { result += "0"; }
-            result += uint::to_str_radix(byte as uint, 16u);
+            if byte <= 16u8 {
+                result.push_char('0')
+            }
+            result.push_str(uint::to_str_radix(byte as uint, 16u));
             i += 1u32;
         }
     }
diff --git a/src/libextra/net_tcp.rs b/src/libextra/net_tcp.rs
index 6ad51931c67..f3f6ffde660 100644
--- a/src/libextra/net_tcp.rs
+++ b/src/libextra/net_tcp.rs
@@ -976,9 +976,7 @@ impl io::Writer for TcpSocketBuf {
         let socket_data_ptr: *TcpSocketData =
             &(*((*(self.data)).sock).socket_data);
         let w_result = write_common_impl(socket_data_ptr,
-                                         vec::slice(data,
-                                                    0,
-                                                    data.len()).to_owned());
+                                         data.slice(0, data.len()).to_owned());
         if w_result.is_err() {
             let err_data = w_result.get_err();
             debug!(
@@ -1459,33 +1457,23 @@ mod test {
 
             #[test]
             fn test_gl_tcp_server_and_client_ipv4() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_and_client();
-                }
+                impl_gl_tcp_ipv4_server_and_client();
             }
             #[test]
             fn test_gl_tcp_get_peer_addr() {
-                unsafe {
-                    impl_gl_tcp_ipv4_get_peer_addr();
-                }
+                impl_gl_tcp_ipv4_get_peer_addr();
             }
             #[test]
             fn test_gl_tcp_ipv4_client_error_connection_refused() {
-                unsafe {
-                    impl_gl_tcp_ipv4_client_error_connection_refused();
-                }
+                impl_gl_tcp_ipv4_client_error_connection_refused();
             }
             #[test]
             fn test_gl_tcp_server_address_in_use() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_address_in_use();
-                }
+                impl_gl_tcp_ipv4_server_address_in_use();
             }
             #[test]
             fn test_gl_tcp_server_access_denied() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_access_denied();
-                }
+                impl_gl_tcp_ipv4_server_access_denied();
             }
             // Strange failure on Windows. --pcwalton
             #[test]
diff --git a/src/libextra/net_url.rs b/src/libextra/net_url.rs
index 5d3d31fdec4..a60f51e751e 100644
--- a/src/libextra/net_url.rs
+++ b/src/libextra/net_url.rs
@@ -93,10 +93,10 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
                         out.push_char(ch);
                       }
 
-                      _ => out += fmt!("%%%X", ch as uint)
+                      _ => out.push_str(fmt!("%%%X", ch as uint))
                     }
                 } else {
-                    out += fmt!("%%%X", ch as uint);
+                    out.push_str(fmt!("%%%X", ch as uint));
                 }
               }
             }
@@ -192,7 +192,7 @@ fn encode_plus(s: &str) -> ~str {
                 out.push_char(ch);
               }
               ' ' => out.push_char('+'),
-              _ => out += fmt!("%%%X", ch as uint)
+              _ => out.push_str(fmt!("%%%X", ch as uint))
             }
         }
 
@@ -218,7 +218,7 @@ pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str {
                 first = false;
             }
 
-            out += fmt!("%s=%s", key, encode_plus(*value));
+            out.push_str(fmt!("%s=%s", key, encode_plus(*value)));
         }
     }
 
@@ -415,7 +415,9 @@ fn get_authority(rawurl: &str) ->
     let mut port = None;
 
     let mut colon_count = 0;
-    let mut (pos, begin, end) = (0, 2, len);
+    let mut pos = 0;
+    let mut begin = 2;
+    let mut end = len;
 
     for rawurl.iter().enumerate().advance |(i,c)| {
         if i < 2 { loop; } // ignore the leading //
diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs
index 4b080e0153c..002d8a7f956 100644
--- a/src/libextra/num/bigint.rs
+++ b/src/libextra/num/bigint.rs
@@ -298,9 +298,8 @@ impl Mul<BigUint, BigUint> for BigUint {
 
         fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
             let mid = uint::min(a.data.len(), n);
-            return (BigUint::from_slice(vec::slice(a.data, mid,
-                                                   a.data.len())),
-                    BigUint::from_slice(vec::slice(a.data, 0, mid)));
+            return (BigUint::from_slice(a.data.slice(mid, a.data.len())),
+                    BigUint::from_slice(a.data.slice(0, mid)));
         }
 
 
@@ -381,7 +380,8 @@ impl Integer for BigUint {
             let mut d = Zero::zero::<BigUint>();
             let mut n = 1;
             while m >= b {
-                let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
+                let (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
+                let mut d0 = d0;
                 let mut prod = b * d0;
                 while prod > m {
                     // FIXME(#6050): overloaded operators force moves with generic types
@@ -413,7 +413,7 @@ impl Integer for BigUint {
                 return (Zero::zero(), Zero::zero(), copy *a);
             }
 
-            let an = vec::slice(a.data, a.data.len() - n, a.data.len());
+            let an = a.data.slice(a.data.len() - n, a.data.len());
             let bn = *b.data.last();
             let mut d = ~[];
             let mut carry = 0;
@@ -443,7 +443,8 @@ impl Integer for BigUint {
 
     fn gcd(&self, other: &BigUint) -> BigUint {
         // Use Euclid's algorithm
-        let mut (m, n) = (copy *self, copy *other);
+        let mut m = copy *self;
+        let mut n = copy *other;
         while !m.is_zero() {
             let temp = m;
             m = n % temp;
@@ -507,11 +508,11 @@ impl ToStrRadix for BigUint {
             let mut m      = n;
             while m > divider {
                 let (d, m0) = m.div_mod_floor(&divider);
-                result += [m0.to_uint() as BigDigit];
+                result.push(m0.to_uint() as BigDigit);
                 m = d;
             }
             if !m.is_zero() {
-                result += [m.to_uint() as BigDigit];
+                result.push(m.to_uint() as BigDigit);
             }
             return result;
         }
@@ -578,7 +579,7 @@ impl BigUint {
         let mut power: BigUint  = One::one();
         loop {
             let start = uint::max(end, unit_len) - unit_len;
-            match uint::parse_bytes(vec::slice(buf, start, end), radix) {
+            match uint::parse_bytes(buf.slice(start, end), radix) {
                 // FIXME(#6102): Assignment operator for BigInt causes ICE
                 // Some(d) => n += BigUint::from_uint(d) * power,
                 Some(d) => n = n + BigUint::from_uint(d) * power,
@@ -634,7 +635,7 @@ impl BigUint {
         if n_unit == 0 { return copy *self; }
         if self.data.len() < n_unit { return Zero::zero(); }
         return BigUint::from_slice(
-            vec::slice(self.data, n_unit, self.data.len())
+            self.data.slice(n_unit, self.data.len())
         );
     }
 
@@ -1132,7 +1133,7 @@ impl BigInt {
             sign  = Minus;
             start = 1;
         }
-        return BigUint::parse_bytes(vec::slice(buf, start, buf.len()), radix)
+        return BigUint::parse_bytes(buf.slice(start, buf.len()), radix)
             .map_consume(|bu| BigInt::from_biguint(sign, bu));
     }
 
@@ -1176,7 +1177,7 @@ mod biguint_tests {
         let data = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1]  ]
             .map(|v| BigUint::from_slice(*v));
         for data.iter().enumerate().advance |(i, ni)| {
-            for vec::slice(data, i, data.len()).iter().enumerate().advance |(j0, nj)| {
+            for data.slice(i, data.len()).iter().enumerate().advance |(j0, nj)| {
                 let j = j0 + i;
                 if i == j {
                     assert_eq!(ni.cmp(nj), Equal);
@@ -1654,7 +1655,7 @@ mod bigint_tests {
         nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
 
         for nums.iter().enumerate().advance |(i, ni)| {
-            for vec::slice(nums, i, nums.len()).iter().enumerate().advance |(j0, nj)| {
+            for nums.slice(i, nums.len()).iter().enumerate().advance |(j0, nj)| {
                 let j = i + j0;
                 if i == j {
                     assert_eq!(ni.cmp(nj), Equal);
diff --git a/src/libextra/par.rs b/src/libextra/par.rs
index 334ab7c9c99..a3014cf8894 100644
--- a/src/libextra/par.rs
+++ b/src/libextra/par.rs
@@ -33,7 +33,7 @@ static min_granularity : uint = 1024u;
  * This is used to build most of the other parallel vector functions,
  * like map or alli.
  */
-fn map_slices<A:Copy + Owned,B:Copy + Owned>(
+fn map_slices<A:Copy + Send,B:Copy + Send>(
     xs: &[A],
     f: &fn() -> ~fn(uint, v: &[A]) -> B)
     -> ~[B] {
@@ -88,7 +88,7 @@ fn map_slices<A:Copy + Owned,B:Copy + Owned>(
 }
 
 /// A parallel version of map.
-pub fn map<A:Copy + Owned,B:Copy + Owned>(
+pub fn map<A:Copy + Send,B:Copy + Send>(
     xs: &[A], fn_factory: &fn() -> ~fn(&A) -> B) -> ~[B] {
     vec::concat(map_slices(xs, || {
         let f = fn_factory();
@@ -99,7 +99,7 @@ pub fn map<A:Copy + Owned,B:Copy + Owned>(
 }
 
 /// A parallel version of mapi.
-pub fn mapi<A:Copy + Owned,B:Copy + Owned>(
+pub fn mapi<A:Copy + Send,B:Copy + Send>(
         xs: &[A],
         fn_factory: &fn() -> ~fn(uint, &A) -> B) -> ~[B] {
     let slices = map_slices(xs, || {
@@ -118,7 +118,7 @@ pub fn mapi<A:Copy + Owned,B:Copy + Owned>(
 }
 
 /// Returns true if the function holds for all elements in the vector.
-pub fn alli<A:Copy + Owned>(
+pub fn alli<A:Copy + Send>(
     xs: &[A],
     fn_factory: &fn() -> ~fn(uint, &A) -> bool) -> bool
 {
@@ -133,7 +133,7 @@ pub fn alli<A:Copy + Owned>(
 }
 
 /// Returns true if the function holds for any elements in the vector.
-pub fn any<A:Copy + Owned>(
+pub fn any<A:Copy + Send>(
     xs: &[A],
     fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
     let mapped = map_slices(xs, || {
diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs
index af891edf9e5..fbb4be0febb 100644
--- a/src/libextra/priority_queue.rs
+++ b/src/libextra/priority_queue.rs
@@ -52,12 +52,12 @@ impl<T:Ord> PriorityQueue<T> {
     }
 
     /// Returns the number of elements the queue can hold without reallocating
-    pub fn capacity(&self) -> uint { vec::capacity(&self.data) }
+    pub fn capacity(&self) -> uint { self.data.capacity() }
 
-    pub fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }
+    pub fn reserve(&mut self, n: uint) { self.data.reserve(n) }
 
     pub fn reserve_at_least(&mut self, n: uint) {
-        vec::reserve_at_least(&mut self.data, n)
+        self.data.reserve_at_least(n)
     }
 
     /// Pop the greatest item from the queue - fails if empty
diff --git a/src/libextra/rc.rs b/src/libextra/rc.rs
index 8ef58a188d9..613c0b1ae41 100644
--- a/src/libextra/rc.rs
+++ b/src/libextra/rc.rs
@@ -13,10 +13,10 @@
 /** 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 types that are either `Owned` or `Const` (or both) to
+destruction. They are restricted to containing types that are either `Send` or `Freeze` (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
+Neither `Rc<T>` or `RcMut<T>` is ever `Send` and `RcMut<T>` is never `Freeze`. If `T` is `Freeze`, a
 cycle cannot be created with `Rc<T>` because there is no way to modify it after creation.
 
 */
@@ -35,7 +35,8 @@ struct RcBox<T> {
 }
 
 /// Immutable reference counted pointer type
-#[non_owned]
+#[unsafe_no_drop_flag]
+#[no_send]
 pub struct Rc<T> {
     priv ptr: *mut RcBox<T>,
 }
@@ -50,12 +51,12 @@ impl<T> Rc<T> {
 }
 
 // FIXME: #6516: should be a static method
-pub fn rc_from_owned<T: Owned>(value: T) -> Rc<T> {
+pub fn rc_from_owned<T: Send>(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> {
+pub fn rc_from_const<T: Freeze>(value: T) -> Rc<T> {
     unsafe { Rc::new(value) }
 }
 
@@ -167,7 +168,10 @@ struct RcMutBox<T> {
 
 /// Mutable reference counted pointer type
 #[non_owned]
-#[mutable]
+#[no_send]
+#[mutable] // XXX remove after snap
+#[no_freeze]
+#[unsafe_no_drop_flag]
 pub struct RcMut<T> {
     priv ptr: *mut RcMutBox<T>,
 }
@@ -182,12 +186,12 @@ impl<T> RcMut<T> {
 }
 
 // FIXME: #6516: should be a static method
-pub fn rc_mut_from_owned<T: Owned>(value: T) -> RcMut<T> {
+pub fn rc_mut_from_owned<T: Send>(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> {
+pub fn rc_mut_from_const<T: Freeze>(value: T) -> RcMut<T> {
     unsafe { RcMut::new(value) }
 }
 
diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs
index fed73256c00..71393ff9fae 100644
--- a/src/libextra/rope.rs
+++ b/src/libextra/rope.rs
@@ -1078,7 +1078,7 @@ pub mod node {
 
     pub fn loop_chars(node: @Node, it: &fn(c: char) -> bool) -> bool {
         return loop_leaves(node,|leaf| {
-            leaf.content.slice(leaf.byte_offset, leaf.byte_len).iter().all(it)
+            leaf.content.slice(leaf.byte_offset, leaf.byte_len).iter().all(|c| it(c))
         });
     }
 
@@ -1101,7 +1101,7 @@ pub mod node {
         loop {
             match (*current) {
               Leaf(x) => return it(x),
-              Concat(ref x) => if loop_leaves(x.left, it) { //non tail call
+              Concat(ref x) => if loop_leaves(x.left, |l| it(l)) { //non tail call
                 current = x.right;       //tail call
               } else {
                 return false;
diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs
index 3c872d64ca0..10dbe2326d7 100644
--- a/src/libextra/sort.rs
+++ b/src/libextra/sort.rs
@@ -42,7 +42,8 @@ pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
         let mid = v_len / 2 + begin;
         let a = (begin, mid);
         let b = (mid, end);
-        return merge(le, merge_sort_(v, a, le), merge_sort_(v, b, le));
+        return merge(|x,y| le(x,y), merge_sort_(v, a, |x,y| le(x,y)),
+                                    merge_sort_(v, b, |x,y| le(x,y)));
     }
 
     fn merge<T:Copy>(le: Le<T>, a: &[T], b: &[T]) -> ~[T] {
@@ -57,8 +58,8 @@ pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
                 a_ix += 1;
             } else { rs.push(copy b[b_ix]); b_ix += 1; }
         }
-        rs.push_all(vec::slice(a, a_ix, a_len));
-        rs.push_all(vec::slice(b, b_ix, b_len));
+        rs.push_all(a.slice(a_ix, a_len));
+        rs.push_all(b.slice(b_ix, b_len));
         rs
     }
 }
@@ -83,10 +84,10 @@ fn qsort<T>(arr: &mut [T], left: uint,
             right: uint, compare_func: Le<T>) {
     if right > left {
         let pivot = (left + right) / 2u;
-        let new_pivot = part::<T>(arr, left, right, pivot, compare_func);
+        let new_pivot = part::<T>(arr, left, right, pivot, |x,y| compare_func(x,y));
         if new_pivot != 0u {
             // Need to do this check before recursing due to overflow
-            qsort::<T>(arr, left, new_pivot - 1u, compare_func);
+            qsort::<T>(arr, left, new_pivot - 1u, |x,y| compare_func(x,y));
         }
         qsort::<T>(arr, new_pivot + 1u, right, compare_func);
     }
@@ -201,12 +202,12 @@ pub fn tim_sort<T:Copy + Ord>(array: &mut [T]) {
     loop {
         let run_len: uint = {
             // This scope contains the slice `arr` here:
-            let arr = vec::mut_slice(array, idx, size);
+            let arr = array.mut_slice(idx, size);
             let mut run_len: uint = count_run_ascending(arr);
 
             if run_len < min_run {
                 let force = if remaining <= min_run {remaining} else {min_run};
-                let slice = vec::mut_slice(arr, 0, force);
+                let slice = arr.mut_slice(0, force);
                 binarysort(slice, run_len);
                 run_len = force;
             }
@@ -443,14 +444,14 @@ impl<T:Copy + Ord> MergeState<T> {
         }
 
         let k = { // constrain lifetime of slice below
-            let slice = vec::slice(array, b1, b1+l1);
+            let slice = array.slice(b1, b1+l1);
             gallop_right(&array[b2], slice, 0)
         };
         b1 += k;
         l1 -= k;
         if l1 != 0 {
             let l2 = { // constrain lifetime of slice below
-                let slice = vec::slice(array, b2, b2+l2);
+                let slice = array.slice(b2, b2+l2);
                 gallop_left(&array[b1+l1-1],slice,l2-1)
             };
             if l2 > 0 {
@@ -526,7 +527,7 @@ impl<T:Copy + Ord> MergeState<T> {
                 assert!(len1 > 1 && len2 != 0);
 
                 count1 = {
-                    let tmp_view = vec::slice(tmp, c1, c1+len1);
+                    let tmp_view = tmp.slice(c1, c1+len1);
                     gallop_right(&array[c2], tmp_view, 0)
                 };
                 if count1 != 0 {
@@ -539,7 +540,7 @@ impl<T:Copy + Ord> MergeState<T> {
                 if len2 == 0 { break_outer = true; break; }
 
                 count2 = {
-                    let tmp_view = vec::slice(array, c2, c2+len2);
+                    let tmp_view = array.slice(c2, c2+len2);
                     gallop_left(&tmp[c1], tmp_view, 0)
                 };
                 if count2 != 0 {
@@ -638,7 +639,7 @@ impl<T:Copy + Ord> MergeState<T> {
                 assert!(len2 > 1 && len1 != 0);
 
                 { // constrain scope of tmp_view:
-                    let tmp_view = vec::mut_slice (array, base1, base1+len1);
+                    let tmp_view = array.mut_slice(base1, base1+len1);
                     count1 = len1 - gallop_right(
                         &tmp[c2], tmp_view, len1-1);
                 }
@@ -655,7 +656,7 @@ impl<T:Copy + Ord> MergeState<T> {
 
                 let count2;
                 { // constrain scope of tmp_view
-                    let tmp_view = vec::mut_slice(tmp, 0, len2);
+                    let tmp_view = tmp.mut_slice(0, len2);
                     count2 = len2 - gallop_left(&array[c1],
                                                 tmp_view,
                                                 len2-1);
@@ -1111,7 +1112,7 @@ mod big_tests {
             isSorted(arr);
 
             let mut arr = if n > 4 {
-                let part = vec::slice(arr, 0, 4);
+                let part = arr.slice(0, 4);
                 multiplyVec(part, n)
             } else { arr };
             tim_sort(arr); // ~sort
@@ -1183,7 +1184,7 @@ mod big_tests {
             isSorted(arr);
 
             let mut arr = if n > 4 {
-                let part = vec::slice(arr, 0, 4);
+                let part = arr.slice(0, 4);
                 multiplyVec(part, n)
             } else { arr };
             tim_sort(arr); // ~sort
@@ -1202,7 +1203,7 @@ mod big_tests {
 
     struct LVal<'self> {
         val: uint,
-        key: &'self fn(@uint),
+        key: &'self fn:Copy(@uint),
     }
 
     #[unsafe_destructor]
diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs
index 8cfe39c5ef2..9c6be901d98 100644
--- a/src/libextra/sync.rs
+++ b/src/libextra/sync.rs
@@ -86,7 +86,7 @@ struct SemInner<Q> {
 struct Sem<Q>(Exclusive<SemInner<Q>>);
 
 #[doc(hidden)]
-fn new_sem<Q:Owned>(count: int, q: Q) -> Sem<Q> {
+fn new_sem<Q:Send>(count: int, q: Q) -> Sem<Q> {
     Sem(exclusive(SemInner {
         count: count, waiters: new_waitqueue(), blocked: q }))
 }
@@ -101,7 +101,7 @@ fn new_sem_and_signal(count: int, num_condvars: uint)
 }
 
 #[doc(hidden)]
-impl<Q:Owned> Sem<Q> {
+impl<Q:Send> Sem<Q> {
     pub fn acquire(&self) {
         unsafe {
             let mut waiter_nobe = None;
@@ -153,7 +153,7 @@ impl Sem<()> {
 
 #[doc(hidden)]
 impl Sem<~[Waitqueue]> {
-    pub fn access<U>(&self, blk: &fn() -> U) -> U {
+    pub fn access_waitqueue<U>(&self, blk: &fn() -> U) -> U {
         let mut release = None;
         unsafe {
             do task::unkillable {
@@ -175,7 +175,7 @@ struct SemReleaseGeneric<'self, Q> { sem: &'self Sem<Q> }
 
 #[doc(hidden)]
 #[unsafe_destructor]
-impl<'self, Q:Owned> Drop for SemReleaseGeneric<'self, Q> {
+impl<'self, Q:Send> Drop for SemReleaseGeneric<'self, Q> {
     fn drop(&self) {
         self.sem.release();
     }
@@ -381,7 +381,7 @@ impl Sem<~[Waitqueue]> {
     // The only other places that condvars get built are rwlock.write_cond()
     // and rwlock_write_mode.
     pub fn access_cond<U>(&self, blk: &fn(c: &Condvar) -> U) -> U {
-        do self.access {
+        do self.access_waitqueue {
             blk(&Condvar { sem: self, order: Nothing })
         }
     }
@@ -456,7 +456,9 @@ impl Clone for Mutex {
 
 impl Mutex {
     /// Run a function with ownership of the mutex.
-    pub fn lock<U>(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) }
+    pub fn lock<U>(&self, blk: &fn() -> U) -> U {
+        (&self.sem).access_waitqueue(blk)
+    }
 
     /// Run a function with ownership of the mutex and a handle to a condvar.
     pub fn lock_cond<U>(&self, blk: &fn(c: &Condvar) -> U) -> U {
@@ -559,9 +561,11 @@ impl RWlock {
         unsafe {
             do task::unkillable {
                 (&self.order_lock).acquire();
-                do (&self.access_lock).access {
+                do (&self.access_lock).access_waitqueue {
                     (&self.order_lock).release();
-                    task::rekillable(blk)
+                    do task::rekillable {
+                        blk()
+                    }
                 }
             }
         }
@@ -808,7 +812,6 @@ mod tests {
     use core::comm;
     use core::result;
     use core::task;
-    use core::vec;
 
     /************************************************************************
      * Semaphore tests
@@ -1181,12 +1184,12 @@ mod tests {
             Write => x.write(blk),
             Downgrade =>
                 do x.write_downgrade |mode| {
-                    (&mode).write(blk);
+                    do mode.write { blk() };
                 },
             DowngradeRead =>
                 do x.write_downgrade |mode| {
                     let mode = x.downgrade(mode);
-                    (&mode).read(blk);
+                    do mode.read { blk() };
                 },
         }
     }
@@ -1339,10 +1342,10 @@ mod tests {
         fn lock_cond(x: &RWlock, downgrade: bool, blk: &fn(c: &Condvar)) {
             if downgrade {
                 do x.write_downgrade |mode| {
-                    (&mode).write_cond(blk)
+                    do mode.write_cond |c| { blk(c) }
                 }
             } else {
-                x.write_cond(blk)
+                do x.write_cond |c| { blk(c) }
             }
         }
         let x = ~RWlock();
diff --git a/src/libextra/term.rs b/src/libextra/term.rs
index 9a4469cb526..d448a1588a6 100644
--- a/src/libextra/term.rs
+++ b/src/libextra/term.rs
@@ -97,7 +97,7 @@ impl Terminal {
             if s.is_ok() {
                 self.out.write(s.unwrap());
             } else {
-                warn!(s.unwrap_err());
+                warn!("%s", s.unwrap_err());
             }
         }
     }
@@ -113,17 +113,22 @@ impl Terminal {
             if s.is_ok() {
                 self.out.write(s.unwrap());
             } else {
-                warn!(s.unwrap_err());
+                warn!("%s", s.unwrap_err());
             }
         }
     }
     pub fn reset(&self) {
         let mut vars = Variables::new();
-        let s = expand(*self.ti.strings.find_equiv(&("op")).unwrap(), [], &mut vars);
+        let s = do self.ti.strings.find_equiv(&("op"))
+                       .map_consume_default(Err(~"can't find terminfo capability `op`")) |&op| {
+                           expand(op, [], &mut vars)
+                       };
         if s.is_ok() {
             self.out.write(s.unwrap());
+        } else if self.num_colors > 0 {
+            warn!("%s", s.unwrap_err());
         } else {
-            warn!(s.unwrap_err());
+            debug!("%s", s.unwrap_err());
         }
     }
 
diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs
index dca890ddf51..5180a71939c 100644
--- a/src/libextra/terminfo/parm.rs
+++ b/src/libextra/terminfo/parm.rs
@@ -470,13 +470,14 @@ priv fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
                         FormatHex|FormatHEX => 16,
                         FormatString => util::unreachable()
                     };
-                    let mut (s,_) = match op {
+                    let (s,_) = match op {
                         FormatDigit => {
                             let sign = if flags.sign { SignAll } else { SignNeg };
                             to_str_bytes_common(&d, radix, false, sign, DigAll)
                         }
                         _ => to_str_bytes_common(&(d as uint), radix, false, SignNone, DigAll)
                     };
+                    let mut s = s;
                     if flags.precision > s.len() {
                         let mut s_ = vec::with_capacity(flags.precision);
                         let n = flags.precision - s.len();
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index 72e70943ce1..50ca96e6e21 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -19,15 +19,21 @@ use core::prelude::*;
 
 use getopts;
 use sort;
+use stats::Stats;
 use term;
+use time::precise_time_ns;
 
 use core::comm::{stream, SharedChan};
 use core::either;
 use core::io;
+use core::num;
 use core::option;
+use core::rand::RngUtil;
+use core::rand;
 use core::result;
 use core::task;
 use core::to_str::ToStr;
+use core::u64;
 use core::uint;
 use core::vec;
 
@@ -139,7 +145,7 @@ type OptRes = Either<TestOpts, ~str>;
 
 // Parses command line arguments into test options
 pub fn parse_opts(args: &[~str]) -> OptRes {
-    let args_ = vec::tail(args);
+    let args_ = args.tail();
     let opts = ~[getopts::optflag("ignored"),
                  getopts::optflag("test"),
                  getopts::optflag("bench"),
@@ -431,7 +437,7 @@ fn run_tests(opts: &TestOpts,
     callback(TeFiltered(filtered_descs));
 
     let (filtered_tests, filtered_benchs) =
-        do vec::partition(filtered_tests) |e| {
+        do filtered_tests.partition |e| {
         match e.testfn {
             StaticTestFn(_) | DynTestFn(_) => true,
             StaticBenchFn(_) | DynBenchFn(_) => false
@@ -609,152 +615,143 @@ fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult {
     }
 }
 
-pub mod bench {
-    use core::prelude::*;
-
-    use core::num;
-    use core::rand::RngUtil;
-    use core::rand;
-    use core::u64;
-    use core::vec;
-    use stats::Stats;
-    use test::{BenchHarness, BenchSamples};
-    use time::precise_time_ns;
-
-    impl BenchHarness {
-        /// Callback for benchmark functions to run in their body.
-        pub fn iter(&mut self, inner:&fn()) {
-            self.ns_start = precise_time_ns();
-            let k = self.iterations;
-            for u64::range(0, k) |_| {
-                inner();
-            }
-            self.ns_end = precise_time_ns();
+impl BenchHarness {
+    /// Callback for benchmark functions to run in their body.
+    pub fn iter(&mut self, inner:&fn()) {
+        self.ns_start = precise_time_ns();
+        let k = self.iterations;
+        for u64::range(0, k) |_| {
+            inner();
         }
+        self.ns_end = precise_time_ns();
+    }
 
-        pub fn ns_elapsed(&mut self) -> u64 {
-            if self.ns_start == 0 || self.ns_end == 0 {
-                0
-            } else {
-                self.ns_end - self.ns_start
-            }
+    pub fn ns_elapsed(&mut self) -> u64 {
+        if self.ns_start == 0 || self.ns_end == 0 {
+            0
+        } else {
+            self.ns_end - self.ns_start
         }
+    }
 
-        pub fn ns_per_iter(&mut self) -> u64 {
-            if self.iterations == 0 {
-                0
-            } else {
-                self.ns_elapsed() / self.iterations
-            }
+    pub fn ns_per_iter(&mut self) -> u64 {
+        if self.iterations == 0 {
+            0
+        } else {
+            self.ns_elapsed() / self.iterations
         }
+    }
 
-        pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) {
-            self.iterations = n;
-            debug!("running benchmark for %u iterations",
-                   n as uint);
-            f(self);
-        }
+    pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) {
+        self.iterations = n;
+        debug!("running benchmark for %u iterations",
+               n as uint);
+        f(self);
+    }
 
-        // This is the Go benchmark algorithm. It produces a single
-        // datapoint and always tries to run for 1s.
-        pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) {
-
-            // Rounds a number down to the nearest power of 10.
-            fn round_down_10(n: u64) -> u64 {
-                let mut n = n;
-                let mut res = 1;
-                while n > 10 {
-                    n = n / 10;
-                    res *= 10;
-                }
-                res
-            }
+    // This is the Go benchmark algorithm. It produces a single
+    // datapoint and always tries to run for 1s.
+    pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) {
 
-            // Rounds x up to a number of the form [1eX, 2eX, 5eX].
-            fn round_up(n: u64) -> u64 {
-                let base = round_down_10(n);
-                if n < (2 * base) {
-                    2 * base
-                } else if n < (5 * base) {
-                    5 * base
-                } else {
-                    10 * base
-                }
+        // Rounds a number down to the nearest power of 10.
+        fn round_down_10(n: u64) -> u64 {
+            let mut n = n;
+            let mut res = 1;
+            while n > 10 {
+                n = n / 10;
+                res *= 10;
             }
+            res
+        }
 
-            // Initial bench run to get ballpark figure.
-            let mut n = 1_u64;
-            self.bench_n(n, f);
-
-            while n < 1_000_000_000 &&
-                self.ns_elapsed() < 1_000_000_000 {
-                let last = n;
-
-                // Try to estimate iter count for 1s falling back to 1bn
-                // iterations if first run took < 1ns.
-                if self.ns_per_iter() == 0 {
-                    n = 1_000_000_000;
-                } else {
-                    n = 1_000_000_000 / self.ns_per_iter();
-                }
-
-                n = u64::max(u64::min(n+n/2, 100*last), last+1);
-                n = round_up(n);
-                self.bench_n(n, f);
+        // Rounds x up to a number of the form [1eX, 2eX, 5eX].
+        fn round_up(n: u64) -> u64 {
+            let base = round_down_10(n);
+            if n < (2 * base) {
+                2 * base
+            } else if n < (5 * base) {
+                5 * base
+            } else {
+                10 * base
             }
         }
 
-        // This is a more statistics-driven benchmark algorithm.
-        // It stops as quickly as 50ms, so long as the statistical
-        // properties are satisfactory. If those properties are
-        // not met, it may run as long as the Go algorithm.
-        pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] {
-
-            let mut rng = rand::rng();
-            let mut magnitude = 10;
-            let mut prev_madp = 0.0;
+        // Initial bench run to get ballpark figure.
+        let mut n = 1_u64;
+        self.bench_n(n, |x| f(x));
 
-            loop {
-                let n_samples = rng.gen_uint_range(50, 60);
-                let n_iter = rng.gen_uint_range(magnitude,
-                                                magnitude * 2);
+        while n < 1_000_000_000 &&
+            self.ns_elapsed() < 1_000_000_000 {
+            let last = n;
 
-                let samples = do vec::from_fn(n_samples) |_| {
-                    self.bench_n(n_iter as u64, f);
-                    self.ns_per_iter() as f64
-                };
+            // Try to estimate iter count for 1s falling back to 1bn
+            // iterations if first run took < 1ns.
+            if self.ns_per_iter() == 0 {
+                n = 1_000_000_000;
+            } else {
+                n = 1_000_000_000 / self.ns_per_iter();
+            }
 
-                // Eliminate outliers
-                let med = samples.median();
-                let mad = samples.median_abs_dev();
-                let samples = do vec::filter(samples) |f| {
-                    num::abs(*f - med) <= 3.0 * mad
-                };
+            n = u64::max(u64::min(n+n/2, 100*last), last+1);
+            n = round_up(n);
+            self.bench_n(n, |x| f(x));
+        }
+    }
 
-                debug!("%u samples, median %f, MAD=%f, %u survived filter",
-                       n_samples, med as float, mad as float,
-                       samples.len());
-
-                if samples.len() != 0 {
-                    // If we have _any_ cluster of signal...
-                    let curr_madp = samples.median_abs_dev_pct();
-                    if self.ns_elapsed() > 1_000_000 &&
-                        (curr_madp < 1.0 ||
-                         num::abs(curr_madp - prev_madp) < 0.1) {
-                        return samples;
-                    }
-                    prev_madp = curr_madp;
-
-                    if n_iter > 20_000_000 ||
-                        self.ns_elapsed() > 20_000_000 {
-                        return samples;
-                    }
+    // This is a more statistics-driven benchmark algorithm.
+    // It stops as quickly as 50ms, so long as the statistical
+    // properties are satisfactory. If those properties are
+    // not met, it may run as long as the Go algorithm.
+    pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] {
+
+        let mut rng = rand::rng();
+        let mut magnitude = 10;
+        let mut prev_madp = 0.0;
+
+        loop {
+            let n_samples = rng.gen_uint_range(50, 60);
+            let n_iter = rng.gen_uint_range(magnitude,
+                                            magnitude * 2);
+
+            let samples = do vec::from_fn(n_samples) |_| {
+                self.bench_n(n_iter as u64, |x| f(x));
+                self.ns_per_iter() as f64
+            };
+
+            // Eliminate outliers
+            let med = samples.median();
+            let mad = samples.median_abs_dev();
+            let samples = do vec::filter(samples) |f| {
+                num::abs(*f - med) <= 3.0 * mad
+            };
+
+            debug!("%u samples, median %f, MAD=%f, %u survived filter",
+                   n_samples, med as float, mad as float,
+                   samples.len());
+
+            if samples.len() != 0 {
+                // If we have _any_ cluster of signal...
+                let curr_madp = samples.median_abs_dev_pct();
+                if self.ns_elapsed() > 1_000_000 &&
+                    (curr_madp < 1.0 ||
+                     num::abs(curr_madp - prev_madp) < 0.1) {
+                    return samples;
                 }
+                prev_madp = curr_madp;
 
-                magnitude *= 2;
+                if n_iter > 20_000_000 ||
+                    self.ns_elapsed() > 20_000_000 {
+                    return samples;
+                }
             }
+
+            magnitude *= 2;
         }
     }
+}
+
+pub mod bench {
+    use test::{BenchHarness, BenchSamples};
 
     pub fn benchmark(f: &fn(&mut BenchHarness)) -> BenchSamples {
 
diff --git a/src/libextra/time.rs b/src/libextra/time.rs
index 555563a0cd7..931a42d3c53 100644
--- a/src/libextra/time.rs
+++ b/src/libextra/time.rs
@@ -849,7 +849,7 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str {
     do io::with_str_reader(format) |rdr| {
         while !rdr.eof() {
             match rdr.read_char() {
-                '%' => buf += parse_type(rdr.read_char(), tm),
+                '%' => buf.push_str(parse_type(rdr.read_char(), tm)),
                 ch => buf.push_char(ch)
             }
         }
diff --git a/src/libextra/timer.rs b/src/libextra/timer.rs
index 71d8a5d81e7..e23f9113319 100644
--- a/src/libextra/timer.rs
+++ b/src/libextra/timer.rs
@@ -39,7 +39,7 @@ use core::libc;
  * * ch - a channel of type T to send a `val` on
  * * val - a value of type T to send over the provided `ch`
  */
-pub fn delayed_send<T:Owned>(iotask: &IoTask,
+pub fn delayed_send<T:Send>(iotask: &IoTask,
                               msecs: uint,
                               ch: &Chan<T>,
                               val: T) {
@@ -119,11 +119,12 @@ pub fn sleep(iotask: &IoTask, msecs: uint) {
  * on the provided port in the allotted timeout period, then the result will
  * be a `Some(T)`. If not, then `None` will be returned.
  */
-pub fn recv_timeout<T:Copy + Owned>(iotask: &IoTask,
+pub fn recv_timeout<T:Copy + Send>(iotask: &IoTask,
                                    msecs: uint,
                                    wait_po: &Port<T>)
                                    -> Option<T> {
-    let mut (timeout_po, timeout_ch) = stream::<()>();
+    let (timeout_po, timeout_ch) = stream::<()>();
+    let mut timeout_po = timeout_po;
     delayed_send(iotask, msecs, &timeout_ch, ());
 
     // XXX: Workaround due to ports and channels not being &mut. They should
diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs
index 33ec4ae94ba..d546b48f817 100644
--- a/src/libextra/treemap.rs
+++ b/src/libextra/treemap.rs
@@ -511,14 +511,14 @@ impl<K: TotalOrd, V> TreeNode<K, V> {
 
 fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
                             f: &fn(&'r K, &'r V) -> bool) -> bool {
-    node.iter().advance(|x| each(&x.left, f) && f(&x.key, &x.value) &&
-                            each(&x.right, f))
+    node.iter().advance(|x| each(&x.left,  |k,v| f(k,v)) && f(&x.key, &x.value) &&
+                            each(&x.right, |k,v| f(k,v)))
 }
 
 fn each_reverse<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
                                     f: &fn(&'r K, &'r V) -> bool) -> bool {
-    node.iter().advance(|x| each_reverse(&x.right, f) && f(&x.key, &x.value) &&
-                            each_reverse(&x.left, f))
+    node.iter().advance(|x| each_reverse(&x.right, |k,v| f(k,v)) && f(&x.key, &x.value) &&
+                            each_reverse(&x.left,  |k,v| f(k,v)))
 }
 
 fn mutate_values<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
@@ -527,9 +527,9 @@ fn mutate_values<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
     match *node {
       Some(~TreeNode{key: ref key, value: ref mut value, left: ref mut left,
                      right: ref mut right, _}) => {
-        if !mutate_values(left, f) { return false }
+        if !mutate_values(left,  |k,v| f(k,v)) { return false }
         if !f(key, value) { return false }
-        if !mutate_values(right, f) { return false }
+        if !mutate_values(right, |k,v| f(k,v)) { return false }
       }
       None => return false
     }
@@ -695,7 +695,6 @@ mod test_treemap {
 
     use core::rand::RngUtil;
     use core::rand;
-    use core::vec;
 
     #[test]
     fn find_empty() {
@@ -848,7 +847,7 @@ mod test_treemap {
 
             for 30.times {
                 let r = rng.gen_uint_range(0, ctrl.len());
-                let (key, _) = vec::remove(&mut ctrl, r);
+                let (key, _) = ctrl.remove(r);
                 assert!(map.remove(&key));
                 check_structure(&map);
                 check_equal(ctrl, &map);
diff --git a/src/libextra/uv_global_loop.rs b/src/libextra/uv_global_loop.rs
index 286863bef64..f1dde1b8cb4 100644
--- a/src/libextra/uv_global_loop.rs
+++ b/src/libextra/uv_global_loop.rs
@@ -150,9 +150,7 @@ mod test {
             let hl_loop = &get_gl();
             do iotask::interact(hl_loop) |_loop_ptr| {
                 debug!(~"closing timer");
-                unsafe {
-                    ll::close(timer_ptr, simple_timer_close_cb);
-                }
+                ll::close(timer_ptr, simple_timer_close_cb);
                 debug!(~"about to deref exit_ch_ptr");
                 debug!(~"after msg sent on deref'd exit_ch");
             };
@@ -169,24 +167,22 @@ mod test {
             let timer_handle = ll::timer_t();
             let timer_ptr: *ll::uv_timer_t = &timer_handle;
             do iotask::interact(iotask) |loop_ptr| {
-                unsafe {
-                    debug!(~"user code inside interact loop!!!");
-                    let init_status = ll::timer_init(loop_ptr, timer_ptr);
-                    if(init_status == 0i32) {
-                        ll::set_data_for_uv_handle(
-                            timer_ptr as *libc::c_void,
-                            exit_ch_ptr);
-                        let start_status = ll::timer_start(timer_ptr,
-                                                           simple_timer_cb,
-                                                           1u, 0u);
-                        if(start_status != 0i32) {
-                            fail!("failure on ll::timer_start()");
-                        }
-                    }
-                    else {
-                        fail!("failure on ll::timer_init()");
+                debug!(~"user code inside interact loop!!!");
+                let init_status = ll::timer_init(loop_ptr, timer_ptr);
+                if(init_status == 0i32) {
+                    ll::set_data_for_uv_handle(
+                        timer_ptr as *libc::c_void,
+                        exit_ch_ptr);
+                    let start_status = ll::timer_start(timer_ptr,
+                                                       simple_timer_cb,
+                                                       1u, 0u);
+                    if(start_status != 0i32) {
+                        fail!("failure on ll::timer_start()");
                     }
                 }
+                else {
+                    fail!("failure on ll::timer_init()");
+                }
             };
             exit_po.recv();
             debug!(
diff --git a/src/libextra/uv_ll.rs b/src/libextra/uv_ll.rs
index 744f4555d5c..58b477d4ccf 100644
--- a/src/libextra/uv_ll.rs
+++ b/src/libextra/uv_ll.rs
@@ -1767,9 +1767,7 @@ mod test {
         mod impl64 {
             #[test]
             fn test_uv_ll_tcp_server_and_request() {
-                unsafe {
-                    super::super::impl_uv_tcp_server_and_request();
-                }
+                super::super::impl_uv_tcp_server_and_request();
             }
         }
         #[cfg(target_arch="x86")]
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index a014293f063..4d4f3c3a49b 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -107,7 +107,7 @@ struct WorkKey {
 impl to_bytes::IterBytes for WorkKey {
     #[inline]
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.kind.iter_bytes(lsb0, f) && self.name.iter_bytes(lsb0, f)
+        self.kind.iter_bytes(lsb0, |b| f(b)) && self.name.iter_bytes(lsb0, |b| f(b))
     }
 }
 
@@ -272,7 +272,7 @@ impl Context {
         }
     }
 
-    pub fn prep<T:Owned +
+    pub fn prep<T:Send +
                   Encodable<json::Encoder> +
                   Decodable<json::Decoder>>(@self, // FIXME(#5121)
                                             fn_name:&str,
@@ -292,7 +292,7 @@ trait TPrep {
     fn declare_input(&mut self, kind:&str, name:&str, val:&str);
     fn is_fresh(&self, cat:&str, kind:&str, name:&str, val:&str) -> bool;
     fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool;
-    fn exec<T:Owned +
+    fn exec<T:Send +
               Encodable<json::Encoder> +
               Decodable<json::Decoder>>( // FIXME(#5121)
         &self, blk: ~fn(&Exec) -> T) -> Work<T>;
@@ -328,7 +328,7 @@ impl TPrep for Prep {
         return true;
     }
 
-    fn exec<T:Owned +
+    fn exec<T:Send +
               Encodable<json::Encoder> +
               Decodable<json::Decoder>>( // FIXME(#5121)
             &self, blk: ~fn(&Exec) -> T) -> Work<T> {
@@ -365,7 +365,7 @@ impl TPrep for Prep {
     }
 }
 
-impl<T:Owned +
+impl<T:Send +
        Encodable<json::Encoder> +
        Decodable<json::Decoder>> Work<T> { // FIXME(#5121)
     pub fn new(p: @mut Prep, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
@@ -374,7 +374,7 @@ impl<T:Owned +
 }
 
 // FIXME (#3724): movable self. This should be in impl Work.
-fn unwrap<T:Owned +
+fn unwrap<T:Send +
             Encodable<json::Encoder> +
             Decodable<json::Decoder>>( // FIXME(#5121)
         w: Work<T>) -> T {
diff --git a/src/librust/rust.rs b/src/librust/rust.rs
index 68427745ff5..ba5e592b605 100644
--- a/src/librust/rust.rs
+++ b/src/librust/rust.rs
@@ -57,13 +57,13 @@ impl ValidUsage {
 }
 
 enum Action<'self> {
-    Call(&'self fn(args: &[~str]) -> ValidUsage),
-    CallMain(&'static str, &'self fn()),
+    Call(&'self fn:Copy(args: &[~str]) -> ValidUsage),
+    CallMain(&'static str, &'self fn:Copy()),
 }
 
 enum UsageSource<'self> {
     UsgStr(&'self str),
-    UsgCall(&'self fn()),
+    UsgCall(&'self fn:Copy()),
 }
 
 struct Command<'self> {
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 01ad3507b83..af23696cbc1 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -19,6 +19,7 @@ use lib;
 use metadata::common::LinkMeta;
 use metadata::{encoder, csearch, cstore};
 use middle::trans::context::CrateContext;
+use middle::trans::common::gensym_name;
 use middle::ty;
 use util::ppaux;
 
@@ -37,6 +38,7 @@ use syntax::ast;
 use syntax::ast_map::{path, path_mod, path_name};
 use syntax::attr;
 use syntax::print::pprust;
+use syntax::parse::token;
 
 #[deriving(Eq)]
 pub enum output_type {
@@ -640,15 +642,15 @@ pub fn sanitize(s: &str) -> ~str {
     for s.iter().advance |c| {
         match c {
             // Escape these with $ sequences
-            '@' => result += "$SP$",
-            '~' => result += "$UP$",
-            '*' => result += "$RP$",
-            '&' => result += "$BP$",
-            '<' => result += "$LT$",
-            '>' => result += "$GT$",
-            '(' => result += "$LP$",
-            ')' => result += "$RP$",
-            ',' => result += "$C$",
+            '@' => result.push_str("$SP$"),
+            '~' => result.push_str("$UP$"),
+            '*' => result.push_str("$RP$"),
+            '&' => result.push_str("$BP$"),
+            '<' => result.push_str("$LT$"),
+            '>' => result.push_str("$GT$"),
+            '(' => result.push_str("$LP$"),
+            ')' => result.push_str("$RP$"),
+            ',' => result.push_str("$C$"),
 
             // '.' doesn't occur in types and functions, so reuse it
             // for ':'
@@ -684,12 +686,14 @@ pub fn mangle(sess: Session, ss: path) -> ~str {
     let mut n = ~"_ZN"; // Begin name-sequence.
 
     for ss.iter().advance |s| {
-        match *s { path_name(s) | path_mod(s) => {
-          let sani = sanitize(sess.str_of(s));
-          n += fmt!("%u%s", sani.len(), sani);
-        } }
+        match *s {
+            path_name(s) | path_mod(s) => {
+                let sani = sanitize(sess.str_of(s));
+                n.push_str(fmt!("%u%s", sani.len(), sani));
+            }
+        }
     }
-    n += "E"; // End name-sequence.
+    n.push_char('E'); // End name-sequence.
     n
 }
 
@@ -731,22 +735,22 @@ pub fn mangle_internal_name_by_type_and_seq(ccx: &mut CrateContext,
     return mangle(ccx.sess,
         ~[path_name(ccx.sess.ident_of(s)),
           path_name(ccx.sess.ident_of(hash)),
-          path_name((ccx.names)(name))]);
+          path_name(gensym_name(name))]);
 }
 
 pub fn mangle_internal_name_by_path_and_seq(ccx: &mut CrateContext,
-                                            path: path,
+                                            mut path: path,
                                             flav: &str) -> ~str {
-    mangle(ccx.sess,
-           vec::append_one(path, path_name((ccx.names)(flav))))
+    path.push(path_name(gensym_name(flav)));
+    mangle(ccx.sess, path)
 }
 
 pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str {
     mangle(ccx.sess, path)
 }
 
-pub fn mangle_internal_name_by_seq(ccx: &mut CrateContext, flav: &str) -> ~str {
-    fmt!("%s_%u", flav, (ccx.names)(flav).name)
+pub fn mangle_internal_name_by_seq(_ccx: &mut CrateContext, flav: &str) -> ~str {
+    return fmt!("%s_%u", flav, token::gensym(flav));
 }
 
 
diff --git a/src/librustc/back/passes.rs b/src/librustc/back/passes.rs
index fa261a977f5..d2b4c87c744 100644
--- a/src/librustc/back/passes.rs
+++ b/src/librustc/back/passes.rs
@@ -60,90 +60,109 @@ impl PassManager {
     }
 }
 
-pub fn create_standard_passes(level:OptLevel) -> ~[~str] {
-    let mut passes = ~[~"strip-dead-prototypes"];
-
-    if level == No {
-        passes.push(~"always-inline");
-        return passes;
+pub fn create_standard_passes(level: OptLevel) -> ~[~str] {
+    let mut passes = ~[];
+
+    // mostly identical to clang 3.3, all differences are documented with comments
+
+    if level != No {
+        passes.push(~"targetlibinfo");
+        passes.push(~"no-aa");
+        // "tbaa" omitted, we don't emit clang-style type-based alias analysis information
+        passes.push(~"basicaa");
+        passes.push(~"globalopt");
+        passes.push(~"ipsccp");
+        passes.push(~"deadargelim");
+        passes.push(~"instcombine");
+        passes.push(~"simplifycfg");
     }
 
-    passes.push(~"targetlibinfo");
-
-    passes.push(~"scev-aa");
-    passes.push(~"basicaa");
-
-    passes.push(~"instcombine");
-    passes.push(~"simplifycfg");
-    passes.push(~"scalarrepl-ssa");
-    passes.push(~"early-cse");
-
-    passes.push(~"globalopt");
-    passes.push(~"ipsccp");
-    passes.push(~"deadargelim");
-    passes.push(~"instcombine");
-    passes.push(~"simplifycfg");
+    passes.push(~"basiccg");
 
-    passes.push(~"prune-eh");
-
-    passes.push(~"inline");
-
-    passes.push(~"functionattrs");
-
-    if level == Aggressive {
-        passes.push(~"argpromotion");
+    if level != No {
+        passes.push(~"prune-eh");
     }
 
-    passes.push(~"scalarrepl-ssa");
-    passes.push(~"early-cse");
-    passes.push(~"simplify-libcalls");
-    passes.push(~"jump-threading");
-    passes.push(~"correlated-propagation");
-    passes.push(~"simplifycfg");
-    passes.push(~"instcombine");
-
-    passes.push(~"tailcallelim");
-    passes.push(~"simplifycfg");
-    passes.push(~"reassociate");
-    passes.push(~"loop-rotate");
-    passes.push(~"licm");
-
-    passes.push(~"lcssa");
-    passes.push(~"loop-unswitch");
+    passes.push(~"inline-cost");
 
-    passes.push(~"instcombine");
-    passes.push(~"indvars");
-    passes.push(~"loop-idiom");
-    passes.push(~"loop-deletion");
-
-    if level == Aggressive {
-        passes.push(~"loop-vectorize");
+    if level == No || level == Less {
+        passes.push(~"always-inline");
+    } else {
+        passes.push(~"inline");
     }
 
-    passes.push(~"loop-unroll");
-
-    if level != Less {
-        passes.push(~"gvn");
+    if level != No {
+        passes.push(~"functionattrs");
+        if level == Aggressive {
+            passes.push(~"argpromotion");
+        }
+        passes.push(~"sroa");
+        passes.push(~"domtree");
+        passes.push(~"early-cse");
+        passes.push(~"simplify-libcalls");
+        passes.push(~"lazy-value-info");
+        passes.push(~"jump-threading");
+        passes.push(~"correlated-propagation");
+        passes.push(~"simplifycfg");
+        passes.push(~"instcombine");
+        passes.push(~"tailcallelim");
+        passes.push(~"simplifycfg");
+        passes.push(~"reassociate");
+        passes.push(~"domtree");
+        passes.push(~"loops");
+        passes.push(~"loop-simplify");
+        passes.push(~"lcssa");
+        passes.push(~"loop-rotate");
+        passes.push(~"licm");
+        passes.push(~"lcssa");
+        passes.push(~"loop-unswitch");
+        passes.push(~"instcombine");
+        passes.push(~"scalar-evolution");
+        passes.push(~"loop-simplify");
+        passes.push(~"lcssa");
+        passes.push(~"indvars");
+        passes.push(~"loop-idiom");
+        passes.push(~"loop-deletion");
+        if level == Aggressive {
+            passes.push(~"loop-simplify");
+            passes.push(~"lcssa");
+            passes.push(~"loop-vectorize");
+            passes.push(~"loop-simplify");
+            passes.push(~"lcssa");
+            passes.push(~"scalar-evolution");
+            passes.push(~"loop-simplify");
+            passes.push(~"lcssa");
+        }
+        if level != Less {
+            passes.push(~"loop-unroll");
+            passes.push(~"memdep");
+            passes.push(~"gvn");
+        }
+        passes.push(~"memdep");
+        passes.push(~"memcpyopt");
+        passes.push(~"sccp");
+        passes.push(~"instcombine");
+        passes.push(~"lazy-value-info");
+        passes.push(~"jump-threading");
+        passes.push(~"correlated-propagation");
+        passes.push(~"domtree");
+        passes.push(~"memdep");
+        passes.push(~"dse");
+        passes.push(~"adce");
+        passes.push(~"simplifycfg");
+        passes.push(~"instcombine");
+        // clang does `strip-dead-prototypes` here, since it does not emit them
     }
 
-    passes.push(~"memcpyopt");
-    passes.push(~"sccp");
-
-    passes.push(~"instcombine");
-    passes.push(~"jump-threading");
-    passes.push(~"correlated-propagation");
-    passes.push(~"dse");
-
-    passes.push(~"adce");
-    passes.push(~"simplifycfg");
-    passes.push(~"instsimplify");
+    // rustc emits dead prototypes, so always ask LLVM to strip them
+    passes.push(~"strip-dead-prototypes");
 
     if level != Less {
         passes.push(~"globaldce");
         passes.push(~"constmerge");
     }
 
-    return passes;
+    passes
 }
 
 pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~str]) {
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index 4657c069c21..dce2b7fe3df 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -154,7 +154,7 @@ pub fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
     let mut path = ~[];
     for uint::range(start_idx, len1 - 1) |_i| { path.push(~".."); };
 
-    path.push_all(vec::slice(split2, start_idx, len2 - 1));
+    path.push_all(split2.slice(start_idx, len2 - 1));
 
     return if !path.is_empty() {
         Path("").push_many(path)
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 2229a85836a..18693b52fc8 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -19,7 +19,7 @@ use front;
 use lib::llvm::llvm;
 use metadata::{creader, cstore, filesearch};
 use metadata;
-use middle::{trans, freevars, kind, ty, typeck, lint, astencode};
+use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
 use middle;
 use util::common::time;
 use util::ppaux;
@@ -299,10 +299,16 @@ pub fn compile_rest(sess: Session,
         time(time_passes, ~"kind checking", ||
              kind::check_crate(ty_cx, method_map, crate));
 
+        let reachable_map =
+            time(time_passes, ~"reachability checking", ||
+                reachable::find_reachable(ty_cx, method_map, crate));
+
         time(time_passes, ~"lint checking", ||
              lint::check_crate(ty_cx, crate));
 
-        if phases.to == cu_no_trans { return (Some(crate), Some(ty_cx)); }
+        if phases.to == cu_no_trans {
+            return (Some(crate), Some(ty_cx));
+        }
 
         let maps = astencode::Maps {
             root_map: root_map,
@@ -315,9 +321,13 @@ pub fn compile_rest(sess: Session,
 
         let outputs = outputs.get_ref();
         time(time_passes, ~"translation", ||
-             trans::base::trans_crate(sess, crate, ty_cx,
+             trans::base::trans_crate(sess,
+                                      crate,
+                                      ty_cx,
                                       &outputs.obj_filename,
-                                      exp_map2, maps))
+                                      exp_map2,
+                                      reachable_map,
+                                      maps))
     };
 
     let outputs = outputs.get_ref();
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index b5eb351a8a5..9459116307d 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -45,32 +45,33 @@ pub struct config {
     float_type: float_ty
 }
 
-pub static verbose: uint = 1 << 0;
-pub static time_passes: uint = 1 << 1;
-pub static count_llvm_insns: uint = 1 << 2;
-pub static time_llvm_passes: uint = 1 << 3;
-pub static trans_stats: uint = 1 << 4;
-pub static asm_comments: uint = 1 << 5;
-pub static no_verify: uint = 1 << 6;
-pub static trace: uint = 1 << 7;
-pub static coherence: uint = 1 << 8;
-pub static borrowck_stats: uint = 1 << 9;
-pub static borrowck_note_pure: uint = 1 << 10;
-pub static borrowck_note_loan: uint = 1 << 11;
-pub static no_landing_pads: uint = 1 << 12;
-pub static debug_llvm: uint = 1 << 13;
-pub static count_type_sizes: uint = 1 << 14;
-pub static meta_stats: uint = 1 << 15;
-pub static no_opt: uint = 1 << 16;
+pub static verbose:                 uint = 1 <<  0;
+pub static time_passes:             uint = 1 <<  1;
+pub static count_llvm_insns:        uint = 1 <<  2;
+pub static time_llvm_passes:        uint = 1 <<  3;
+pub static trans_stats:             uint = 1 <<  4;
+pub static asm_comments:            uint = 1 <<  5;
+pub static no_verify:               uint = 1 <<  6;
+pub static trace:                   uint = 1 <<  7;
+pub static coherence:               uint = 1 <<  8;
+pub static borrowck_stats:          uint = 1 <<  9;
+pub static borrowck_note_pure:      uint = 1 << 10;
+pub static borrowck_note_loan:      uint = 1 << 11;
+pub static no_landing_pads:         uint = 1 << 12;
+pub static debug_llvm:              uint = 1 << 13;
+pub static count_type_sizes:        uint = 1 << 14;
+pub static meta_stats:              uint = 1 << 15;
+pub static no_opt:                  uint = 1 << 16;
 pub static no_monomorphic_collapse: uint = 1 << 17;
-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 statik: uint = 1 << 22;
-pub static print_link_args: uint = 1 << 23;
-pub static no_debug_borrows: uint = 1 << 24;
-pub static lint_llvm : uint = 1 << 25;
+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 statik:                  uint = 1 << 22;
+pub static print_link_args:         uint = 1 << 23;
+pub static no_debug_borrows:        uint = 1 << 24;
+pub static lint_llvm:               uint = 1 << 25;
+pub static once_fns:                uint = 1 << 26;
 
 pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
     ~[(~"verbose", ~"in general, enable more debug printouts", verbose),
@@ -112,6 +113,9 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
      (~"lint-llvm",
       ~"Run the LLVM lint pass on the pre-optimization IR",
       lint_llvm),
+     (~"once-fns",
+      ~"Allow 'once fn' closures to deinitialize captured variables",
+      once_fns),
     ]
 }
 
@@ -293,6 +297,7 @@ impl Session_ {
     pub fn debug_borrows(@self) -> bool {
         self.opts.optimize == No && !self.debugging_opt(no_debug_borrows)
     }
+    pub fn once_fns(@self) -> bool { self.debugging_opt(once_fns) }
 
     // pointless function, now...
     pub fn str_of(@self, id: ast::ident) -> @str {
@@ -403,8 +408,12 @@ mod test {
 
     fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate {
         let mut attrs = ~[];
-        if with_bin { attrs += [make_crate_type_attr(@"bin")]; }
-        if with_lib { attrs += [make_crate_type_attr(@"lib")]; }
+        if with_bin {
+            attrs.push(make_crate_type_attr(@"bin"));
+        }
+        if with_lib {
+            attrs.push(make_crate_type_attr(@"lib"));
+        }
         @codemap::respan(codemap::dummy_sp(), ast::crate_ {
             module: ast::_mod { view_items: ~[], items: ~[] },
             attrs: attrs,
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index d7f33dcf0d0..41349d9c085 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -2149,18 +2149,24 @@ impl TypeNames {
         self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
     }
 
-    pub fn type_to_str(&self, ty: Type) -> ~str {
+    // We have a depth count, because we seem to make infinite types.
+    pub fn type_to_str_depth(&self, ty: Type, depth: int) -> ~str {
         match self.find_name(&ty) {
             option::Some(name) => return name.to_owned(),
             None => ()
         }
 
+        if depth == 0 {
+            return ~"###";
+        }
+
         unsafe {
             let kind = ty.kind();
 
             match kind {
                 Void => ~"Void",
                 Half => ~"Half",
+                Float => ~"Float",
                 Double => ~"Double",
                 X86_FP80 => ~"X86_FP80",
                 FP128 => ~"FP128",
@@ -2175,24 +2181,25 @@ impl TypeNames {
                 Function => {
                     let out_ty = ty.return_type();
                     let args = ty.func_params();
-                    let args = args.map(|&ty| self.type_to_str(ty)).connect(", ");
-                    let out_ty = self.type_to_str(out_ty);
+                    let args =
+                        args.map(|&ty| self.type_to_str_depth(ty, depth-1)).connect(", ");
+                    let out_ty = self.type_to_str_depth(out_ty, depth-1);
                     fmt!("fn(%s) -> %s", args, out_ty)
                 }
                 Struct => {
                     let tys = ty.field_types();
-                    let tys = tys.map(|&ty| self.type_to_str(ty)).connect(", ");
+                    let tys = tys.map(|&ty| self.type_to_str_depth(ty, depth-1)).connect(", ");
                     fmt!("{%s}", tys)
                 }
                 Array => {
                     let el_ty = ty.element_type();
-                    let el_ty = self.type_to_str(el_ty);
+                    let el_ty = self.type_to_str_depth(el_ty, depth-1);
                     let len = ty.array_length();
                     fmt!("[%s x %u]", el_ty, len)
                 }
                 Pointer => {
                     let el_ty = ty.element_type();
-                    let el_ty = self.type_to_str(el_ty);
+                    let el_ty = self.type_to_str_depth(el_ty, depth-1);
                     fmt!("*%s", el_ty)
                 }
                 _ => fail!("Unknown Type Kind (%u)", kind as uint)
@@ -2200,6 +2207,10 @@ impl TypeNames {
         }
     }
 
+    pub fn type_to_str(&self, ty: Type) -> ~str {
+        self.type_to_str_depth(ty, 30)
+    }
+
     pub fn val_to_str(&self, val: ValueRef) -> ~str {
         unsafe {
             let ty = Type::from_ref(llvm::LLVMTypeOf(val));
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index f487c73372f..e7725436f2b 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -176,6 +176,10 @@ pub static tag_item_method_tps: uint = 0x7b;
 pub static tag_item_method_fty: uint = 0x7c;
 pub static tag_item_method_transformed_self_ty: uint = 0x7d;
 
+pub static tag_mod_child: uint = 0x7e;
+pub static tag_misc_info: uint = 0x7f;
+pub static tag_misc_info_crate_items: uint = 0x80;
+
 pub struct LinkMeta {
     name: @str,
     vers: @str,
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index bfc5d512b37..4ede9f96f1f 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -97,18 +97,14 @@ pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id)
     return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx)
 }
 
-pub fn get_impls_for_mod(cstore: @mut cstore::CStore, def: ast::def_id,
-                         name: Option<ast::ident>)
-                      -> @~[@resolve::Impl] {
-    let cdata = cstore::get_crate_data(cstore, def.crate);
-    do decoder::get_impls_for_mod(cstore.intr, cdata, def.node, name) |cnum| {
-        cstore::get_crate_data(cstore, cnum)
-    }
+/// Returns information about the given implementation.
+pub fn get_impl(cstore: @mut cstore::CStore, impl_def_id: ast::def_id)
+                -> resolve::Impl {
+    let cdata = cstore::get_crate_data(cstore, impl_def_id.crate);
+    decoder::get_impl(cstore.intr, cdata, impl_def_id.node)
 }
 
-pub fn get_method(tcx: ty::ctxt,
-                  def: ast::def_id) -> ty::Method
-{
+pub fn get_method(tcx: ty::ctxt, 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)
 }
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 30f0a52b4e5..69faf519bc2 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -60,7 +60,7 @@ fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: uint) ->
     let belt = tag_index_buckets_bucket_elt;
     for reader::tagged_docs(tagged_doc.doc, belt) |elt| {
         let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4u) as uint;
-        if eq_fn(vec::slice(*elt.data, elt.start + 4u, elt.end)) {
+        if eq_fn(elt.data.slice(elt.start + 4u, elt.end)) {
             return Some(reader::doc_at(d.data, pos).doc);
         }
     };
@@ -72,7 +72,7 @@ pub type GetCrateDataCb<'self> = &'self fn(ast::crate_num) -> cmd;
 pub fn maybe_find_item(item_id: int, items: ebml::Doc) -> Option<ebml::Doc> {
     fn eq_item(bytes: &[u8], item_id: int) -> bool {
         return io::u64_from_be_bytes(
-            vec::slice(bytes, 0u, 4u), 0u, 4u) as int
+            bytes.slice(0u, 4u), 0u, 4u) as int
             == item_id;
     }
     lookup_hash(items,
@@ -458,64 +458,192 @@ pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) -> bool {
     return true;
 }
 
-/// Iterates over all the paths in the given crate.
-pub fn each_path(intr: @ident_interner,
-                 cdata: cmd,
-                 get_crate_data: GetCrateDataCb,
-                 f: &fn(&str, def_like, ast::visibility) -> bool)
-                 -> bool {
-    // FIXME #4572: This function needs to be nuked, as it's impossible to make fast.
-    // It's the source of most of the performance problems when compiling small crates.
+struct EachItemContext<'self> {
+    intr: @ident_interner,
+    cdata: cmd,
+    get_crate_data: GetCrateDataCb<'self>,
+    path_builder: &'self mut ~str,
+    callback: &'self fn(&str, def_like, ast::visibility) -> bool,
+}
 
-    let root = reader::Doc(cdata.data);
-    let items = reader::get_doc(root, tag_items);
-    let items_data = reader::get_doc(items, tag_items_data);
-
-    // First, go through all the explicit items.
-    for reader::tagged_docs(items_data, tag_items_data_item) |item_doc| {
-        let path = ast_map::path_to_str(item_path(item_doc), intr);
-        let path_is_empty = path.is_empty();
-        if !path_is_empty {
-            // Extract the def ID.
-            let def_id = item_def_id(item_doc, cdata);
-
-            // Construct the def for this item.
-            debug!("(each_path) yielding explicit item: %s", path);
-            let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);
-
-            let vis = item_visibility(item_doc);
-
-            // Hand the information off to the iteratee.
-            if !f(path, def_like, vis) {
-                return false;
+impl<'self> EachItemContext<'self> {
+    // Pushes the given name and returns the old length.
+    fn push_name(&mut self, string: &str) -> uint {
+        let path_len = self.path_builder.len();
+        if path_len != 0 {
+            self.path_builder.push_str("::")
+        }
+        self.path_builder.push_str(string);
+        path_len
+    }
+
+    // Pops the given name.
+    fn pop_name(&mut self, old_len: uint) {
+        // XXX(pcwalton): There's no safe function to do this. :(
+        unsafe {
+            str::raw::set_len(self.path_builder, old_len)
+        }
+    }
+
+    fn process_item_and_pop_name(&mut self,
+                                 doc: ebml::Doc,
+                                 def_id: ast::def_id,
+                                 old_len: uint)
+                                 -> bool {
+        let def_like = item_to_def_like(doc, def_id, self.cdata.cnum);
+        match def_like {
+            dl_def(def) => {
+                debug!("(iterating over each item of a module) processing \
+                        `%s` (def %?)",
+                       *self.path_builder,
+                       def);
+            }
+            _ => {
+                debug!("(iterating over each item of a module) processing \
+                        `%s` (%d:%d)",
+                       *self.path_builder,
+                       def_id.crate,
+                       def_id.node);
             }
         }
 
-        // If this is a module, find the reexports.
-        for each_reexport(item_doc) |reexport_doc| {
-            let def_id_doc =
-                reader::get_doc(reexport_doc,
-                                tag_items_data_item_reexport_def_id);
-            let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
-            let def_id = translate_def_id(cdata, def_id);
-
-            let reexport_name_doc =
-                reader::get_doc(reexport_doc,
-                                tag_items_data_item_reexport_name);
-            let reexport_name = reexport_name_doc.as_str_slice();
-
-            let reexport_path;
-            if path_is_empty {
-                reexport_path = reexport_name.to_owned();
+        let vis = item_visibility(doc);
+
+        let mut continue = (self.callback)(*self.path_builder, def_like, vis);
+
+        let family = item_family(doc);
+        if family == ForeignMod {
+            // These are unnamed; pop the name now.
+            self.pop_name(old_len)
+        }
+
+        if continue {
+            // Recurse if necessary.
+            match family {
+                Mod | ForeignMod | Trait | Impl => {
+                    continue = self.each_item_of_module(def_id);
+                }
+                ImmStatic | MutStatic | Struct | UnsafeFn | Fn | ForeignFn |
+                UnsafeStaticMethod | StaticMethod | Type | ForeignType |
+                Variant | Enum | PublicField | PrivateField |
+                InheritedField => {}
+            }
+        }
+
+        if family != ForeignMod {
+            self.pop_name(old_len)
+        }
+
+        continue
+    }
+
+    fn each_item_of_module(&mut self, def_id: ast::def_id) -> bool {
+        // This item might not be in this crate. If it's not, look it up.
+        let (cdata, items) = if def_id.crate == self.cdata.cnum {
+            let items = reader::get_doc(reader::Doc(self.cdata.data),
+                                        tag_items);
+            (self.cdata, items)
+        } else {
+            let crate_data = (self.get_crate_data)(def_id.crate);
+            let root = reader::Doc(crate_data.data);
+            (crate_data, reader::get_doc(root, tag_items))
+        };
+
+        // Look up the item.
+        let item_doc = match maybe_find_item(def_id.node, items) {
+            None => return false,
+            Some(item_doc) => item_doc,
+        };
+
+        self.each_child_of_module_or_crate(item_doc)
+    }
+
+    fn each_child_of_module_or_crate(&mut self, item_doc: ebml::Doc) -> bool {
+        let mut continue = true;
+
+        // Iterate over all children.
+        for reader::tagged_docs(item_doc, tag_mod_child) |child_info_doc| {
+            let child_def_id = reader::with_doc_data(child_info_doc,
+                                                     parse_def_id);
+            let child_def_id = translate_def_id(self.cdata, child_def_id);
+
+            // This item may be in yet another crate, if it was the child of
+            // a reexport.
+            let other_crates_items = if child_def_id.crate ==
+                    self.cdata.cnum {
+                reader::get_doc(reader::Doc(self.cdata.data), tag_items)
             } else {
-                reexport_path = path + "::" + reexport_name;
+                let crate_data = (self.get_crate_data)(child_def_id.crate);
+                let root = reader::Doc(crate_data.data);
+                reader::get_doc(root, tag_items)
+            };
+
+            debug!("(iterating over each item of a module) looking up item \
+                    %d:%d in `%s`, crate %d",
+                   child_def_id.crate,
+                   child_def_id.node,
+                   *self.path_builder,
+                   self.cdata.cnum);
+
+            // Get the item.
+            match maybe_find_item(child_def_id.node, other_crates_items) {
+                None => {}
+                Some(child_item_doc) => {
+                    // Push the name.
+                    let child_name = item_name(self.intr, child_item_doc);
+                    debug!("(iterating over each item of a module) pushing \
+                            name `%s` onto `%s`",
+                           token::ident_to_str(&child_name),
+                           *self.path_builder);
+                    let old_len =
+                        self.push_name(token::ident_to_str(&child_name));
+
+                    // Process this item.
+                    continue = self.process_item_and_pop_name(child_item_doc,
+                                                              child_def_id,
+                                                              old_len);
+
+                    if !continue {
+                        break
+                    }
+                }
             }
+        }
+
+        if !continue {
+            return false
+        }
 
-            // This reexport may be in yet another crate
-            let other_crates_items = if def_id.crate == cdata.cnum {
-                items
+        // Iterate over reexports.
+        for each_reexport(item_doc) |reexport_doc| {
+            let def_id_doc = reader::get_doc(
+                reexport_doc,
+                tag_items_data_item_reexport_def_id);
+            let orig_def_id = reader::with_doc_data(def_id_doc, parse_def_id);
+
+            // NB: was "cdata"
+            let def_id = translate_def_id(self.cdata, orig_def_id);
+
+            let name_doc = reader::get_doc(reexport_doc,
+                                           tag_items_data_item_reexport_name);
+            let name = name_doc.as_str_slice();
+
+            // Push the name.
+            debug!("(iterating over each item of a module) pushing \
+                    reexported name `%s` onto `%s` (crate %d, orig %d, \
+                    in crate %d)",
+                   name,
+                   *self.path_builder,
+                   def_id.crate,
+                   orig_def_id.crate,
+                   self.cdata.cnum);
+            let old_len = self.push_name(name);
+
+            // This reexport may be in yet another crate.
+            let other_crates_items = if def_id.crate == self.cdata.cnum {
+                reader::get_doc(reader::Doc(self.cdata.data), tag_items)
             } else {
-                let crate_data = get_crate_data(def_id.crate);
+                let crate_data = (self.get_crate_data)(def_id.crate);
                 let root = reader::Doc(crate_data.data);
                 reader::get_doc(root, tag_items)
             };
@@ -523,29 +651,53 @@ pub fn each_path(intr: @ident_interner,
             // Get the item.
             match maybe_find_item(def_id.node, other_crates_items) {
                 None => {}
-                Some(item_doc) => {
-                    // Construct the def for this item.
-                    let def_like = item_to_def_like(item_doc,
-                                                    def_id,
-                                                    cdata.cnum);
-
-                    // Hand the information off to the iteratee.
-                    debug!("(each_path) yielding reexported \
-                           item: %s", reexport_path);
-
-                    if (!f(reexport_path, def_like, ast::public)) {
-                        return false;
-                    }
+                Some(reexported_item_doc) => {
+                    continue = self.process_item_and_pop_name(
+                        reexported_item_doc,
+                        def_id,
+                        old_len);
                 }
             }
+
+            if !continue {
+                break
+            }
         }
+
+        continue
     }
+}
 
-    return true;
+/// Iterates over all the paths in the given crate.
+pub fn each_path(intr: @ident_interner,
+                 cdata: cmd,
+                 get_crate_data: GetCrateDataCb,
+                 f: &fn(&str, def_like, ast::visibility) -> bool)
+                 -> bool {
+    // FIXME #4572: This function needs to be nuked, as it's impossible to
+    // make fast. It's the source of most of the performance problems when
+    // compiling small crates.
+
+    let root_doc = reader::Doc(cdata.data);
+    let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
+    let crate_items_doc = reader::get_doc(misc_info_doc,
+                                          tag_misc_info_crate_items);
+
+    let mut path_builder = ~"";
+
+    let mut context = EachItemContext {
+        intr: intr,
+        cdata: cdata,
+        get_crate_data: get_crate_data,
+        path_builder: &mut path_builder,
+        callback: f,
+    };
+
+    // Iterate over all top-level crate items.
+    context.each_child_of_module_or_crate(crate_items_doc)
 }
 
-pub fn get_item_path(cdata: cmd, id: ast::node_id)
-    -> ast_map::path {
+pub fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path {
     item_path(lookup_item(id, cdata.data))
 }
 
@@ -661,35 +813,20 @@ fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
     rslt
 }
 
-pub fn get_impls_for_mod(intr: @ident_interner,
-                         cdata: cmd,
-                         m_id: ast::node_id,
-                         name: Option<ast::ident>,
-                         get_cdata: &fn(ast::crate_num) -> cmd)
-                      -> @~[@resolve::Impl] {
+/// Returns information about the given implementation.
+pub fn get_impl(intr: @ident_interner, cdata: cmd, impl_id: ast::node_id)
+                -> resolve::Impl {
     let data = cdata.data;
-    let mod_item = lookup_item(m_id, data);
-    let mut result = ~[];
-    for reader::tagged_docs(mod_item, tag_mod_impl) |doc| {
-        let did = reader::with_doc_data(doc, parse_def_id);
-        let local_did = translate_def_id(cdata, did);
-        debug!("(get impls for mod) getting did %? for '%?'",
-               local_did, name);
-          // The impl may be defined in a different crate. Ask the caller
-          // to give us the metadata
-        let impl_cdata = get_cdata(local_did.crate);
-        let impl_data = impl_cdata.data;
-        let item = lookup_item(local_did.node, impl_data);
-        let nm = item_name(intr, item);
-        if match name { Some(n) => { n == nm } None => { true } } {
-           let base_tps = item_ty_param_count(item);
-           result.push(@resolve::Impl {
-                did: local_did, ident: nm,
-                methods: item_impl_methods(intr, impl_cdata, item, base_tps)
-            });
-        };
+    let impl_item = lookup_item(impl_id, data);
+    let base_tps = item_ty_param_count(impl_item);
+    resolve::Impl {
+        did: ast::def_id {
+            crate: cdata.cnum,
+            node: impl_id,
+        },
+        ident: item_name(intr, impl_item),
+        methods: item_impl_methods(intr, cdata, impl_item, base_tps),
     }
-    @result
 }
 
 pub fn get_method_name_and_explicit_self(
@@ -754,8 +891,7 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
 
         if item_method_sort(mth) != 'p' { loop; }
 
-        vec::push(&mut result,
-                  @get_method(intr, cdata, did.node, tcx));
+        result.push(@get_method(intr, cdata, did.node, tcx));
     }
 
     return result;
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index b96e96c9618..e394c8dcf92 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -16,14 +16,13 @@ use metadata::common::*;
 use metadata::cstore;
 use metadata::decoder;
 use metadata::tyencode;
-use middle::trans::reachable;
 use middle::ty::node_id_to_type;
 use middle::ty;
 use middle;
 use util::ppaux::ty_to_str;
 
 use core::hash::HashUtil;
-use core::hashmap::HashMap;
+use core::hashmap::{HashMap, HashSet};
 use core::int;
 use core::io;
 use core::str;
@@ -60,13 +59,13 @@ pub type encode_inlined_item<'self> = &'self fn(ecx: &EncodeContext,
 pub struct EncodeParams<'self> {
     diag: @span_handler,
     tcx: ty::ctxt,
-    reachable: reachable::map,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'self HashMap<ast::node_id, ~str>,
     discrim_symbols: &'self HashMap<ast::node_id, @str>,
     link_meta: &'self LinkMeta,
     cstore: @mut cstore::CStore,
-    encode_inlined_item: encode_inlined_item<'self>
+    encode_inlined_item: encode_inlined_item<'self>,
+    reachable: @mut HashSet<ast::node_id>,
 }
 
 struct Stats {
@@ -75,6 +74,7 @@ struct Stats {
     dep_bytes: uint,
     lang_item_bytes: uint,
     link_args_bytes: uint,
+    misc_bytes: uint,
     item_bytes: uint,
     index_bytes: uint,
     zero_bytes: uint,
@@ -87,14 +87,14 @@ pub struct EncodeContext<'self> {
     diag: @span_handler,
     tcx: ty::ctxt,
     stats: @mut Stats,
-    reachable: reachable::map,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'self HashMap<ast::node_id, ~str>,
     discrim_symbols: &'self HashMap<ast::node_id, @str>,
     link_meta: &'self LinkMeta,
     cstore: &'self cstore::CStore,
     encode_inlined_item: encode_inlined_item<'self>,
-    type_abbrevs: abbrev_map
+    type_abbrevs: abbrev_map,
+    reachable: @mut HashSet<ast::node_id>,
 }
 
 pub fn reachable(ecx: &EncodeContext, id: node_id) -> bool {
@@ -157,8 +157,8 @@ fn encode_trait_ref(ebml_w: &mut writer::Encoder,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        reachable: |a| r.contains(&a),
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+    };
 
     ebml_w.start_tag(tag);
     tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
@@ -185,8 +185,8 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        reachable: |a| r.contains(&a),
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+    };
     for params.iter().advance |param| {
         ebml_w.start_tag(tag);
         tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
@@ -218,8 +218,8 @@ pub fn write_type(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        reachable: |a| r.contains(&a),
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+    };
     tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
 }
 
@@ -231,8 +231,8 @@ pub fn write_vstore(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        reachable: |a| r.contains(&a),
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+    };
     tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
 }
 
@@ -264,8 +264,8 @@ fn encode_method_fty(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        reachable: |a| r.contains(&a),
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+    };
     tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
 
     ebml_w.end_tag();
@@ -473,12 +473,77 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
     }
 }
 
+/// Iterates through "auxiliary node IDs", which are node IDs that describe
+/// top-level items that are sub-items of the given item. Specifically:
+///
+/// * For enums, iterates through the node IDs of the variants.
+///
+/// * For newtype structs, iterates through the node ID of the constructor.
+fn each_auxiliary_node_id(item: @item, callback: &fn(node_id) -> bool)
+                          -> bool {
+    let mut continue = true;
+    match item.node {
+        item_enum(ref enum_def, _) => {
+            for enum_def.variants.iter().advance |variant| {
+                continue = callback(variant.node.id);
+                if !continue {
+                    break
+                }
+            }
+        }
+        item_struct(struct_def, _) => {
+            // If this is a newtype struct, return the constructor.
+            match struct_def.ctor_id {
+                Some(ctor_id) if struct_def.fields.len() > 0 &&
+                        struct_def.fields[0].node.kind ==
+                        ast::unnamed_field => {
+                    continue = callback(ctor_id);
+                }
+                _ => {}
+            }
+        }
+        _ => {}
+    }
+
+    continue
+}
+
+fn encode_reexports(ecx: &EncodeContext,
+                    ebml_w: &mut writer::Encoder,
+                    id: node_id,
+                    path: &[ast_map::path_elt]) {
+    debug!("(encoding info for module) encoding reexports for %d", id);
+    match ecx.reexports2.find(&id) {
+        Some(ref exports) => {
+            debug!("(encoding info for module) found reexports for %d", id);
+            for exports.iter().advance |exp| {
+                debug!("(encoding info for module) reexport '%s' for %d",
+                       exp.name, id);
+                ebml_w.start_tag(tag_items_data_item_reexport);
+                ebml_w.start_tag(tag_items_data_item_reexport_def_id);
+                ebml_w.wr_str(def_to_str(exp.def_id));
+                ebml_w.end_tag();
+                ebml_w.start_tag(tag_items_data_item_reexport_name);
+                ebml_w.wr_str(exp.name);
+                ebml_w.end_tag();
+                ebml_w.end_tag();
+                encode_reexported_static_methods(ecx, ebml_w, path, exp);
+            }
+        }
+        None => {
+            debug!("(encoding info for module) found no reexports for %d",
+                   id);
+        }
+    }
+}
+
 fn encode_info_for_mod(ecx: &EncodeContext,
                        ebml_w: &mut writer::Encoder,
                        md: &_mod,
                        id: node_id,
                        path: &[ast_map::path_elt],
-                       name: ident) {
+                       name: ident,
+                       vis: visibility) {
     ebml_w.start_tag(tag_items_data_item);
     encode_def_id(ebml_w, local_def(id));
     encode_family(ebml_w, 'm');
@@ -487,6 +552,16 @@ fn encode_info_for_mod(ecx: &EncodeContext,
 
     // Encode info about all the module children.
     for md.items.iter().advance |item| {
+        ebml_w.start_tag(tag_mod_child);
+        ebml_w.wr_str(def_to_str(local_def(item.id)));
+        ebml_w.end_tag();
+
+        for each_auxiliary_node_id(*item) |auxiliary_node_id| {
+            ebml_w.start_tag(tag_mod_child);
+            ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
+            ebml_w.end_tag();
+        }
+
         match item.node {
             item_impl(*) => {
                 let (ident, did) = (item.ident, item.id);
@@ -500,35 +575,16 @@ fn encode_info_for_mod(ecx: &EncodeContext,
                 ebml_w.wr_str(def_to_str(local_def(did)));
                 ebml_w.end_tag();
             }
-            _ => {} // FIXME #4573: Encode these too.
+            _ => {}
         }
     }
 
     encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
 
-    // Encode the reexports of this module.
-    debug!("(encoding info for module) encoding reexports for %d", id);
-    match ecx.reexports2.find(&id) {
-        Some(ref exports) => {
-            debug!("(encoding info for module) found reexports for %d", id);
-            for exports.iter().advance |exp| {
-                debug!("(encoding info for module) reexport '%s' for %d",
-                       exp.name, id);
-                ebml_w.start_tag(tag_items_data_item_reexport);
-                ebml_w.start_tag(tag_items_data_item_reexport_def_id);
-                ebml_w.wr_str(def_to_str(exp.def_id));
-                ebml_w.end_tag();
-                ebml_w.start_tag(tag_items_data_item_reexport_name);
-                ebml_w.wr_str(exp.name);
-                ebml_w.end_tag();
-                ebml_w.end_tag();
-                encode_reexported_static_methods(ecx, ebml_w, path, exp);
-            }
-        }
-        None => {
-            debug!("(encoding info for module) found no reexports for %d",
-                   id);
-        }
+    // Encode the reexports of this module, if this module is public.
+    if vis == public {
+        debug!("(encoding info for module) encoding reexports for %d", id);
+        encode_reexports(ecx, ebml_w, id, path);
     }
 
     ebml_w.end_tag();
@@ -780,13 +836,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
                         index: @mut ~[entry<int>],
                         path: &[ast_map::path_elt]) {
     let tcx = ecx.tcx;
-    let must_write =
-        match item.node {
-          item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) |
-          item_mod(*) | item_foreign_mod(*) | item_static(*) => true,
-          _ => false
-        };
-    if !must_write && !reachable(ecx, item.id) { return; }
 
     fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
                      index: @mut ~[entry<int>]) {
@@ -809,6 +858,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         }
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
+        encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
         ebml_w.end_tag();
@@ -821,6 +871,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         let tps_len = generics.ty_params.len();
         encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+        encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         encode_attributes(ebml_w, item.attrs);
         if tps_len > 0u || should_inline(item.attrs) {
@@ -832,15 +883,29 @@ fn encode_info_for_item(ecx: &EncodeContext,
       }
       item_mod(ref m) => {
         add_to_index();
-        encode_info_for_mod(ecx, ebml_w, m, item.id, path, item.ident);
+        encode_info_for_mod(ecx,
+                            ebml_w,
+                            m,
+                            item.id,
+                            path,
+                            item.ident,
+                            item.vis);
       }
-      item_foreign_mod(_) => {
+      item_foreign_mod(ref fm) => {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 'n');
         encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
+
+        // Encode all the items in this module.
+        for fm.items.iter().advance |foreign_item| {
+            ebml_w.start_tag(tag_mod_child);
+            ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
+            ebml_w.end_tag();
+        }
+
         ebml_w.end_tag();
       }
       item_ty(_, ref generics) => {
@@ -898,23 +963,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
 
-        // If this is a tuple- or enum-like struct, encode the type of the
-        // constructor.
-        if struct_def.fields.len() > 0 &&
-                struct_def.fields[0].node.kind == ast::unnamed_field {
-            let ctor_id = match struct_def.ctor_id {
-                Some(ctor_id) => ctor_id,
-                None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
-            };
-
-            encode_info_for_struct_ctor(ecx,
-                                        ebml_w,
-                                        path,
-                                        item.ident,
-                                        ctor_id,
-                                        index);
-        }
-
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
@@ -944,6 +992,23 @@ fn encode_info_for_item(ecx: &EncodeContext,
         let bkts = create_index(idx);
         encode_index(ebml_w, bkts, write_int);
         ebml_w.end_tag();
+
+        // If this is a tuple- or enum-like struct, encode the type of the
+        // constructor.
+        if struct_def.fields.len() > 0 &&
+                struct_def.fields[0].node.kind == ast::unnamed_field {
+            let ctor_id = match struct_def.ctor_id {
+                Some(ctor_id) => ctor_id,
+                None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
+            };
+
+            encode_info_for_struct_ctor(ecx,
+                                        ebml_w,
+                                        path,
+                                        item.ident,
+                                        ctor_id,
+                                        index);
+        }
       }
       item_impl(ref generics, opt_trait, ty, ref methods) => {
         add_to_index();
@@ -979,7 +1044,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
         // >:-<
         let mut impl_path = vec::append(~[], path);
-        impl_path += [ast_map::path_name(item.ident)];
+        impl_path.push(ast_map::path_name(item.ident));
 
         for methods.iter().advance |m| {
             index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
@@ -1008,6 +1073,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
             ebml_w.start_tag(tag_item_trait_method);
             encode_def_id(ebml_w, method_def_id);
             ebml_w.end_tag();
+
+            ebml_w.start_tag(tag_mod_child);
+            ebml_w.wr_str(def_to_str(method_def_id));
+            ebml_w.end_tag();
         }
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         for super_traits.iter().advance |ast_trait_ref| {
@@ -1092,7 +1161,6 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 index: @mut ~[entry<int>],
                                 path: ast_map::path,
                                 abi: AbiSet) {
-    if !reachable(ecx, nitem.id) { return; }
     index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
 
     ebml_w.start_tag(tag_items_data_item);
@@ -1102,6 +1170,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         encode_family(ebml_w, purity_fn_family(purity));
         encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
+        encode_name(ecx, ebml_w, nitem.ident);
         if abi.is_intrinsic() {
             (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem));
         } else {
@@ -1118,6 +1187,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         }
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
+        encode_name(ecx, ebml_w, nitem.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
       }
     }
@@ -1131,9 +1201,13 @@ fn encode_info_for_items(ecx: &EncodeContext,
     let index = @mut ~[];
     ebml_w.start_tag(tag_items_data);
     index.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() });
-    encode_info_for_mod(ecx, ebml_w, &crate.node.module,
-                        crate_node_id, [],
-                        syntax::parse::token::special_idents::invalid);
+    encode_info_for_mod(ecx,
+                        ebml_w,
+                        &crate.node.module,
+                        crate_node_id,
+                        [],
+                        syntax::parse::token::special_idents::invalid,
+                        public);
     let items = ecx.tcx.items;
 
     // See comment in `encode_side_tables_for_ii` in astencode
@@ -1162,6 +1236,12 @@ fn encode_info_for_items(ecx: &EncodeContext,
                 visit::visit_foreign_item(ni, (cx, v));
                 match items.get_copy(&ni.id) {
                     ast_map::node_foreign_item(_, abi, _, pt) => {
+                        debug!("writing foreign item %s::%s",
+                               ast_map::path_to_str(
+                                *pt,
+                                token::get_ident_interner()),
+                                token::ident_to_str(&ni.ident));
+
                         let mut ebml_w = copy ebml_w;
                         // See above
                         let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
@@ -1421,6 +1501,30 @@ fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
     ebml_w.end_tag();
 }
 
+fn encode_misc_info(ecx: &EncodeContext,
+                    crate: &crate,
+                    ebml_w: &mut writer::Encoder) {
+    ebml_w.start_tag(tag_misc_info);
+    ebml_w.start_tag(tag_misc_info_crate_items);
+    for crate.node.module.items.iter().advance |&item| {
+        ebml_w.start_tag(tag_mod_child);
+        ebml_w.wr_str(def_to_str(local_def(item.id)));
+        ebml_w.end_tag();
+
+        for each_auxiliary_node_id(item) |auxiliary_node_id| {
+            ebml_w.start_tag(tag_mod_child);
+            ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
+            ebml_w.end_tag();
+        }
+    }
+
+    // Encode reexports for the root module.
+    encode_reexports(ecx, ebml_w, 0, []);
+
+    ebml_w.end_tag();
+    ebml_w.end_tag();
+}
+
 fn encode_crate_dep(ecx: &EncodeContext,
                     ebml_w: &mut writer::Encoder,
                     dep: decoder::crate_dep) {
@@ -1460,29 +1564,39 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {
         dep_bytes: 0,
         lang_item_bytes: 0,
         link_args_bytes: 0,
+        misc_bytes: 0,
         item_bytes: 0,
         index_bytes: 0,
         zero_bytes: 0,
         total_bytes: 0,
         n_inlines: 0
     };
-    let EncodeParams{item_symbols, diag, tcx, reachable, reexports2,
-                     discrim_symbols, cstore, encode_inlined_item,
-                     link_meta, _} = parms;
+    let EncodeParams {
+        item_symbols,
+        diag,
+        tcx,
+        reexports2,
+        discrim_symbols,
+        cstore,
+        encode_inlined_item,
+        link_meta,
+        reachable,
+        _
+    } = parms;
     let type_abbrevs = @mut HashMap::new();
     let stats = @mut stats;
     let ecx = EncodeContext {
         diag: diag,
         tcx: tcx,
         stats: stats,
-        reachable: reachable,
         reexports2: reexports2,
         item_symbols: item_symbols,
         discrim_symbols: discrim_symbols,
         link_meta: link_meta,
         cstore: cstore,
         encode_inlined_item: encode_inlined_item,
-        type_abbrevs: type_abbrevs
+        type_abbrevs: type_abbrevs,
+        reachable: reachable,
      };
 
     let mut ebml_w = writer::Encoder(wr as @io::Writer);
@@ -1508,6 +1622,11 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {
     encode_link_args(&ecx, &mut ebml_w);
     ecx.stats.link_args_bytes = *wr.pos - i;
 
+    // Encode miscellaneous info.
+    i = *wr.pos;
+    encode_misc_info(&ecx, crate, &mut ebml_w);
+    ecx.stats.misc_bytes = *wr.pos - i;
+
     // Encode and index the items.
     ebml_w.start_tag(tag_items);
     i = *wr.pos;
@@ -1535,6 +1654,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {
         io::println(fmt!("       dep bytes: %u", ecx.stats.dep_bytes));
         io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
         io::println(fmt!(" link args bytes: %u", ecx.stats.link_args_bytes));
+        io::println(fmt!("      misc bytes: %u", ecx.stats.misc_bytes));
         io::println(fmt!("      item bytes: %u", ecx.stats.item_bytes));
         io::println(fmt!("     index bytes: %u", ecx.stats.index_bytes));
         io::println(fmt!("      zero bytes: %u", ecx.stats.zero_bytes));
@@ -1557,7 +1677,6 @@ pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
         diag: tcx.diag,
         ds: def_to_str,
         tcx: tcx,
-        reachable: |_id| false,
         abbrevs: tyencode::ac_no_abbrevs};
     do io::with_str_writer |wr| {
         tyencode::enc_ty(wr, cx, t);
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 6268932ba99..abfb5f7d4d4 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -48,7 +48,7 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
             debug!("filesearch: searching additional lib search paths [%?]",
                    self.addl_lib_search_paths.len());
             // a little weird
-            self.addl_lib_search_paths.iter().advance(f);
+            self.addl_lib_search_paths.iter().advance(|path| f(path));
 
             debug!("filesearch: searching target lib path");
             if !f(&make_target_lib_path(self.sysroot,
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index c3840c9c87f..22786581073 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -20,7 +20,6 @@ use middle::ty;
 
 use core::str;
 use core::uint;
-use core::vec;
 use syntax::abi::AbiSet;
 use syntax::abi;
 use syntax::ast;
@@ -190,11 +189,11 @@ fn parse_trait_store(st: &mut PState) -> ty::TraitStore {
 fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
     let self_r = parse_opt(st, |st| parse_region(st) );
 
-    let self_ty = parse_opt(st, |st| parse_ty(st, conv) );
+    let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
 
     assert_eq!(next(st), '[');
     let mut params: ~[ty::t] = ~[];
-    while peek(st) != ']' { params.push(parse_ty(st, conv)); }
+    while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
     st.pos = st.pos + 1u;
 
     return ty::substs {
@@ -262,15 +261,17 @@ fn parse_opt<T>(st: &mut PState, f: &fn(&mut PState) -> T) -> Option<T> {
 fn parse_str(st: &mut PState, term: char) -> ~str {
     let mut result = ~"";
     while peek(st) != term {
-        result += str::from_byte(next_byte(st));
+        unsafe {
+            str::raw::push_byte(&mut result, next_byte(st));
+        }
     }
     next(st);
     return result;
 }
 
 fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef {
-    let def = parse_def(st, NominalType, conv);
-    let substs = parse_substs(st, conv);
+    let def = parse_def(st, NominalType, |x,y| conv(x,y));
+    let substs = parse_substs(st, |x,y| conv(x,y));
     ty::TraitRef {def_id: def, substs: substs}
 }
 
@@ -300,18 +301,18 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       'c' => return ty::mk_char(),
       't' => {
         assert_eq!(next(st), '[');
-        let def = parse_def(st, NominalType, conv);
-        let substs = parse_substs(st, conv);
+        let def = parse_def(st, NominalType, |x,y| conv(x,y));
+        let substs = parse_substs(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
         return ty::mk_enum(st.tcx, def, substs);
       }
       'x' => {
         assert_eq!(next(st), '[');
-        let def = parse_def(st, NominalType, conv);
-        let substs = parse_substs(st, conv);
+        let def = parse_def(st, NominalType, |x,y| conv(x,y));
+        let substs = parse_substs(st, |x,y| conv(x,y));
         let store = parse_trait_store(st);
         let mt = parse_mutability(st);
-        let bounds = parse_bounds(st, conv);
+        let bounds = parse_bounds(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
         return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
       }
@@ -345,7 +346,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = ~[];
-        while peek(st) != ']' { params.push(parse_ty(st, conv)); }
+        while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
         st.pos = st.pos + 1u;
         return ty::mk_tup(st.tcx, params);
       }
@@ -379,15 +380,15 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         }
       }
       '"' => {
-        let _ = parse_def(st, TypeWithId, conv);
-        let inner = parse_ty(st, conv);
+        let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
+        let inner = parse_ty(st, |x,y| conv(x,y));
         inner
       }
       'B' => ty::mk_opaque_box(st.tcx),
       'a' => {
           assert_eq!(next(st), '[');
-          let did = parse_def(st, NominalType, conv);
-          let substs = parse_substs(st, conv);
+          let did = parse_def(st, NominalType, |x,y| conv(x,y));
+          let substs = parse_substs(st, |x,y| conv(x,y));
           assert_eq!(next(st), ']');
           return ty::mk_struct(st.tcx, did, substs);
       }
@@ -472,8 +473,8 @@ 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);
+    let bounds = parse_bounds(st, |x,y| conv(x,y));
+    let sig = parse_sig(st, |x,y| conv(x,y));
     ty::ClosureTy {
         purity: purity,
         sigil: sigil,
@@ -499,7 +500,7 @@ fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
     assert_eq!(next(st), '[');
     let mut inputs = ~[];
     while peek(st) != ']' {
-        inputs.push(parse_ty(st, conv));
+        inputs.push(parse_ty(st, |x,y| conv(x,y)));
     }
     st.pos += 1u; // eat the ']'
     let ret_ty = parse_ty(st, conv);
@@ -518,8 +519,8 @@ pub fn parse_def_id(buf: &[u8]) -> ast::def_id {
         fail!();
     }
 
-    let crate_part = vec::slice(buf, 0u, colon_idx);
-    let def_part = vec::slice(buf, colon_idx + 1u, len);
+    let crate_part = buf.slice(0u, colon_idx);
+    let def_part = buf.slice(colon_idx + 1u, len);
 
     let crate_num = match uint::parse_bytes(crate_part, 10u) {
        Some(cn) => cn as int,
@@ -543,8 +544,8 @@ 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)}
+    ty::TypeParameterDef {def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
+                          bounds: @parse_bounds(st, |x,y| conv(x,y))}
 }
 
 fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
@@ -555,13 +556,13 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
     loop {
         match next(st) {
             'S' => {
-                param_bounds.builtin_bounds.add(ty::BoundOwned);
+                param_bounds.builtin_bounds.add(ty::BoundSend);
             }
             'C' => {
                 param_bounds.builtin_bounds.add(ty::BoundCopy);
             }
             'K' => {
-                param_bounds.builtin_bounds.add(ty::BoundConst);
+                param_bounds.builtin_bounds.add(ty::BoundFreeze);
             }
             'O' => {
                 param_bounds.builtin_bounds.add(ty::BoundStatic);
@@ -570,7 +571,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
                 param_bounds.builtin_bounds.add(ty::BoundSized);
             }
             'I' => {
-                param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
+                param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
             }
             '.' => {
                 return param_bounds;
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 37fedc16122..fb72617b743 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -31,7 +31,6 @@ pub struct ctxt {
     ds: @fn(def_id) -> ~str,
     // The type context.
     tcx: ty::ctxt,
-    reachable: @fn(node_id) -> bool,
     abbrevs: abbrev_ctxt
 }
 
@@ -401,9 +400,9 @@ fn enc_fn_sig(w: @io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
 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'),
+            ty::BoundSend => w.write_char('S'),
             ty::BoundCopy => w.write_char('C'),
-            ty::BoundConst => w.write_char('K'),
+            ty::BoundFreeze => w.write_char('K'),
             ty::BoundStatic => w.write_char('O'),
             ty::BoundSized => w.write_char('Z'),
         }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index fb8238b84d6..16e3bd34cdd 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -368,14 +368,17 @@ impl tr for ast::def {
             ast::def_static_method(did.tr(xcx),
                                    did2_opt.map(|did2| did2.tr(xcx)),
                                    p)
-          },
-          ast::def_self_ty(nid) => ast::def_self_ty(xcx.tr_id(nid)),
-          ast::def_self(nid, i) => ast::def_self(xcx.tr_id(nid), i),
-          ast::def_mod(did) => ast::def_mod(did.tr(xcx)),
-          ast::def_foreign_mod(did) => ast::def_foreign_mod(did.tr(xcx)),
-          ast::def_static(did, m) => ast::def_static(did.tr(xcx), m),
-          ast::def_arg(nid, b) => ast::def_arg(xcx.tr_id(nid), b),
-          ast::def_local(nid, b) => ast::def_local(xcx.tr_id(nid), b),
+          }
+          ast::def_method(did0, did1) => {
+            ast::def_method(did0.tr(xcx), did1.map(|did1| did1.tr(xcx)))
+          }
+          ast::def_self_ty(nid) => { ast::def_self_ty(xcx.tr_id(nid)) }
+          ast::def_self(nid, i) => { ast::def_self(xcx.tr_id(nid), i) }
+          ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
+          ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) }
+          ast::def_static(did, m) => { ast::def_static(did.tr(xcx), m) }
+          ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) }
+          ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) }
           ast::def_variant(e_did, v_did) => {
             ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
           },
@@ -596,8 +599,10 @@ fn encode_vtable_res(ecx: &e::EncodeContext,
     // ty::t doesn't work, and there is no way (atm) to have
     // hand-written encoding routines combine with auto-generated
     // ones.  perhaps we should fix this.
-    do ebml_w.emit_from_vec(*dr) |ebml_w, vtable_origin| {
-        encode_vtable_origin(ecx, ebml_w, vtable_origin)
+    do ebml_w.emit_from_vec(*dr) |ebml_w, param_tables| {
+        do ebml_w.emit_from_vec(**param_tables) |ebml_w, vtable_origin| {
+            encode_vtable_origin(ecx, ebml_w, vtable_origin)
+        }
     }
 }
 
@@ -629,6 +634,13 @@ fn encode_vtable_origin(ecx: &e::EncodeContext,
                 }
             }
           }
+          typeck::vtable_self(def_id) => {
+            do ebml_w.emit_enum_variant("vtable_self", 2u, 1u) |ebml_w| {
+                do ebml_w.emit_enum_variant_arg(0u) |ebml_w| {
+                    ebml_w.emit_def_id(def_id)
+                }
+            }
+          }
         }
     }
 }
@@ -643,13 +655,17 @@ trait vtable_decoder_helpers {
 impl vtable_decoder_helpers for reader::Decoder {
     fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
                       -> typeck::vtable_res {
-        @self.read_to_vec(|this| this.read_vtable_origin(xcx))
+        @self.read_to_vec(|this|
+           @this.read_to_vec(|this|
+               this.read_vtable_origin(xcx)))
     }
 
     fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
         -> typeck::vtable_origin {
         do self.read_enum("vtable_origin") |this| {
-            do this.read_enum_variant(["vtable_static", "vtable_param"])
+            do this.read_enum_variant(["vtable_static",
+                                       "vtable_param",
+                                       "vtable_self"])
                     |this, i| {
                 match i {
                   0 => {
@@ -675,6 +691,13 @@ impl vtable_decoder_helpers for reader::Decoder {
                         }
                     )
                   }
+                  2 => {
+                    typeck::vtable_self(
+                        do this.read_enum_variant_arg(0u) |this| {
+                            this.read_def_id(xcx)
+                        }
+                    )
+                  }
                   // hard to avoid - user input
                   _ => fail!("bad enum variant")
                 }
@@ -692,12 +715,12 @@ trait get_ty_str_ctxt {
 
 impl<'self> get_ty_str_ctxt for e::EncodeContext<'self> {
     fn ty_str_ctxt(&self) -> @tyencode::ctxt {
-        let r = self.reachable;
-        @tyencode::ctxt {diag: self.tcx.sess.diagnostic(),
-                        ds: e::def_to_str,
-                        tcx: self.tcx,
-                        reachable: |a| r.contains(&a),
-                        abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)}
+        @tyencode::ctxt {
+            diag: self.tcx.sess.diagnostic(),
+            ds: e::def_to_str,
+            tcx: self.tcx,
+            abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)
+        }
     }
 }
 
diff --git a/src/librustc/middle/borrowck/doc.rs b/src/librustc/middle/borrowck/doc.rs
index cb3983117e9..8bb5c4620ef 100644
--- a/src/librustc/middle/borrowck/doc.rs
+++ b/src/librustc/middle/borrowck/doc.rs
@@ -359,7 +359,7 @@ of its owner:
     LIFETIME(LV.f, LT, MQ)              // L-Field
       LIFETIME(LV, LT, MQ)
 
-    LIFETIME(*LV, LT, MQ)               // L-Deref-Owned
+    LIFETIME(*LV, LT, MQ)               // L-Deref-Send
       TYPE(LV) = ~Ty
       LIFETIME(LV, LT, MQ)
 
@@ -504,7 +504,7 @@ must prevent the owned pointer `LV` from being mutated, which means
 that we always add `MUTATE` and `CLAIM` to the restriction set imposed
 on `LV`:
 
-    RESTRICTIONS(*LV, ACTIONS) = RS, (*LV, ACTIONS)    // R-Deref-Owned-Pointer
+    RESTRICTIONS(*LV, ACTIONS) = RS, (*LV, ACTIONS)    // R-Deref-Send-Pointer
       TYPE(LV) = ~Ty
       RESTRICTIONS(LV, ACTIONS|MUTATE|CLAIM) = RS
 
@@ -539,14 +539,14 @@ mutable borrowed pointers.
 
 ### Restrictions for loans of const aliasable pointees
 
-Const pointers are read-only. There may be `&mut` or `&` aliases, and
+Freeze pointers are read-only. There may be `&mut` or `&` aliases, and
 we can not prevent *anything* but moves in that case. So the
 `RESTRICTIONS` function is only defined if `ACTIONS` is the empty set.
 Because moves from a `&const` or `@const` lvalue are never legal, it
 is not necessary to add any restrictions at all to the final
 result.
 
-    RESTRICTIONS(*LV, []) = []                         // R-Deref-Const-Borrowed
+    RESTRICTIONS(*LV, []) = []                         // R-Deref-Freeze-Borrowed
       TYPE(LV) = &const Ty or @const Ty
 
 ### Restrictions for loans of mutable borrowed pointees
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index c7bad60e90e..e950610cce6 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -101,9 +101,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
                                cmt0: mc::cmt,
                                cmt: mc::cmt) -> bool {
     match cmt.cat {
-        mc::cat_stack_upvar(*) |
         mc::cat_implicit_self(*) |
-        mc::cat_copied_upvar(*) |
         mc::cat_deref(_, _, mc::region_ptr(*)) |
         mc::cat_deref(_, _, mc::gc_ptr(*)) |
         mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
@@ -114,6 +112,27 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
             false
         }
 
+        // These are separate from the above cases for a better error message.
+        mc::cat_stack_upvar(*) |
+        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, _ }) => {
+            let once_hint = if bccx.tcx.sess.once_fns() {
+                " (unless the destination closure type is `once fn')"
+            } else {
+                ""
+            };
+            bccx.span_err(
+                cmt0.span,
+                fmt!("cannot move out of %s%s", bccx.cmt_to_str(cmt), once_hint));
+            false
+        }
+
+        // Can move out of captured upvars only if the destination closure
+        // type is 'once'. 1-shot stack closures emit the copied_upvar form
+        // (see mem_categorization.rs).
+        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, _ }) => {
+            true
+        }
+
         // It seems strange to allow a move out of a static item,
         // but what happens in practice is that you have a
         // reference to a constant with a type that should be
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index 9455340268e..131ee5aa067 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -109,7 +109,7 @@ impl GuaranteeLifetimeContext {
             }
 
             mc::cat_downcast(base) |
-            mc::cat_deref(base, _, mc::uniq_ptr(*)) |  // L-Deref-Owned
+            mc::cat_deref(base, _, mc::uniq_ptr(*)) |  // L-Deref-Send
             mc::cat_interior(base, _) => {             // L-Field
                 self.check(base, discr_scope)
             }
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index bedb465c5c1..5f4251ad0a4 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -103,7 +103,7 @@ impl RestrictionsContext {
             }
 
             mc::cat_deref(cmt_base, _, mc::uniq_ptr(*)) => {
-                // R-Deref-Owned-Pointer
+                // R-Deref-Send-Pointer
                 //
                 // When we borrow the interior of an owned pointer, we
                 // cannot permit the base to be mutated, because that
@@ -125,7 +125,7 @@ impl RestrictionsContext {
 
             mc::cat_deref(_, _, mc::region_ptr(m_const, _)) |
             mc::cat_deref(_, _, mc::gc_ptr(m_const)) => {
-                // R-Deref-Const-Borrowed
+                // R-Deref-Freeze-Borrowed
                 self.check_no_mutability_control(cmt, restrictions);
                 Safe
             }
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 7396dc1bd7b..623dbbd61b2 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -411,7 +411,7 @@ impl MoveData {
 
         let mut p = self.path(index).first_child;
         while p != InvalidMovePathIndex {
-            if !self.each_extending_path(p, f) {
+            if !self.each_extending_path(p, |x| f(x)) {
                 return false;
             }
             p = self.path(p).next_sibling;
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index acd47eca726..93202f3fd55 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -132,7 +132,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
         debug!("add_gen(id=%?, bit=%?)", id, bit);
         let (start, end) = self.compute_id_range(id);
         {
-            let gens = vec::mut_slice(self.gens, start, end);
+            let gens = self.gens.mut_slice(start, end);
             set_bit(gens, bit);
         }
     }
@@ -143,7 +143,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
         debug!("add_kill(id=%?, bit=%?)", id, bit);
         let (start, end) = self.compute_id_range(id);
         {
-            let kills = vec::mut_slice(self.kills, start, end);
+            let kills = self.kills.mut_slice(start, end);
             set_bit(kills, bit);
         }
     }
@@ -216,7 +216,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
             return true;
         }
         let (start, end) = self.compute_id_range_frozen(id);
-        let on_entry = vec::slice(self.on_entry, start, end);
+        let on_entry = self.on_entry.slice(start, end);
         debug!("each_bit_on_entry_frozen(id=%?, on_entry=%s)",
                id, bits_to_str(on_entry));
         self.each_bit(on_entry, f)
@@ -229,7 +229,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
         //! Only useful after `propagate()` has been called.
 
         let (start, end) = self.compute_id_range(id);
-        let on_entry = vec::slice(self.on_entry, start, end);
+        let on_entry = self.on_entry.slice(start, end);
         debug!("each_bit_on_entry(id=%?, on_entry=%s)",
                id, bits_to_str(on_entry));
         self.each_bit(on_entry, f)
@@ -241,7 +241,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
         //! Iterates through each bit in the gen set for `id`.
 
         let (start, end) = self.compute_id_range(id);
-        let gens = vec::slice(self.gens, start, end);
+        let gens = self.gens.slice(start, end);
         debug!("each_gen_bit(id=%?, gens=%s)",
                id, bits_to_str(gens));
         self.each_bit(gens, f)
@@ -255,7 +255,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
             return true;
         }
         let (start, end) = self.compute_id_range_frozen(id);
-        let gens = vec::slice(self.gens, start, end);
+        let gens = self.gens.slice(start, end);
         debug!("each_gen_bit(id=%?, gens=%s)",
                id, bits_to_str(gens));
         self.each_bit(gens, f)
@@ -338,17 +338,17 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
 
             if self.nodeid_to_bitset.contains_key(&id) {
                 let (start, end) = self.compute_id_range_frozen(id);
-                let on_entry = vec::slice(self.on_entry, start, end);
+                let on_entry = self.on_entry.slice(start, end);
                 let entry_str = bits_to_str(on_entry);
 
-                let gens = vec::slice(self.gens, start, end);
+                let gens = self.gens.slice(start, end);
                 let gens_str = if gens.iter().any_(|&u| u != 0) {
                     fmt!(" gen: %s", bits_to_str(gens))
                 } else {
                     ~""
                 };
 
-                let kills = vec::slice(self.kills, start, end);
+                let kills = self.kills.slice(start, end);
                 let kills_str = if kills.iter().any_(|&u| u != 0) {
                     fmt!(" kill: %s", bits_to_str(kills))
                 } else {
@@ -953,7 +953,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
                id, bits_to_str(pred_bits));
         let (start, end) = self.dfcx.compute_id_range(id);
         let changed = { // FIXME(#5074) awkward construction
-            let on_entry = vec::mut_slice(self.dfcx.on_entry, start, end);
+            let on_entry = self.dfcx.on_entry.mut_slice(start, end);
             join_bits(&self.dfcx.oper, pred_bits, on_entry)
         };
         if changed {
@@ -970,7 +970,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> {
                id, mut_bits_to_str(pred_bits));
         let (start, end) = self.dfcx.compute_id_range(id);
         let changed = { // FIXME(#5074) awkward construction
-            let on_entry = vec::mut_slice(self.dfcx.on_entry, start, end);
+            let on_entry = self.dfcx.on_entry.mut_slice(start, end);
             let changed = join_bits(&self.dfcx.oper, reslice(pred_bits), on_entry);
             copy_bits(reslice(on_entry), pred_bits);
             changed
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index ef96fa97972..d4b91ed589d 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -31,21 +31,21 @@ use syntax::{visit, ast_util};
 //
 //  send: Things that can be sent on channels or included in spawned closures.
 //  copy: Things that can be copied.
-//  const: Things thare are deeply immutable. They are guaranteed never to
+//  freeze: Things thare are deeply immutable. They are guaranteed never to
 //    change, and can be safely shared without copying between tasks.
-//  owned: Things that do not contain borrowed pointers.
+//  'static: Things that do not contain borrowed pointers.
 //
 // Send includes scalar types as well as classes and unique types containing
 // only sendable types.
 //
 // Copy includes boxes, closure and unique types containing copyable types.
 //
-// Const include scalar types, things without non-const fields, and pointers
-// to const things.
+// Freeze include scalar types, things without non-const fields, and pointers
+// to freezable things.
 //
 // This pass ensures that type parameters are only instantiated with types
 // whose kinds are equal or less general than the way the type parameter was
-// annotated (with the `send`, `copy` or `const` keyword).
+// annotated (with the `Send`, `Copy` or `Freeze` bound).
 //
 // It also verifies that noncopyable kinds are not copied. Sendability is not
 // applied, since none of our language primitives send. Instead, the sending
@@ -90,10 +90,10 @@ fn check_struct_safe_for_destructor(cx: Context,
             self_ty: None,
             tps: ~[]
         });
-        if !ty::type_is_owned(cx.tcx, struct_ty) {
+        if !ty::type_is_sendable(cx.tcx, struct_ty) {
             cx.tcx.sess.span_err(span,
-                                 "cannot implement a destructor on a struct \
-                                  that is not Owned");
+                                 "cannot implement a destructor on a \
+                                  structure that does not satisfy Send");
             cx.tcx.sess.span_note(span,
                                   "use \"#[unsafe_destructor]\" on the \
                                    implementation to force the compiler to \
@@ -101,7 +101,7 @@ fn check_struct_safe_for_destructor(cx: Context,
         }
     } else {
         cx.tcx.sess.span_err(span,
-                             "cannot implement a destructor on a struct \
+                             "cannot implement a destructor on a structure \
                               with type parameters");
         cx.tcx.sess.span_note(span,
                               "use \"#[unsafe_destructor]\" on the \
@@ -171,7 +171,7 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         // check that only immutable variables are implicitly copied in
         check_imm_free_var(cx, fv.def, fv.span);
 
-        check_freevar_bounds(cx, fv.span, var_t, bounds);
+        check_freevar_bounds(cx, fv.span, var_t, bounds, None);
     }
 
     fn check_for_box(cx: Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
@@ -182,13 +182,18 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         // check that only immutable variables are implicitly copied in
         check_imm_free_var(cx, fv.def, fv.span);
 
-        check_freevar_bounds(cx, fv.span, var_t, bounds);
+        check_freevar_bounds(cx, fv.span, var_t, bounds, None);
     }
 
-    fn check_for_block(cx: Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
+    fn check_for_block(cx: Context, fv: &freevar_entry,
+                       bounds: ty::BuiltinBounds, region: ty::Region) {
         let id = ast_util::def_id_of_def(fv.def).node;
         let var_t = ty::node_id_to_type(cx.tcx, id);
-        check_freevar_bounds(cx, fv.span, var_t, bounds);
+        // FIXME(#3569): Figure out whether the implicit borrow is actually
+        // mutable. Currently we assume all upvars are referenced mutably.
+        let implicit_borrowed_type = ty::mk_mut_rptr(cx.tcx, region, var_t);
+        check_freevar_bounds(cx, fv.span, implicit_borrowed_type,
+                             bounds, Some(var_t));
     }
 
     fn check_for_bare(cx: Context, fv: @freevar_entry) {
@@ -205,8 +210,9 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, bounds: bounds, _}) => {
             b(|cx, fv| check_for_box(cx, fv, bounds))
         }
-        ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, bounds: bounds, _}) => {
-            b(|cx, fv| check_for_block(cx, fv, bounds))
+        ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, bounds: bounds,
+                                      region: region, _}) => {
+            b(|cx, fv| check_for_block(cx, fv, bounds, region))
         }
         ty::ty_bare_fn(_) => {
             b(check_for_bare)
@@ -366,14 +372,21 @@ pub fn check_typaram_bounds(cx: Context,
 }
 
 pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
-                            bounds: ty::BuiltinBounds)
+                            bounds: ty::BuiltinBounds, referenced_ty: Option<ty::t>)
 {
     do check_builtin_bounds(cx, ty, bounds) |missing| {
-        cx.tcx.sess.span_err(
-            sp,
-            fmt!("cannot capture variable of type `%s`, which does not fulfill \
-                  `%s`, in a bounded closure",
-                 ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx)));
+        // Will be Some if the freevar is implicitly borrowed (stack closure).
+        // Emit a less mysterious error message in this case.
+        match referenced_ty {
+            Some(rty) => cx.tcx.sess.span_err(sp,
+                fmt!("cannot implicitly borrow variable of type `%s` in a bounded \
+                      stack closure (implicit reference does not fulfill `%s`)",
+                     ty_to_str(cx.tcx, rty), missing.user_string(cx.tcx))),
+            None => cx.tcx.sess.span_err(sp,
+                fmt!("cannot capture variable of type `%s`, which does \
+                      not fulfill `%s`, in a bounded closure",
+                     ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx))),
+        }
         cx.tcx.sess.span_note(
             sp,
             fmt!("this closure's environment must satisfy `%s`",
@@ -438,10 +451,10 @@ fn check_copy(cx: Context, ty: ty::t, sp: span, reason: &str) {
     }
 }
 
-pub fn check_owned(cx: Context, ty: ty::t, sp: span) -> bool {
-    if !ty::type_is_owned(cx.tcx, ty) {
+pub fn check_send(cx: Context, ty: ty::t, sp: span) -> bool {
+    if !ty::type_is_sendable(cx.tcx, ty) {
         cx.tcx.sess.span_err(
-            sp, fmt!("value has non-owned type `%s`",
+            sp, fmt!("value has non-sendable type `%s`",
                      ty_to_str(cx.tcx, ty)));
         false
     } else {
@@ -489,7 +502,7 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool {
 /// `deque<T>`, then whatever borrowed ptrs may appear in `T` also
 /// appear in `deque<T>`.
 ///
-/// (3) The type parameter is owned (and therefore does not contain
+/// (3) The type parameter is sendable (and therefore does not contain
 /// borrowed ptrs).
 ///
 /// FIXME(#5723)---This code should probably move into regionck.
@@ -528,7 +541,7 @@ pub fn check_cast_for_escaping_regions(
     }
 
     // Assuming the trait instance can escape, then ensure that each parameter
-    // either appears in the trait type or is owned.
+    // either appears in the trait type or is sendable.
     let target_params = ty::param_tys_in_type(target_ty);
     let source_ty = ty::expr_ty(cx.tcx, source);
     ty::walk_regions_and_ty(
@@ -574,3 +587,4 @@ pub fn check_cast_for_escaping_regions(
         cx.tcx.region_maps.is_subregion_of(r_sub, r_sup)
     }
 }
+
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index cd6070cc638..08e55df5b36 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -13,9 +13,9 @@
 // Language items are items that represent concepts intrinsic to the language
 // itself. Examples are:
 //
-// * Traits that specify "kinds"; e.g. "const", "copy", "owned".
+// * Traits that specify "kinds"; e.g. "Freeze", "Copy", "Send".
 //
-// * Traits that represent operators; e.g. "add", "sub", "index".
+// * Traits that represent operators; e.g. "Add", "Sub", "Index".
 //
 // * Functions called by the compiler itself.
 
@@ -33,9 +33,9 @@ use syntax::visit::visit_crate;
 use core::hashmap::HashMap;
 
 pub enum LangItem {
-    ConstTraitLangItem,         // 0
+    FreezeTraitLangItem,        // 0
     CopyTraitLangItem,          // 1
-    OwnedTraitLangItem,         // 2
+    SendTraitLangItem,          // 2
     SizedTraitLangItem,         // 3
 
     DropTraitLangItem,          // 4
@@ -99,9 +99,9 @@ impl LanguageItems {
 
     pub fn item_name(index: uint) -> &'static str {
         match index {
-            0  => "const",
+            0  => "freeze",
             1  => "copy",
-            2  => "owned",
+            2  => "send",
             3  => "sized",
 
             4  => "drop",
@@ -152,14 +152,14 @@ impl LanguageItems {
 
     // FIXME #4621: Method macros sure would be nice here.
 
-    pub fn const_trait(&const self) -> def_id {
-        self.items[ConstTraitLangItem as uint].get()
+    pub fn freeze_trait(&const self) -> def_id {
+        self.items[FreezeTraitLangItem as uint].get()
     }
     pub fn copy_trait(&const self) -> def_id {
         self.items[CopyTraitLangItem as uint].get()
     }
-    pub fn owned_trait(&const self) -> def_id {
-        self.items[OwnedTraitLangItem as uint].get()
+    pub fn send_trait(&const self) -> def_id {
+        self.items[SendTraitLangItem as uint].get()
     }
     pub fn sized_trait(&const self) -> def_id {
         self.items[SizedTraitLangItem as uint].get()
@@ -291,13 +291,13 @@ struct LanguageItemCollector<'self> {
 }
 
 impl<'self> LanguageItemCollector<'self> {
-
-    pub fn new<'a>(crate: &'a crate, session: Session) -> LanguageItemCollector<'a> {
+    pub fn new<'a>(crate: &'a crate, session: Session)
+                   -> LanguageItemCollector<'a> {
         let mut item_refs = HashMap::new();
 
-        item_refs.insert(@"const", ConstTraitLangItem as uint);
+        item_refs.insert(@"freeze", FreezeTraitLangItem as uint);
         item_refs.insert(@"copy", CopyTraitLangItem as uint);
-        item_refs.insert(@"owned", OwnedTraitLangItem as uint);
+        item_refs.insert(@"send", SendTraitLangItem as uint);
         item_refs.insert(@"sized", SizedTraitLangItem as uint);
 
         item_refs.insert(@"drop", DropTraitLangItem as uint);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index f93cb265d78..ad5951b3976 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -78,7 +78,7 @@ pub enum categorization {
 }
 
 #[deriving(Eq)]
-struct CopiedUpvar {
+pub struct CopiedUpvar {
     upvar_id: ast::node_id,
     onceness: ast::Onceness,
 }
@@ -452,7 +452,7 @@ impl mem_categorization_ctxt {
           ast::def_trait(_) | ast::def_ty(_) | ast::def_prim_ty(_) |
           ast::def_ty_param(*) | ast::def_struct(*) |
           ast::def_typaram_binder(*) | ast::def_region(_) |
-          ast::def_label(_) | ast::def_self_ty(*) => {
+          ast::def_label(_) | ast::def_self_ty(*) | ast::def_method(*) => {
               @cmt_ {
                   id:id,
                   span:span,
@@ -507,30 +507,41 @@ impl mem_categorization_ctxt {
               let ty = ty::node_id_to_type(self.tcx, fn_node_id);
               match ty::get(ty).sty {
                   ty::ty_closure(ref closure_ty) => {
-                      let sigil = closure_ty.sigil;
-                      match sigil {
-                          ast::BorrowedSigil => {
-                              let upvar_cmt =
-                                  self.cat_def(id, span, expr_ty, *inner);
-                              @cmt_ {
-                                  id:id,
-                                  span:span,
-                                  cat:cat_stack_upvar(upvar_cmt),
-                                  mutbl:upvar_cmt.mutbl.inherit(),
-                                  ty:upvar_cmt.ty
-                              }
+                      // Decide whether to use implicit reference or by copy/move
+                      // capture for the upvar. This, combined with the onceness,
+                      // determines whether the closure can move out of it.
+                      let var_is_refd = match (closure_ty.sigil, closure_ty.onceness) {
+                          // Many-shot stack closures can never move out.
+                          (ast::BorrowedSigil, ast::Many) => true,
+                          // 1-shot stack closures can move out with "-Z once-fns".
+                          (ast::BorrowedSigil, ast::Once)
+                              if self.tcx.sess.once_fns() => false,
+                          (ast::BorrowedSigil, ast::Once) => true,
+                          // Heap closures always capture by copy/move, and can
+                          // move out iff they are once.
+                          (ast::OwnedSigil, _) | (ast::ManagedSigil, _) => false,
+
+                      };
+                      if var_is_refd {
+                          let upvar_cmt =
+                              self.cat_def(id, span, expr_ty, *inner);
+                          @cmt_ {
+                              id:id,
+                              span:span,
+                              cat:cat_stack_upvar(upvar_cmt),
+                              mutbl:upvar_cmt.mutbl.inherit(),
+                              ty:upvar_cmt.ty
                           }
-                          ast::OwnedSigil | ast::ManagedSigil => {
-                              // FIXME #2152 allow mutation of moved upvars
-                              @cmt_ {
-                                  id:id,
-                                  span:span,
-                                  cat:cat_copied_upvar(CopiedUpvar {
-                                      upvar_id: upvar_id,
-                                      onceness: closure_ty.onceness}),
-                                  mutbl:McImmutable,
-                                  ty:expr_ty
-                              }
+                      } else {
+                          // FIXME #2152 allow mutation of moved upvars
+                          @cmt_ {
+                              id:id,
+                              span:span,
+                              cat:cat_copied_upvar(CopiedUpvar {
+                                  upvar_id: upvar_id,
+                                  onceness: closure_ty.onceness}),
+                              mutbl:McImmutable,
+                              ty:expr_ty
                           }
                       }
                   }
@@ -890,7 +901,7 @@ impl mem_categorization_ctxt {
                                 pat, downcast_cmt, subpat_ty,
                                 InteriorField(PositionalField(i)));
 
-                        self.cat_pattern(subcmt, subpat, op);
+                        self.cat_pattern(subcmt, subpat, |x,y| op(x,y));
                     }
                 }
                 Some(&ast::def_fn(*)) |
@@ -901,12 +912,12 @@ impl mem_categorization_ctxt {
                             self.cat_imm_interior(
                                 pat, cmt, subpat_ty,
                                 InteriorField(PositionalField(i)));
-                        self.cat_pattern(cmt_field, subpat, op);
+                        self.cat_pattern(cmt_field, subpat, |x,y| op(x,y));
                     }
                 }
                 Some(&ast::def_static(*)) => {
                     for subpats.iter().advance |&subpat| {
-                        self.cat_pattern(cmt, subpat, op);
+                        self.cat_pattern(cmt, subpat, |x,y| op(x,y));
                     }
                 }
                 _ => {
@@ -930,7 +941,7 @@ impl mem_categorization_ctxt {
             for field_pats.iter().advance |fp| {
                 let field_ty = self.pat_ty(fp.pat); // see (*)
                 let cmt_field = self.cat_field(pat, cmt, fp.ident, field_ty);
-                self.cat_pattern(cmt_field, fp.pat, op);
+                self.cat_pattern(cmt_field, fp.pat, |x,y| op(x,y));
             }
           }
 
@@ -942,7 +953,7 @@ impl mem_categorization_ctxt {
                     self.cat_imm_interior(
                         pat, cmt, subpat_ty,
                         InteriorField(PositionalField(i)));
-                self.cat_pattern(subcmt, subpat, op);
+                self.cat_pattern(subcmt, subpat, |x,y| op(x,y));
             }
           }
 
@@ -956,15 +967,15 @@ impl mem_categorization_ctxt {
           ast::pat_vec(ref before, slice, ref after) => {
               let elt_cmt = self.cat_index(pat, cmt, 0);
               for before.iter().advance |&before_pat| {
-                  self.cat_pattern(elt_cmt, before_pat, op);
+                  self.cat_pattern(elt_cmt, before_pat, |x,y| op(x,y));
               }
               for slice.iter().advance |&slice_pat| {
                   let slice_ty = self.pat_ty(slice_pat);
                   let slice_cmt = self.cat_rvalue(pat, slice_ty);
-                  self.cat_pattern(slice_cmt, slice_pat, op);
+                  self.cat_pattern(slice_cmt, slice_pat, |x,y| op(x,y));
               }
               for after.iter().advance |&after_pat| {
-                  self.cat_pattern(elt_cmt, after_pat, op);
+                  self.cat_pattern(elt_cmt, after_pat, |x,y| op(x,y));
               }
           }
 
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 68307a49d3b..cd9d8738026 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -183,6 +183,7 @@ struct VisitContext {
     move_maps: MoveMaps
 }
 
+#[deriving(Eq)]
 enum UseMode {
     Move,        // This value or something owned by it is moved.
     Read         // Read no matter what the type.
@@ -335,7 +336,27 @@ impl VisitContext {
             }
 
             expr_call(callee, ref args, _) => {    // callee(args)
-                self.use_expr(callee, Read, visitor);
+                // Figure out whether the called function is consumed.
+                let mode = match ty::get(ty::expr_ty(self.tcx, callee)).sty {
+                    ty::ty_closure(ref cty) => {
+                        match cty.onceness {
+                        Once => Move,
+                        Many => Read,
+                        }
+                    },
+                    ty::ty_bare_fn(*) => Read,
+                    ref x =>
+                        self.tcx.sess.span_bug(callee.span,
+                            fmt!("non-function type in moves for expr_call: %?", x)),
+                };
+                // Note we're not using consume_expr, which uses type_moves_by_default
+                // to determine the mode, for this. The reason is that while stack
+                // closures should be noncopyable, they shouldn't move by default;
+                // calling a closure should only consume it if it's once.
+                if mode == Move {
+                    self.move_maps.moves_map.insert(callee.id);
+                }
+                self.use_expr(callee, mode, visitor);
                 self.use_fn_args(callee.id, *args, visitor);
             }
 
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
new file mode 100644
index 00000000000..88bd9c1f6f4
--- /dev/null
+++ b/src/librustc/middle/reachable.rs
@@ -0,0 +1,438 @@
+// 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.
+
+// Finds items that are externally reachable, to determine which items
+// need to have their metadata (and possibly their AST) serialized.
+// All items that can be referred to through an exported name are
+// reachable, and when a reachable thing is inline or generic, it
+// makes all other generics or inline functions that it references
+// reachable as well.
+
+use core::prelude::*;
+use core::iterator::IteratorUtil;
+
+use middle::resolve;
+use middle::ty;
+use middle::typeck;
+
+use core::hashmap::HashSet;
+use syntax::ast::*;
+use syntax::ast;
+use syntax::ast_map;
+use syntax::ast_util::def_id_of_def;
+use syntax::attr;
+use syntax::codemap;
+use syntax::parse::token;
+use syntax::visit::Visitor;
+use syntax::visit;
+
+// Returns true if the given set of attributes contains the `#[inline]`
+// attribute.
+fn attributes_specify_inlining(attrs: &[attribute]) -> bool {
+    attr::attrs_contains_name(attrs, "inline")
+}
+
+// Returns true if the given set of generics implies that the item it's
+// associated with must be inlined.
+fn generics_require_inlining(generics: &Generics) -> bool {
+    !generics.ty_params.is_empty()
+}
+
+// Returns true if the given item must be inlined because it may be
+// monomorphized or it was marked with `#[inline]`. This will only return
+// true for functions.
+fn item_might_be_inlined(item: @item) -> bool {
+    if attributes_specify_inlining(item.attrs) {
+        return true
+    }
+
+    match item.node {
+        item_fn(_, _, _, ref generics, _) => {
+            generics_require_inlining(generics)
+        }
+        _ => false,
+    }
+}
+
+// Returns true if the given type method must be inlined because it may be
+// monomorphized or it was marked with `#[inline]`.
+fn ty_method_might_be_inlined(ty_method: &ty_method) -> bool {
+    attributes_specify_inlining(ty_method.attrs) ||
+        generics_require_inlining(&ty_method.generics)
+}
+
+// Returns true if the given trait method must be inlined because it may be
+// monomorphized or it was marked with `#[inline]`.
+fn trait_method_might_be_inlined(trait_method: &trait_method) -> bool {
+    match *trait_method {
+        required(ref ty_method) => ty_method_might_be_inlined(ty_method),
+        provided(_) => true
+    }
+}
+
+// The context we're in. If we're in a public context, then public symbols are
+// marked reachable. If we're in a private context, then only trait
+// implementations are marked reachable.
+#[deriving(Eq)]
+enum PrivacyContext {
+    PublicContext,
+    PrivateContext,
+}
+
+// Information needed while computing reachability.
+struct ReachableContext {
+    // The type context.
+    tcx: ty::ctxt,
+    // The method map, which links node IDs of method call expressions to the
+    // methods they've been resolved to.
+    method_map: typeck::method_map,
+    // The set of items which must be exported in the linkage sense.
+    reachable_symbols: @mut HashSet<node_id>,
+    // A worklist of item IDs. Each item ID in this worklist will be inlined
+    // and will be scanned for further references.
+    worklist: @mut ~[node_id],
+}
+
+impl ReachableContext {
+    // Creates a new reachability computation context.
+    fn new(tcx: ty::ctxt, method_map: typeck::method_map)
+           -> ReachableContext {
+        ReachableContext {
+            tcx: tcx,
+            method_map: method_map,
+            reachable_symbols: @mut HashSet::new(),
+            worklist: @mut ~[],
+        }
+    }
+
+    // Step 1: Mark all public symbols, and add all public symbols that might
+    // be inlined to a worklist.
+    fn mark_public_symbols(&self, crate: @crate) {
+        let reachable_symbols = self.reachable_symbols;
+        let worklist = self.worklist;
+        let visitor = visit::mk_vt(@Visitor {
+            visit_item: |item, (privacy_context, visitor):
+                    (PrivacyContext, visit::vt<PrivacyContext>)| {
+                match item.node {
+                    item_fn(*) => {
+                        if privacy_context == PublicContext {
+                            reachable_symbols.insert(item.id);
+                        }
+                        if item_might_be_inlined(item) {
+                            worklist.push(item.id)
+                        }
+                    }
+                    item_struct(ref struct_def, _) => {
+                        match struct_def.ctor_id {
+                            Some(ctor_id) if
+                                    privacy_context == PublicContext => {
+                                reachable_symbols.insert(ctor_id);
+                            }
+                            Some(_) | None => {}
+                        }
+                    }
+                    item_enum(ref enum_def, _) => {
+                        if privacy_context == PublicContext {
+                            for enum_def.variants.iter().advance |variant| {
+                                reachable_symbols.insert(variant.node.id);
+                            }
+                        }
+                    }
+                    item_impl(ref generics, trait_ref, _, ref methods) => {
+                        // XXX(pcwalton): We conservatively assume any methods
+                        // on a trait implementation are reachable, when this
+                        // is not the case. We could be more precise by only
+                        // treating implementations of reachable or cross-
+                        // crate traits as reachable.
+
+                        let should_be_considered_public = |method: @method| {
+                            (method.vis == public &&
+                                    privacy_context == PublicContext) ||
+                                    trait_ref.is_some()
+                        };
+
+                        // Mark all public methods as reachable.
+                        for methods.iter().advance |&method| {
+                            if should_be_considered_public(method) {
+                                reachable_symbols.insert(method.id);
+                            }
+                        }
+
+                        if generics_require_inlining(generics) {
+                            // If the impl itself has generics, add all public
+                            // symbols to the worklist.
+                            for methods.iter().advance |&method| {
+                                if should_be_considered_public(method) {
+                                    worklist.push(method.id)
+                                }
+                            }
+                        } else {
+                            // Otherwise, add only public methods that have
+                            // generics to the worklist.
+                            for methods.iter().advance |method| {
+                                let generics = &method.generics;
+                                let attrs = &method.attrs;
+                                if generics_require_inlining(generics) ||
+                                        attributes_specify_inlining(*attrs) ||
+                                        should_be_considered_public(*method) {
+                                    worklist.push(method.id)
+                                }
+                            }
+                        }
+                    }
+                    item_trait(_, _, ref trait_methods) => {
+                        // Mark all provided methods as reachable.
+                        if privacy_context == PublicContext {
+                            for trait_methods.iter().advance |trait_method| {
+                                match *trait_method {
+                                    provided(method) => {
+                                        reachable_symbols.insert(method.id);
+                                        worklist.push(method.id)
+                                    }
+                                    required(_) => {}
+                                }
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+
+                if item.vis == public && privacy_context == PublicContext {
+                    visit::visit_item(item, (PublicContext, visitor))
+                } else {
+                    visit::visit_item(item, (PrivateContext, visitor))
+                }
+            },
+            .. *visit::default_visitor()
+        });
+
+        visit::visit_crate(crate, (PublicContext, visitor))
+    }
+
+    // Returns true if the given def ID represents a local item that is
+    // eligible for inlining and false otherwise.
+    fn def_id_represents_local_inlined_item(tcx: ty::ctxt, def_id: def_id)
+                                            -> bool {
+        if def_id.crate != local_crate {
+            return false
+        }
+
+        let node_id = def_id.node;
+        match tcx.items.find(&node_id) {
+            Some(&ast_map::node_item(item, _)) => {
+                match item.node {
+                    item_fn(*) => item_might_be_inlined(item),
+                    _ => false,
+                }
+            }
+            Some(&ast_map::node_trait_method(trait_method, _, _)) => {
+                match *trait_method {
+                    required(_) => false,
+                    provided(_) => true,
+                }
+            }
+            Some(&ast_map::node_method(method, impl_did, _)) => {
+                if generics_require_inlining(&method.generics) ||
+                        attributes_specify_inlining(method.attrs) {
+                    true
+                } else {
+                    // Check the impl. If the generics on the self type of the
+                    // impl require inlining, this method does too.
+                    assert!(impl_did.crate == local_crate);
+                    match tcx.items.find(&impl_did.node) {
+                        Some(&ast_map::node_item(item, _)) => {
+                            match item.node {
+                                item_impl(ref generics, _, _, _) => {
+                                    generics_require_inlining(generics)
+                                }
+                                _ => false
+                            }
+                        }
+                        Some(_) => {
+                            tcx.sess.span_bug(method.span,
+                                              "method is not inside an \
+                                               impl?!")
+                        }
+                        None => {
+                            tcx.sess.span_bug(method.span,
+                                              "the impl that this method is \
+                                               supposedly inside of doesn't \
+                                               exist in the AST map?!")
+                        }
+                    }
+                }
+            }
+            Some(_) => false,
+            None => false   // This will happen for default methods.
+        }
+    }
+
+    // Helper function to set up a visitor for `propagate()` below.
+    fn init_visitor(&self) -> visit::vt<()> {
+        let (worklist, method_map) = (self.worklist, self.method_map);
+        let (tcx, reachable_symbols) = (self.tcx, self.reachable_symbols);
+        visit::mk_vt(@visit::Visitor {
+            visit_expr: |expr, (_, visitor)| {
+                match expr.node {
+                    expr_path(_) => {
+                        let def = match tcx.def_map.find(&expr.id) {
+                            Some(&def) => def,
+                            None => {
+                                tcx.sess.span_bug(expr.span,
+                                                  "def ID not in def map?!")
+                            }
+                        };
+
+                        let def_id = def_id_of_def(def);
+                        if ReachableContext::
+                                def_id_represents_local_inlined_item(tcx,
+                                                                     def_id) {
+                            worklist.push(def_id.node)
+                        }
+                        reachable_symbols.insert(def_id.node);
+                    }
+                    expr_method_call(*) => {
+                        match method_map.find(&expr.id) {
+                            Some(&typeck::method_map_entry {
+                                origin: typeck::method_static(def_id),
+                                _
+                            }) => {
+                                if ReachableContext::
+                                    def_id_represents_local_inlined_item(
+                                        tcx,
+                                        def_id) {
+                                    worklist.push(def_id.node)
+                                }
+                                reachable_symbols.insert(def_id.node);
+                            }
+                            Some(_) => {}
+                            None => {
+                                tcx.sess.span_bug(expr.span,
+                                                  "method call expression \
+                                                   not in method map?!")
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+
+                visit::visit_expr(expr, ((), visitor))
+            },
+            ..*visit::default_visitor()
+        })
+    }
+
+    // Step 2: Mark all symbols that the symbols on the worklist touch.
+    fn propagate(&self) {
+        let visitor = self.init_visitor();
+        let mut scanned = HashSet::new();
+        while self.worklist.len() > 0 {
+            let search_item = self.worklist.pop();
+            if scanned.contains(&search_item) {
+                loop
+            }
+            scanned.insert(search_item);
+            self.reachable_symbols.insert(search_item);
+
+            // Find the AST block corresponding to the item and visit it,
+            // marking all path expressions that resolve to something
+            // interesting.
+            match self.tcx.items.find(&search_item) {
+                Some(&ast_map::node_item(item, _)) => {
+                    match item.node {
+                        item_fn(_, _, _, _, ref search_block) => {
+                            visit::visit_block(search_block, ((), visitor))
+                        }
+                        _ => {
+                            self.tcx.sess.span_bug(item.span,
+                                                   "found non-function item \
+                                                    in worklist?!")
+                        }
+                    }
+                }
+                Some(&ast_map::node_trait_method(trait_method, _, _)) => {
+                    match *trait_method {
+                        required(ref ty_method) => {
+                            self.tcx.sess.span_bug(ty_method.span,
+                                                   "found required method in \
+                                                    worklist?!")
+                        }
+                        provided(ref method) => {
+                            visit::visit_block(&method.body, ((), visitor))
+                        }
+                    }
+                }
+                Some(&ast_map::node_method(ref method, _, _)) => {
+                    visit::visit_block(&method.body, ((), visitor))
+                }
+                Some(_) => {
+                    let ident_interner = token::get_ident_interner();
+                    let desc = ast_map::node_id_to_str(self.tcx.items,
+                                                       search_item,
+                                                       ident_interner);
+                    self.tcx.sess.bug(fmt!("found unexpected thingy in \
+                                            worklist: %s",
+                                            desc))
+                }
+                None => {
+                    self.tcx.sess.bug(fmt!("found unmapped ID in worklist: \
+                                            %d",
+                                           search_item))
+                }
+            }
+        }
+    }
+
+    // Step 3: Mark all destructors as reachable.
+    //
+    // XXX(pcwalton): This is a conservative overapproximation, but fixing
+    // this properly would result in the necessity of computing *type*
+    // reachability, which might result in a compile time loss.
+    fn mark_destructors_reachable(&self) {
+        for self.tcx.destructor_for_type.iter().advance
+                |(_, destructor_def_id)| {
+            if destructor_def_id.crate == local_crate {
+                self.reachable_symbols.insert(destructor_def_id.node);
+            }
+        }
+    }
+}
+
+pub fn find_reachable(tcx: ty::ctxt,
+                      method_map: typeck::method_map,
+                      crate: @crate)
+                      -> @mut HashSet<node_id> {
+    // XXX(pcwalton): We only need to mark symbols that are exported. But this
+    // is more complicated than just looking at whether the symbol is `pub`,
+    // because it might be the target of a `pub use` somewhere. For now, I
+    // think we are fine, because you can't `pub use` something that wasn't
+    // exported due to the bug whereby `use` only looks through public
+    // modules even if you're inside the module the `use` appears in. When
+    // this bug is fixed, however, this code will need to be updated. Probably
+    // the easiest way to fix this (although a conservative overapproximation)
+    // is to have the name resolution pass mark all targets of a `pub use` as
+    // "must be reachable".
+
+    let reachable_context = ReachableContext::new(tcx, method_map);
+
+    // Step 1: Mark all public symbols, and add all public symbols that might
+    // be inlined to a worklist.
+    reachable_context.mark_public_symbols(crate);
+
+    // Step 2: Mark all symbols that the symbols on the worklist touch.
+    reachable_context.propagate();
+
+    // Step 3: Mark all destructors as reachable.
+    reachable_context.mark_destructors_reachable();
+
+    // Return the set of reachable symbols.
+    reachable_context.reachable_symbols
+}
+
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index e06fd8f9717..b2bfd9d1661 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -652,19 +652,17 @@ impl NameBindings {
                 match self.type_def {
                     None => None,
                     Some(ref type_def) => {
-                        // FIXME (#3784): This is reallllly questionable.
-                        // Perhaps the right thing to do is to merge def_mod
-                        // and def_ty.
                         match (*type_def).type_def {
                             Some(type_def) => Some(type_def),
                             None => {
-                                match (*type_def).module_def {
-                                    Some(module_def) => {
-                                        let module_def = &mut *module_def;
-                                        module_def.def_id.map(|def_id|
-                                            def_mod(*def_id))
+                                match type_def.module_def {
+                                    Some(module) => {
+                                        match module.def_id {
+                                            Some(did) => Some(def_mod(did)),
+                                            None => None,
+                                        }
                                     }
-                                    None => None
+                                    None => None,
                                 }
                             }
                         }
@@ -1230,49 +1228,29 @@ impl Resolver {
                 visit_item(item, (new_parent, visitor));
             }
 
-            item_impl(_, trait_ref_opt, ty, ref methods) => {
-                // If this implements an anonymous trait and it has static
-                // methods, then add all the static methods within to a new
-                // module, if the type was defined within this module.
+            item_impl(_, None, ty, ref methods) => {
+                // If this implements an anonymous trait, then add all the
+                // methods within to a new module, if the type was defined
+                // within this module.
                 //
                 // FIXME (#3785): This is quite unsatisfactory. Perhaps we
                 // should modify anonymous traits to only be implementable in
                 // the same module that declared the type.
 
-                // Bail out early if there are no static methods.
-                let mut methods_seen = HashMap::new();
-                let mut has_static_methods = false;
-                for methods.iter().advance |method| {
-                    match method.explicit_self.node {
-                        sty_static => has_static_methods = true,
-                        _ => {
-                            // Make sure you can't define duplicate methods
-                            let ident = method.ident;
-                            let span = method.span;
-                            let old_sp = methods_seen.find_or_insert(ident, span);
-                            if *old_sp != span {
-                                self.session.span_err(span,
-                                                      fmt!("duplicate definition of method `%s`",
-                                                           self.session.str_of(ident)));
-                                self.session.span_note(*old_sp,
-                                                       fmt!("first definition of method `%s` here",
-                                                            self.session.str_of(ident)));
-                            }
-                        }
-                    }
-                }
-
-                // If there are static methods, then create the module
-                // and add them.
-                match (trait_ref_opt, ty) {
-                    (None, @Ty { node: ty_path(path, _, _), _ }) if
-                            has_static_methods && path.idents.len() == 1 => {
+                // Create the module and add all methods.
+                match *ty {
+                    Ty {
+                        node: ty_path(path, _, _),
+                        _
+                    } if path.idents.len() == 1 => {
                         let name = path_to_ident(path);
 
                         let new_parent = match parent.children.find(&name) {
                             // It already exists
-                            Some(&child) if child.get_module_if_available().is_some() &&
-                                            child.get_module().kind == ImplModuleKind => {
+                            Some(&child) if child.get_module_if_available()
+                                                 .is_some() &&
+                                            child.get_module().kind ==
+                                                ImplModuleKind => {
                                 ModuleReducedGraphParent(child.get_module())
                             }
                             // Create the module
@@ -1283,8 +1261,8 @@ impl Resolver {
                                                    ForbidDuplicateModules,
                                                    sp);
 
-                                let parent_link = self.get_parent_link(new_parent,
-                                                                       ident);
+                                let parent_link =
+                                    self.get_parent_link(new_parent, ident);
                                 let def_id = local_def(item.id);
                                 name_bindings.define_module(Public,
                                                             parent_link,
@@ -1292,30 +1270,36 @@ impl Resolver {
                                                             ImplModuleKind,
                                                             sp);
 
-                                ModuleReducedGraphParent(name_bindings.get_module())
+                                ModuleReducedGraphParent(
+                                    name_bindings.get_module())
                             }
                         };
 
-                        // For each static method...
+                        // For each method...
                         for methods.iter().advance |method| {
-                            match method.explicit_self.node {
+                            // Add the method to the module.
+                            let ident = method.ident;
+                            let (method_name_bindings, _) =
+                                self.add_child(ident,
+                                               new_parent,
+                                               ForbidDuplicateValues,
+                                               method.span);
+                            let def = match method.explicit_self.node {
                                 sty_static => {
-                                    // Add the static method to the
-                                    // module.
-                                    let ident = method.ident;
-                                    let (method_name_bindings, _) =
-                                        self.add_child(
-                                            ident,
-                                            new_parent,
-                                            ForbidDuplicateValues,
-                                            method.span);
-                                    let def = def_fn(local_def(method.id),
-                                                     method.purity);
-                                    method_name_bindings.define_value(
-                                        Public, def, method.span);
+                                    // Static methods become `def_fn`s.
+                                    def_fn(local_def(method.id),
+                                           method.purity)
                                 }
-                                _ => {}
-                            }
+                                _ => {
+                                    // Non-static methods become
+                                    // `def_method`s.
+                                    def_method(local_def(method.id), None)
+                                }
+                            };
+
+                            method_name_bindings.define_value(Public,
+                                                              def,
+                                                              method.span);
                         }
                     }
                     _ => {}
@@ -1324,41 +1308,23 @@ impl Resolver {
                 visit_item(item, (parent, visitor));
             }
 
+            item_impl(_, Some(_), ty, ref methods) => {
+                visit_item(item, (parent, visitor));
+            }
+
             item_trait(_, _, ref methods) => {
                 let (name_bindings, new_parent) =
                     self.add_child(ident, parent, ForbidDuplicateTypes, sp);
 
-                // If the trait has static methods, then add all the static
-                // methods within to a new module.
-                //
-                // We only need to create the module if the trait has static
-                // methods, so check that first.
-                let mut has_static_methods = false;
-                for (*methods).iter().advance |method| {
-                    let ty_m = trait_method_to_ty_method(method);
-                    match ty_m.explicit_self.node {
-                        sty_static => {
-                            has_static_methods = true;
-                            break;
-                        }
-                        _ => {}
-                    }
-                }
-
-                // Create the module if necessary.
-                let module_parent_opt;
-                if has_static_methods {
-                    let parent_link = self.get_parent_link(parent, ident);
-                    name_bindings.define_module(privacy,
-                                                parent_link,
-                                                Some(local_def(item.id)),
-                                                TraitModuleKind,
-                                                sp);
-                    module_parent_opt = Some(ModuleReducedGraphParent(
-                        name_bindings.get_module()));
-                } else {
-                    module_parent_opt = None;
-                }
+                // Add all the methods within to a new module.
+                let parent_link = self.get_parent_link(parent, ident);
+                name_bindings.define_module(privacy,
+                                            parent_link,
+                                            Some(local_def(item.id)),
+                                            TraitModuleKind,
+                                            sp);
+                let module_parent = ModuleReducedGraphParent(name_bindings.
+                                                             get_module());
 
                 // Add the names of all the methods to the trait info.
                 let mut method_names = HashMap::new();
@@ -1366,35 +1332,34 @@ impl Resolver {
                     let ty_m = trait_method_to_ty_method(method);
 
                     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.explicit_self.node {
-                        sty_static => {
-                            let def = def_static_method(
-                                local_def(ty_m.id),
-                                Some(local_def(item.id)),
-                                ty_m.purity);
 
-                            let (method_name_bindings, _) =
-                                self.add_child(ident,
-                                               module_parent_opt.get(),
-                                               ForbidDuplicateValues,
-                                               ty_m.span);
-                            method_name_bindings.define_value(Public,
-                                                              def,
-                                                              ty_m.span);
+                    // Add it as a name in the trait module.
+                    let def = match ty_m.explicit_self.node {
+                        sty_static => {
+                            // Static methods become `def_static_method`s.
+                            def_static_method(local_def(ty_m.id),
+                                              Some(local_def(item.id)),
+                                              ty_m.purity)
                         }
                         _ => {
-                            // Make sure you can't define duplicate methods
-                            let old_sp = method_names.find_or_insert(ident, ty_m.span);
-                            if *old_sp != ty_m.span {
-                                self.session.span_err(ty_m.span,
-                                                      fmt!("duplicate definition of method `%s`",
-                                                           self.session.str_of(ident)));
-                                self.session.span_note(*old_sp,
-                                                       fmt!("first definition of method `%s` here",
-                                                            self.session.str_of(ident)));
-                            }
+                            // Non-static methods become `def_method`s.
+                            def_method(local_def(ty_m.id),
+                                       Some(local_def(item.id)))
+                        }
+                    };
+
+                    let (method_name_bindings, _) =
+                        self.add_child(ident,
+                                       module_parent,
+                                       ForbidDuplicateValues,
+                                       ty_m.span);
+                    method_name_bindings.define_value(Public, def, ty_m.span);
+
+                    // Add it to the trait info if not static.
+                    match ty_m.explicit_self.node {
+                        sty_static => {}
+                        _ => {
+                            method_names.insert(ident, ());
                         }
                     }
                 }
@@ -1751,6 +1716,9 @@ impl Resolver {
             child_name_bindings.define_type(privacy, def, dummy_sp());
             self.structs.insert(def_id);
           }
+          def_method(*) => {
+            // Ignored; handled elsewhere.
+          }
           def_self(*) | def_arg(*) | def_local(*) |
           def_prim_ty(*) | def_ty_param(*) | def_binding(*) |
           def_use(*) | def_upvar(*) | def_region(*) |
@@ -2091,8 +2059,12 @@ impl Resolver {
         let mut first = true;
         let mut result = ~"";
         for idents.iter().advance |ident| {
-            if first { first = false; } else { result += "::" };
-            result += self.session.str_of(*ident);
+            if first {
+                first = false
+            } else {
+                result.push_str("::")
+            }
+            result.push_str(self.session.str_of(*ident));
         };
         return result;
     }
@@ -2387,7 +2359,8 @@ impl Resolver {
         }
         match type_result {
             BoundResult(target_module, name_bindings) => {
-                debug!("(resolving single import) found type target");
+                debug!("(resolving single import) found type target: %?",
+                        name_bindings.type_def.get().type_def);
                 import_resolution.type_target =
                     Some(Target(target_module, name_bindings));
                 import_resolution.type_id = directive.id;
@@ -3186,12 +3159,14 @@ impl Resolver {
             Some(def_id) if def_id.crate == local_crate => {
                 // OK. Continue.
                 debug!("(recording exports for module subtree) recording \
-                        exports for local module");
+                        exports for local module `%s`",
+                       self.module_to_str(module_));
             }
             None => {
                 // Record exports for the root module.
                 debug!("(recording exports for module subtree) recording \
-                        exports for root module");
+                        exports for root module `%s`",
+                       self.module_to_str(module_));
             }
             Some(_) => {
                 // Bail out.
@@ -3265,22 +3240,8 @@ impl Resolver {
     pub fn add_exports_for_module(@mut self,
                                   exports2: &mut ~[Export2],
                                   module_: @mut Module) {
-        for module_.children.iter().advance |(ident, namebindings)| {
-            debug!("(computing exports) maybe export '%s'",
-                   self.session.str_of(*ident));
-            self.add_exports_of_namebindings(&mut *exports2,
-                                             *ident,
-                                             *namebindings,
-                                             TypeNS,
-                                             false);
-            self.add_exports_of_namebindings(&mut *exports2,
-                                             *ident,
-                                             *namebindings,
-                                             ValueNS,
-                                             false);
-        }
-
-        for module_.import_resolutions.iter().advance |(ident, importresolution)| {
+        for module_.import_resolutions.iter().advance |(ident,
+                                                        importresolution)| {
             if importresolution.privacy != Public {
                 debug!("(computing exports) not reexporting private `%s`",
                        self.session.str_of(*ident));
@@ -4514,8 +4475,8 @@ impl Resolver {
 
         if path.global {
             return self.resolve_crate_relative_path(path,
-                                                 self.xray_context,
-                                                 namespace);
+                                                    self.xray_context,
+                                                    namespace);
         }
 
         if path.idents.len() > 1 {
@@ -4862,8 +4823,8 @@ impl Resolver {
         while j != 0 {
             j -= 1;
             for this.value_ribs[j].bindings.each_key |&k| {
-                vec::push(&mut maybes, this.session.str_of(k));
-                vec::push(&mut values, uint::max_value);
+                maybes.push(this.session.str_of(k));
+                values.push(uint::max_value);
             }
         }
 
@@ -4882,7 +4843,7 @@ impl Resolver {
             values[smallest] <= max_distance &&
             name != maybes[smallest] {
 
-            Some(vec::swap_remove(&mut maybes, smallest))
+            Some(maybes.swap_remove(smallest))
 
         } else {
             None
@@ -4943,6 +4904,22 @@ impl Resolver {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `%s`",
                                self.idents_to_str(path.idents));
+
+                        // First-class methods are not supported yet; error
+                        // out here.
+                        match def {
+                            def_method(*) => {
+                                self.session.span_err(expr.span,
+                                                      "first-class methods \
+                                                       are not supported");
+                                self.session.span_note(expr.span,
+                                                       "call the method \
+                                                        using the `.` \
+                                                        syntax");
+                            }
+                            _ => {}
+                        }
+
                         self.record_def(expr.id, def);
                     }
                     None => {
@@ -5072,6 +5049,9 @@ impl Resolver {
                 self.trait_map.insert(expr.id, @mut traits);
             }
             expr_method_call(_, _, ident, _, _, _) => {
+                debug!("(recording candidate traits for expr) recording \
+                        traits for %d",
+                       expr.id);
                 let traits = self.search_for_traits_containing_method(ident);
                 self.trait_map.insert(expr.id, @mut traits);
             }
@@ -5147,7 +5127,6 @@ impl Resolver {
         debug!("(searching for traits containing method) looking for '%s'",
                self.session.str_of(name));
 
-
         let mut found_traits = ~[];
         let mut search_module = self.current_module;
         match self.method_map.find(&name) {
@@ -5411,7 +5390,7 @@ pub fn resolve_crate(session: Session,
                   -> CrateMap {
     let resolver = @mut Resolver(session, lang_items, crate);
     resolver.resolve();
-    let Resolver{def_map, export_map2, trait_map, _} = copy *resolver;
+    let Resolver { def_map, export_map2, trait_map, _ } = copy *resolver;
     CrateMap {
         def_map: def_map,
         exp_map2: export_map2,
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index a2cbc4d6fe0..c2e9c7b194b 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -388,9 +388,9 @@ pub fn expand_nested_bindings<'r>(bcx: block,
         match br.pats[col].node {
             ast::pat_ident(_, path, Some(inner)) => {
                 let pats = vec::append(
-                    vec::slice(br.pats, 0u, col).to_owned(),
+                    br.pats.slice(0u, col).to_owned(),
                     vec::append(~[inner],
-                                vec::slice(br.pats, col + 1u,
+                                br.pats.slice(col + 1u,
                                            br.pats.len())));
 
                 let binding_info =
@@ -437,8 +437,8 @@ pub fn enter_match<'r>(bcx: block,
             Some(sub) => {
                 let pats =
                     vec::append(
-                        vec::append(sub, vec::slice(br.pats, 0u, col)),
-                        vec::slice(br.pats, col + 1u, br.pats.len()));
+                        vec::append(sub, br.pats.slice(0u, col)),
+                        br.pats.slice(col + 1u, br.pats.len()));
 
                 let this = br.pats[col];
                 match this.node {
@@ -1290,7 +1290,7 @@ pub fn compile_submatch(bcx: block,
         match data.arm.guard {
             Some(guard_expr) => {
                 bcx = compile_guard(bcx, guard_expr, m[0].data,
-                                    vec::slice(m, 1, m.len()),
+                                    m.slice(1, m.len()),
                                     vals, chk);
             }
             _ => ()
@@ -1309,8 +1309,8 @@ pub fn compile_submatch(bcx: block,
         }
     };
 
-    let vals_left = vec::append(vec::slice(vals, 0u, col).to_owned(),
-                                vec::slice(vals, col + 1u, vals.len()));
+    let vals_left = vec::append(vals.slice(0u, col).to_owned(),
+                                vals.slice(col + 1u, vals.len()));
     let ccx = bcx.fcx.ccx;
     let mut pat_id = 0;
     let mut pat_span = dummy_sp();
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 3c263b1c01e..a1d1b737f31 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -41,6 +41,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
             callee::trans_arg_expr(bcx,
                                    expr_ty(bcx, out),
                                    ty::ByCopy,
+                                   ast::sty_static,
                                    out,
                                    &mut cleanups,
                                    None,
@@ -56,6 +57,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
             callee::trans_arg_expr(bcx,
                                    expr_ty(bcx, e),
                                    ty::ByCopy,
+                                   ast::sty_static,
                                    e,
                                    &mut cleanups,
                                    None,
@@ -77,6 +79,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
             callee::trans_arg_expr(bcx,
                                    expr_ty(bcx, in),
                                    ty::ByCopy,
+                                   ast::sty_static,
                                    in,
                                    &mut cleanups,
                                    None,
@@ -95,15 +98,15 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
     if !ia.clobbers.is_empty() && !clobbers.is_empty() {
         clobbers = fmt!("%s,%s", ia.clobbers, clobbers);
     } else {
-        clobbers += ia.clobbers;
+        clobbers.push_str(ia.clobbers);
     };
 
     // Add the clobbers to our constraints list
-    if !clobbers.is_empty() && !constraints.is_empty() {
-        constraints += ",";
-        constraints += clobbers;
+    if clobbers.len() != 0 && constraints.len() != 0 {
+        constraints.push_char(',');
+        constraints.push_str(clobbers);
     } else {
-        constraints += clobbers;
+        constraints.push_str(clobbers);
     }
 
     debug!("Asm Constraints: %?", constraints);
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index a0628bc8e87..d9fea121346 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -54,7 +54,6 @@ use middle::trans::machine;
 use middle::trans::machine::{llalign_of_min, llsize_of};
 use middle::trans::meth;
 use middle::trans::monomorphize;
-use middle::trans::reachable;
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::trans::type_of::*;
@@ -65,7 +64,7 @@ use util::ppaux::{Repr, ty_to_str};
 use middle::trans::type_::Type;
 
 use core::hash;
-use core::hashmap::{HashMap};
+use core::hashmap::{HashMap, HashSet};
 use core::int;
 use core::io;
 use core::libc::c_uint;
@@ -462,6 +461,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
                                                     &tsubsts,
                                                     None,
                                                     None,
+                                                    None,
                                                     None);
 
         val
@@ -674,7 +674,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
                                     int::to_str(variant.disr_val));
                       let variant_cx =
                           iter_variant(variant_cx, repr, av, *variant,
-                                       substs.tps, f);
+                                       substs.tps, |x,y,z| f(x,y,z));
                       match adt::trans_case(cx, repr, variant.disr_val) {
                           _match::single_result(r) => {
                               AddCase(llswitch, r.val, variant_cx.llbb)
@@ -1129,15 +1129,10 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
                  is_lpad: bool, name: &str, opt_node_info: Option<NodeInfo>)
     -> block {
 
-    let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
-        (cx.ccx.names)(name)
-    } else {
-        special_idents::invalid
-    };
     unsafe {
-        let llbb = str::as_c_str(cx.ccx.sess.str_of(s), |buf| {
+        let llbb = do name.as_c_str |buf| {
             llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
-        });
+        };
         let bcx = mk_block(llbb,
                            parent,
                            kind,
@@ -1145,8 +1140,11 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
                            opt_node_info,
                            cx);
         for parent.iter().advance |cx| {
-            if cx.unreachable { Unreachable(bcx); }
-        };
+            if cx.unreachable {
+                Unreachable(bcx);
+                break;
+            }
+        }
         bcx
     }
 }
@@ -1547,17 +1545,15 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
                         llfndecl: ValueRef,
                         id: ast::node_id,
                         output_type: ty::t,
-                        impl_id: Option<ast::def_id>,
                         param_substs: Option<@param_substs>,
                         sp: Option<span>)
                      -> fn_ctxt {
     for param_substs.iter().advance |p| { p.validate(); }
 
-    debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \
+    debug!("new_fn_ctxt_w_id(path=%s, id=%?, \
             param_substs=%s)",
            path_str(ccx.sess, path),
            id,
-           impl_id,
            param_substs.repr(ccx.tcx));
 
     let llbbs = mk_standard_basic_blocks(llfndecl);
@@ -1586,7 +1582,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
           lllocals: @mut HashMap::new(),
           llupvars: @mut HashMap::new(),
           id: id,
-          impl_id: impl_id,
           param_substs: param_substs,
           span: sp,
           path: path,
@@ -1607,7 +1602,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
                    output_type: ty::t,
                    sp: Option<span>)
                 -> fn_ctxt {
-    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp)
+    new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, sp)
 }
 
 // NB: must keep 4 fns in sync:
@@ -1680,23 +1675,15 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
     let mut bcx = bcx;
 
     match fcx.llself {
-      Some(slf) => {
-          let self_val = if slf.is_owned
-                  && datum::appropriate_mode(slf.t).is_by_value() {
-              let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
-              let alloc = alloc_ty(bcx, slf.t);
-              Store(bcx, tmp, alloc);
-              alloc
-          } else {
-              PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to())
-          };
-
-          fcx.llself = Some(ValSelfData {v: self_val, ..slf});
-          if slf.is_owned {
-              add_clean(bcx, self_val, slf.t);
-          }
-      }
-      _ => {}
+        Some(slf) => {
+            let self_val = PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to());
+            fcx.llself = Some(ValSelfData {v: self_val, ..slf});
+
+            if slf.is_owned {
+                add_clean(bcx, slf.v, slf.t);
+            }
+        }
+        _ => {}
     }
 
     for uint::range(0, arg_tys.len()) |arg_n| {
@@ -1784,7 +1771,6 @@ pub fn trans_closure(ccx: @mut CrateContext,
                      self_arg: self_arg,
                      param_substs: Option<@param_substs>,
                      id: ast::node_id,
-                     impl_id: Option<ast::def_id>,
                      attributes: &[ast::attribute],
                      output_type: ty::t,
                      maybe_load_env: &fn(fn_ctxt),
@@ -1802,7 +1788,6 @@ pub fn trans_closure(ccx: @mut CrateContext,
                                llfndecl,
                                id,
                                output_type,
-                               impl_id,
                                param_substs,
                                Some(body.span));
     let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);
@@ -1861,7 +1846,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
                 self_arg: self_arg,
                 param_substs: Option<@param_substs>,
                 id: ast::node_id,
-                impl_id: Option<ast::def_id>,
                 attrs: &[ast::attribute]) {
     let do_time = ccx.sess.trans_stats();
     let start = if do_time { time::get_time() }
@@ -1881,7 +1865,6 @@ pub fn trans_fn(ccx: @mut CrateContext,
                   self_arg,
                   param_substs,
                   id,
-                  impl_id,
                   attrs,
                   output_type,
                   |fcx| {
@@ -1931,7 +1914,6 @@ pub fn trans_enum_variant(ccx: @mut CrateContext,
                                llfndecl,
                                variant.node.id,
                                enum_ty,
-                               None,
                                param_substs,
                                None);
 
@@ -2011,7 +1993,6 @@ pub fn trans_tuple_struct(ccx: @mut CrateContext,
                                llfndecl,
                                ctor_id,
                                tup_ty,
-                               None,
                                param_substs,
                                None);
 
@@ -2091,7 +2072,6 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
                      no_self,
                      None,
                      item.id,
-                     None,
                      item.attrs);
         } else {
             for body.node.stmts.iter().advance |stmt| {
@@ -2447,7 +2427,6 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
             }
           }
           ast_map::node_method(m, _, pth) => {
-            exprt = true;
             register_method(ccx, id, pth, m)
           }
           ast_map::node_foreign_item(ni, _, _, pth) => {
@@ -2521,7 +2500,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
                               variant))
           }
         };
-        if !(exprt || ccx.reachable.contains(&id)) {
+        if !exprt && !ccx.reachable.contains(&id) {
             lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage);
         }
         ccx.item_vals.insert(id, val);
@@ -2532,12 +2511,15 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::node_id) -> ValueRef {
 
 pub fn register_method(ccx: @mut CrateContext,
                        id: ast::node_id,
-                       pth: @ast_map::path,
+                       path: @ast_map::path,
                        m: @ast::method) -> ValueRef {
     let mty = ty::node_id_to_type(ccx.tcx, id);
-    let pth = vec::append(/*bad*/copy *pth, [path_name((ccx.names)("meth")),
-                                  path_name(m.ident)]);
-    let llfn = register_fn_full(ccx, m.span, pth, id, m.attrs, mty);
+
+    let mut path = /*bad*/ copy *path;
+    path.push(path_name(gensym_name("meth")));
+    path.push(path_name(m.ident));
+
+    let llfn = register_fn_full(ccx, m.span, path, id, m.attrs, mty);
     set_inline_hint_if_appr(m.attrs, llfn);
     llfn
 }
@@ -2825,13 +2807,13 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_
         encoder::EncodeParams {
             diag: diag,
             tcx: cx.tcx,
-            reachable: cx.reachable,
             reexports2: cx.exp_map2,
             item_symbols: item_symbols,
             discrim_symbols: discrim_symbols,
             link_meta: link_meta,
             cstore: cx.sess.cstore,
-            encode_inlined_item: ie
+            encode_inlined_item: ie,
+            reachable: cx.reachable,
         }
 }
 
@@ -2897,16 +2879,12 @@ pub fn trans_crate(sess: session::Session,
                    tcx: ty::ctxt,
                    output: &Path,
                    emap2: resolve::ExportMap2,
-                   maps: astencode::Maps) -> (ContextRef, ModuleRef, LinkMeta) {
+                   reachable_map: @mut HashSet<ast::node_id>,
+                   maps: astencode::Maps)
+                   -> (ContextRef, ModuleRef, LinkMeta) {
 
     let mut symbol_hasher = hash::default_state();
     let link_meta = link::build_link_meta(sess, crate, output, &mut symbol_hasher);
-    let reachable = reachable::find_reachable(
-        &crate.node.module,
-        emap2,
-        tcx,
-        maps.method_map
-    );
 
     // Append ".rc" to crate name as LLVM module identifier.
     //
@@ -2924,8 +2902,15 @@ pub fn trans_crate(sess: session::Session,
     //     sess.bug("couldn't enable multi-threaded LLVM");
     // }
 
-    let ccx = @mut CrateContext::new(sess, llmod_id, tcx, emap2, maps,
-                                 symbol_hasher, link_meta, reachable);
+    let ccx = @mut CrateContext::new(sess,
+                                     llmod_id,
+                                     tcx,
+                                     emap2,
+                                     maps,
+                                     symbol_hasher,
+                                     link_meta,
+                                     reachable_map);
+
     {
         let _icx = push_ctxt("data");
         trans_constants(ccx, crate);
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 83c1a3c80db..dc32a3b4e2c 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -68,13 +68,13 @@ pub fn count_insn(cx: block, category: &str) {
         i = 0u;
         while i < len {
             i = *mm.get(&v[i]);
-            s += "/";
-            s += v[i];
+            s.push_char('/');
+            s.push_str(v[i]);
             i += 1u;
         }
 
-        s += "/";
-        s += category;
+        s.push_char('/');
+        s.push_str(category);
 
         let n = match h.find(&s) {
           Some(&n) => n,
@@ -610,12 +610,21 @@ pub fn GEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef {
 
 // Simple wrapper around GEP that takes an array of ints and wraps them
 // in C_i32()
-//
-// FIXME #6571: Use a small-vector optimization to avoid allocations here.
+#[inline]
 pub fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef {
-    let v = do vec::map(ixs) |i| { C_i32(*i as i32) };
-    count_insn(cx, "gepi");
-    return InBoundsGEP(cx, base, v);
+    // Small vector optimization. This should catch 100% of the cases that
+    // we care about.
+    if ixs.len() < 16 {
+        let mut small_vec = [ C_i32(0), ..16 ];
+        for ixs.iter().enumerate().advance |(i, &ix)| {
+            small_vec[i] = C_i32(ix as i32)
+        }
+        InBoundsGEP(cx, base, small_vec.slice(0, ixs.len()))
+    } else {
+        let v = do vec::map(ixs) |i| { C_i32(*i as i32) };
+        count_insn(cx, "gepi");
+        InBoundsGEP(cx, base, v)
+    }
 }
 
 pub fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef {
diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs
index ac51c7efc6f..45fdda1990c 100644
--- a/src/librustc/middle/trans/cabi_arm.rs
+++ b/src/librustc/middle/trans/cabi_arm.rs
@@ -139,12 +139,14 @@ impl ABIInfo for ARM_ABIInfo {
             attrs.push(attr);
         }
 
-        let mut (ret_ty, ret_attr) = if ret_def {
+        let (ret_ty, ret_attr) = if ret_def {
             classify_ret_ty(rty)
         } else {
             (LLVMType { cast: false, ty: Type::void() }, None)
         };
 
+        let mut ret_ty = ret_ty;
+
         let sret = ret_attr.is_some();
         if sret {
             arg_tys.unshift(ret_ty);
diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs
index 8604ae37f77..47f2fb8634c 100644
--- a/src/librustc/middle/trans/cabi_mips.rs
+++ b/src/librustc/middle/trans/cabi_mips.rs
@@ -178,12 +178,14 @@ impl ABIInfo for MIPS_ABIInfo {
                     atys: &[Type],
                     rty: Type,
                     ret_def: bool) -> FnType {
-        let mut (ret_ty, ret_attr) = if ret_def {
+        let (ret_ty, ret_attr) = if ret_def {
             classify_ret_ty(rty)
         } else {
             (LLVMType { cast: false, ty: Type::void() }, None)
         };
 
+        let mut ret_ty = ret_ty;
+
         let sret = ret_attr.is_some();
         let mut arg_tys = ~[];
         let mut attrs = ~[];
diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs
index 14ab17f5030..6c264e637a6 100644
--- a/src/librustc/middle/trans/cabi_x86_64.rs
+++ b/src/librustc/middle/trans/cabi_x86_64.rs
@@ -39,7 +39,11 @@ enum RegClass {
     Memory
 }
 
-impl Type {
+trait TypeMethods {
+    fn is_reg_ty(&self) -> bool;
+}
+
+impl TypeMethods for Type {
     fn is_reg_ty(&self) -> bool {
         match self.kind() {
             Integer | Pointer | Float | Double => true,
@@ -312,7 +316,7 @@ fn llreg_ty(cls: &[RegClass]) -> Type {
                 tys.push(Type::i64());
             }
             SSEFv => {
-                let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
+                let vec_len = llvec_len(cls.tailn(i + 1u)) * 2u;
                 let vec_ty = Type::vector(&Type::f32(), vec_len as u64);
                 tys.push(vec_ty);
                 i += vec_len;
@@ -360,8 +364,9 @@ fn x86_64_tys(atys: &[Type],
         arg_tys.push(ty);
         attrs.push(attr);
     }
-    let mut (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(),
+    let (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(),
                                        StructRetAttribute);
+    let mut ret_ty = ret_ty;
     let sret = ret_attr.is_some();
     if sret {
         arg_tys = vec::append(~[ret_ty], arg_tys);
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index cb475550638..4c07f88f16e 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -17,6 +17,7 @@
 // closure.
 
 use core::prelude::*;
+use core::vec;
 
 use back::abi;
 use driver::session;
@@ -47,7 +48,6 @@ use util::ppaux::Repr;
 
 use middle::trans::type_::Type;
 
-use core::vec;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::visit;
@@ -64,6 +64,7 @@ pub struct MethodData {
     llself: ValueRef,
     self_ty: ty::t,
     self_mode: ty::SelfMode,
+    explicit_self: ast::explicit_self_
 }
 
 pub enum CalleeData {
@@ -146,7 +147,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
             ast::def_static(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
             ast::def_use(*) | ast::def_typaram_binder(*) |
             ast::def_region(*) | ast::def_label(*) | ast::def_ty_param(*) |
-            ast::def_self_ty(*) => {
+            ast::def_self_ty(*) | ast::def_method(*) => {
                 bcx.tcx().sess.span_bug(
                     ref_expr.span,
                     fmt!("Cannot translate def %? \
@@ -194,6 +195,58 @@ pub fn trans_fn_ref_with_vtables_to_callee(
                                                type_params, vtables))}
 }
 
+fn get_impl_resolutions(bcx: block,
+                        impl_id: ast::def_id)
+                         -> typeck::vtable_res {
+    if impl_id.crate == ast::local_crate {
+        *bcx.ccx().maps.vtable_map.get(&impl_id.node)
+    } else {
+        // XXX: This is a temporary hack to work around not properly
+        // exporting information about resolutions for impls.
+        // This doesn't actually work if the trait has param bounds,
+        // but it does allow us to survive the case when it does not.
+        let trait_ref = ty::impl_trait_ref(bcx.tcx(), impl_id).get();
+        @vec::from_elem(trait_ref.substs.tps.len(), @~[])
+    }
+}
+
+fn resolve_default_method_vtables(bcx: block,
+                                  impl_id: ast::def_id,
+                                  method: &ty::Method,
+                                  substs: &ty::substs,
+                                  impl_vtables: Option<typeck::vtable_res>)
+                                 -> typeck::vtable_res {
+
+    // Get the vtables that the impl implements the trait at
+    let trait_vtables = get_impl_resolutions(bcx, impl_id);
+
+    // Build up a param_substs that we are going to resolve the
+    // trait_vtables under.
+    let param_substs = Some(@param_substs {
+        tys: copy substs.tps,
+        self_ty: substs.self_ty,
+        vtables: impl_vtables,
+        self_vtable: None
+    });
+
+    let trait_vtables_fixed = resolve_vtables_under_param_substs(
+        bcx.tcx(), param_substs, trait_vtables);
+
+    // Now we pull any vtables for parameters on the actual method.
+    let num_method_vtables = method.generics.type_param_defs.len();
+    let method_vtables = match impl_vtables {
+        Some(vtables) => {
+            let num_impl_type_parameters =
+                vtables.len() - num_method_vtables;
+            vtables.tailn(num_impl_type_parameters).to_owned()
+        },
+        None => vec::from_elem(num_method_vtables, @~[])
+    };
+
+    @(*trait_vtables_fixed + method_vtables)
+}
+
+
 pub fn trans_fn_ref_with_vtables(
         bcx: block,            //
         def_id: ast::def_id,   // def id of fn
@@ -233,15 +286,21 @@ pub fn trans_fn_ref_with_vtables(
     // Polytype of the function item (may have type params)
     let fn_tpt = ty::lookup_item_type(tcx, def_id);
 
-    let substs = ty::substs { self_r: None, self_ty: None,
+    // For simplicity, we want to use the Subst trait when composing
+    // substitutions for default methods.  The subst trait does
+    // substitutions with regions, though, so we put a dummy self
+    // region parameter in to keep it from failing. This is a hack.
+    let substs = ty::substs { self_r: Some(ty::re_empty),
+                              self_ty: None,
                               tps: /*bad*/ type_params.to_owned() };
 
 
     // We need to do a bunch of special handling for default methods.
     // We need to modify the def_id and our substs in order to monomorphize
     // the function.
-    let (def_id, opt_impl_did, substs) = match tcx.provided_method_sources.find(&def_id) {
-        None => (def_id, None, substs),
+    let (def_id, opt_impl_did, substs, self_vtable, vtables) =
+        match tcx.provided_method_sources.find(&def_id) {
+        None => (def_id, None, substs, None, vtables),
         Some(source) => {
             // There are two relevant substitutions when compiling
             // default methods. First, there is the substitution for
@@ -261,20 +320,42 @@ pub fn trans_fn_ref_with_vtables(
                          default methods");
             let method = ty::method(tcx, source.method_id);
 
+            // Get all of the type params for the receiver
+            let param_defs = method.generics.type_param_defs;
+            let receiver_substs =
+                type_params.initn(param_defs.len()).to_owned();
+            let receiver_vtables = match vtables {
+                None => @~[],
+                Some(call_vtables) => {
+                    @call_vtables.initn(param_defs.len()).to_owned()
+                }
+            };
+
+            let self_vtable =
+                typeck::vtable_static(source.impl_id, receiver_substs,
+                                      receiver_vtables);
             // Compute the first substitution
             let first_subst = make_substs_for_receiver_types(
                 tcx, source.impl_id, trait_ref, method);
 
             // And compose them
             let new_substs = first_subst.subst(tcx, &substs);
+
+
+            let vtables =
+                resolve_default_method_vtables(bcx, source.impl_id,
+                                               method, &new_substs, vtables);
+
             debug!("trans_fn_with_vtables - default method: \
                     substs = %s, trait_subst = %s, \
-                    first_subst = %s, new_subst = %s",
+                    first_subst = %s, new_subst = %s, \
+                    self_vtable = %s, vtables = %s",
                    substs.repr(tcx), trait_ref.substs.repr(tcx),
-                   first_subst.repr(tcx), new_substs.repr(tcx));
+                   first_subst.repr(tcx), new_substs.repr(tcx),
+                   self_vtable.repr(tcx), vtables.repr(tcx));
 
-
-            (source.method_id, Some(source.impl_id), new_substs)
+            (source.method_id, Some(source.impl_id),
+             new_substs, Some(self_vtable), Some(vtables))
         }
     };
 
@@ -319,9 +400,11 @@ pub fn trans_fn_ref_with_vtables(
         // Should be either intra-crate or inlined.
         assert_eq!(def_id.crate, ast::local_crate);
 
-        let mut (val, must_cast) =
+        let (val, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, &substs,
-                                         vtables, opt_impl_did, Some(ref_id));
+                                         vtables, self_vtable,
+                                         opt_impl_did, Some(ref_id));
+        let mut val = val;
         if must_cast && ref_id != 0 {
             // Monotype of the REFERENCE to the function (type params
             // are subst'd)
@@ -503,7 +586,7 @@ pub fn trans_call_inner(in_cx: block,
     do base::with_scope(in_cx, call_info, "call") |cx| {
         let ret_in_loop = match args {
           ArgExprs(args) => {
-            args.len() > 0u && match vec::last(args).node {
+            args.len() > 0u && match args.last().node {
               ast::expr_loop_body(@ast::expr {
                 node: ast::expr_fn_block(_, ref body),
                 _
@@ -566,7 +649,8 @@ pub fn trans_call_inner(in_cx: block,
         // Now that the arguments have finished evaluating, we need to revoke
         // the cleanup for the self argument, if it exists
         match callee.data {
-            Method(d) if d.self_mode == ty::ByCopy => {
+            Method(d) if d.self_mode == ty::ByCopy ||
+                         d.explicit_self == ast::sty_value => {
                 revoke_clean(bcx, d.llself);
             }
             _ => {}
@@ -688,6 +772,7 @@ pub fn trans_args(cx: block,
                 trans_arg_expr(bcx,
                                arg_tys[i],
                                ty::ByCopy,
+                               ast::sty_static,
                                *arg_expr,
                                &mut temp_cleanups,
                                if i == last { ret_flag } else { None },
@@ -721,6 +806,7 @@ pub enum AutorefArg {
 pub fn trans_arg_expr(bcx: block,
                       formal_arg_ty: ty::t,
                       self_mode: ty::SelfMode,
+                      ex_self: ast::explicit_self_,
                       arg_expr: @ast::expr,
                       temp_cleanups: &mut ~[ValueRef],
                       ret_flag: Option<ValueRef>,
@@ -728,9 +814,10 @@ pub fn trans_arg_expr(bcx: block,
     let _icx = push_ctxt("trans_arg_expr");
     let ccx = bcx.ccx();
 
-    debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s, \
+    debug!("trans_arg_expr(formal_arg_ty=(%s), explicit_self=%? self_mode=%?, arg_expr=%s, \
             ret_flag=%?)",
            formal_arg_ty.repr(bcx.tcx()),
+           ex_self,
            self_mode,
            arg_expr.repr(bcx.tcx()),
            ret_flag.map(|v| bcx.val_to_str(*v)));
@@ -790,8 +877,26 @@ pub fn trans_arg_expr(bcx: block,
                 val = arg_datum.to_ref_llval(bcx);
             }
             DontAutorefArg => {
-                match self_mode {
-                    ty::ByRef => {
+                match (self_mode, ex_self) {
+                    (ty::ByRef, ast::sty_value) => {
+                        debug!("by value self with type %s, storing to scratch",
+                               bcx.ty_to_str(arg_datum.ty));
+                        let scratch = scratch_datum(bcx, arg_datum.ty, false);
+
+                        arg_datum.store_to_datum(bcx,
+                                                 arg_expr.id,
+                                                 INIT,
+                                                 scratch);
+
+                        // Technically, ownership of val passes to the callee.
+                        // However, we must cleanup should we fail before the
+                        // callee is actually invoked.
+                        scratch.add_clean(bcx);
+                        temp_cleanups.push(scratch.val);
+
+                        val = scratch.to_ref_llval(bcx);
+                    }
+                    (ty::ByRef, _) => {
                         // This assertion should really be valid, but because
                         // the explicit self code currently passes by-ref, it
                         // does not hold.
@@ -802,7 +907,7 @@ pub fn trans_arg_expr(bcx: block,
                                bcx.ty_to_str(arg_datum.ty));
                         val = arg_datum.to_ref_llval(bcx);
                     }
-                    ty::ByCopy => {
+                    (ty::ByCopy, _) => {
                         if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
                                 arg_datum.appropriate_mode().is_by_ref() {
                             debug!("by copy arg with type %s, storing to scratch",
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 3ce52a63171..ad68ffb402e 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -444,7 +444,6 @@ pub fn trans_expr_fn(bcx: block,
                           no_self,
                           /*bad*/ copy bcx.fcx.param_substs,
                           user_id,
-                          None,
                           [],
                           real_return_type,
                           |fcx| load_environment(fcx, cdata_ty, cap_vars,
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 79d83fbc857..b255f2ca78c 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -36,6 +36,8 @@ use core::cast;
 use core::hashmap::{HashMap};
 use core::libc::{c_uint, c_longlong, c_ulonglong};
 use core::to_bytes;
+use core::str;
+use core::vec::raw::to_ptr;
 use core::vec;
 use syntax::ast::ident;
 use syntax::ast_map::{path, path_elt};
@@ -45,14 +47,8 @@ use syntax::{ast, ast_map};
 
 pub use middle::trans::context::CrateContext;
 
-// NOTE: this thunk is totally pointless now that we're not passing
-// interners around...
-pub type namegen = @fn(s: &str) -> ident;
-pub fn new_namegen() -> namegen {
-    let f: @fn(s: &str) -> ident = |prefix| {
-        token::str_to_ident(fmt!("%s_%u", prefix, token::gensym(prefix)))
-    };
-    f
+pub fn gensym_name(name: &str) -> ident {
+    token::str_to_ident(fmt!("%s_%u", name, token::gensym(name)))
 }
 
 pub struct tydesc_info {
@@ -136,9 +132,9 @@ pub struct ValSelfData {
 // will only be set in the case of default methods.
 pub struct param_substs {
     tys: ~[ty::t],
+    self_ty: Option<ty::t>,
     vtables: Option<typeck::vtable_res>,
-    type_param_defs: @~[ty::TypeParameterDef],
-    self_ty: Option<ty::t>
+    self_vtable: Option<typeck::vtable_origin>
 }
 
 impl param_substs {
@@ -149,10 +145,9 @@ impl param_substs {
 }
 
 fn param_substs_to_str(this: &param_substs, tcx: ty::ctxt) -> ~str {
-    fmt!("param_substs {tys:%s, vtables:%s, type_param_defs:%s}",
+    fmt!("param_substs {tys:%s, vtables:%s}",
          this.tys.repr(tcx),
-         this.vtables.repr(tcx),
-         this.type_param_defs.repr(tcx))
+         this.vtables.repr(tcx))
 }
 
 impl Repr for param_substs {
@@ -229,9 +224,6 @@ pub struct fn_ctxt_ {
     // a user-defined function.
     id: ast::node_id,
 
-    // The def_id of the impl we're inside, or None if we aren't inside one.
-    impl_id: Option<ast::def_id>,
-
     // If this function is being monomorphized, this contains the type
     // substitutions used.
     param_substs: Option<@param_substs>,
@@ -418,10 +410,9 @@ pub fn revoke_clean(cx: block, val: ValueRef) {
             });
         for cleanup_pos.iter().advance |i| {
             scope_info.cleanups =
-                vec::append(vec::slice(scope_info.cleanups, 0u, *i).to_owned(),
-                            vec::slice(scope_info.cleanups,
-                                      *i + 1u,
-                                      scope_info.cleanups.len()));
+                vec::append(scope_info.cleanups.slice(0u, *i).to_owned(),
+                            scope_info.cleanups.slice(*i + 1u,
+                                                      scope_info.cleanups.len()));
             shrink_scope_clean(scope_info, *i);
         }
     }
@@ -820,8 +811,9 @@ pub fn C_bytes(bytes: &[u8]) -> ValueRef {
 
 pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
     unsafe {
-        let ptr = cast::transmute(vec::raw::to_ptr(bytes));
-        return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint,False);
+        return llvm::LLVMConstStringInContext(base::task_llcx(),
+            cast::transmute(vec::raw::to_ptr(bytes)),
+            bytes.len() as c_uint, False);
     }
 }
 
@@ -870,7 +862,7 @@ pub fn is_null(val: ValueRef) -> bool {
 }
 
 // Used to identify cached monomorphized functions and vtables
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub enum mono_param_id {
     mono_precise(ty::t, Option<@~[mono_id]>),
     mono_any,
@@ -880,7 +872,7 @@ pub enum mono_param_id {
               datum::DatumMode),
 }
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub enum MonoDataClass {
     MonoBits,    // Anything not treated differently from arbitrary integer data
     MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
@@ -905,7 +897,7 @@ pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
 }
 
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct mono_id_ {
     def: ast::def_id,
     params: ~[mono_param_id],
@@ -914,40 +906,6 @@ pub struct mono_id_ {
 
 pub type mono_id = @mono_id_;
 
-impl to_bytes::IterBytes for mono_param_id {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            mono_precise(t, ref mids) => {
-                0u8.iter_bytes(lsb0, f) &&
-                ty::type_id(t).iter_bytes(lsb0, f) &&
-                mids.iter_bytes(lsb0, f)
-            }
-
-            mono_any => 1u8.iter_bytes(lsb0, f),
-
-            mono_repr(ref a, ref b, ref c, ref d) => {
-                2u8.iter_bytes(lsb0, f) &&
-                a.iter_bytes(lsb0, f) &&
-                b.iter_bytes(lsb0, f) &&
-                c.iter_bytes(lsb0, f) &&
-                d.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
-impl to_bytes::IterBytes for MonoDataClass {
-    fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for mono_id_ {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.def.iter_bytes(lsb0, f) && self.params.iter_bytes(lsb0, f)
-    }
-}
-
 pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
     return build::Select(cx, cond, b, a);
@@ -970,9 +928,12 @@ pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str {
     for p.iter().advance |e| {
         match *e {
             ast_map::path_name(s) | ast_map::path_mod(s) => {
-                if first { first = false; }
-                else { r += "::"; }
-                r += sess.str_of(s);
+                if first {
+                    first = false
+                } else {
+                    r.push_str("::")
+                }
+                r.push_str(sess.str_of(s));
             }
         }
     }
@@ -984,7 +945,11 @@ pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
         Some(substs) => {
             ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
         }
-        _ => { assert!(!ty::type_has_params(t)); t }
+        _ => {
+            assert!(!ty::type_has_params(t));
+            assert!(!ty::type_has_self(t));
+            t
+        }
     }
 }
 
@@ -1033,17 +998,37 @@ pub fn node_vtables(bcx: block, id: ast::node_id)
 
 pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
     -> typeck::vtable_res {
-    @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d))
+    resolve_vtables_under_param_substs(fcx.ccx.tcx,
+                                       fcx.param_substs,
+                                       vts)
 }
 
+pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
+                                          param_substs: Option<@param_substs>,
+                                          vts: typeck::vtable_res)
+    -> typeck::vtable_res {
+    @vec::map(*vts, |ds|
+      @vec::map(**ds, |d|
+                resolve_vtable_under_param_substs(tcx, param_substs, copy *d)))
+}
+
+
 // Apply the typaram substitutions in the fn_ctxt to a vtable. This should
 // eliminate any vtable_params.
 pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
     -> typeck::vtable_origin {
-    let tcx = fcx.ccx.tcx;
+    resolve_vtable_under_param_substs(fcx.ccx.tcx,
+                                      fcx.param_substs,
+                                      vt)
+}
+
+pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
+                                         param_substs: Option<@param_substs>,
+                                         vt: typeck::vtable_origin)
+    -> typeck::vtable_origin {
     match vt {
         typeck::vtable_static(trait_id, tys, sub) => {
-            let tys = match fcx.param_substs {
+            let tys = match param_substs {
                 Some(substs) => {
                     do vec::map(tys) |t| {
                         ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
@@ -1051,11 +1036,12 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
                 }
                 _ => tys
             };
-            typeck::vtable_static(trait_id, tys,
-                                  resolve_vtables_in_fn_ctxt(fcx, sub))
+            typeck::vtable_static(
+                trait_id, tys,
+                resolve_vtables_under_param_substs(tcx, param_substs, sub))
         }
         typeck::vtable_param(n_param, n_bound) => {
-            match fcx.param_substs {
+            match param_substs {
                 Some(substs) => {
                     find_vtable(tcx, substs, n_param, n_bound)
                 }
@@ -1066,6 +1052,19 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
                 }
             }
         }
+        typeck::vtable_self(_trait_id) => {
+            match param_substs {
+                Some(@param_substs
+                     {self_vtable: Some(ref self_vtable), _}) => {
+                    copy *self_vtable
+                }
+                _ => {
+                    tcx.sess.bug(fmt!(
+                        "resolve_vtable_in_fn_ctxt: asked to lookup but \
+                         no self_vtable in the fn_ctxt!"))
+                }
+            }
+        }
     }
 }
 
@@ -1075,13 +1074,7 @@ pub fn find_vtable(tcx: ty::ctxt, ps: &param_substs,
     debug!("find_vtable(n_param=%u, n_bound=%u, ps=%s)",
            n_param, n_bound, ps.repr(tcx));
 
-    // Vtables are stored in a flat array, finding the right one is
-    // somewhat awkward
-    let first_n_type_param_defs = ps.type_param_defs.slice(0, n_param);
-    let vtables_to_skip =
-        ty::count_traits_and_supertraits(tcx, first_n_type_param_defs);
-    let vtable_off = vtables_to_skip + n_bound;
-    /*bad*/ copy ps.vtables.get()[vtable_off]
+    /*bad*/ copy ps.vtables.get()[n_param][n_bound]
 }
 
 pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index a0ae579c865..9b81fc406b7 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -21,7 +21,6 @@ use middle::resolve;
 use middle::trans::adt;
 use middle::trans::base;
 use middle::trans::debuginfo;
-use middle::trans::reachable;
 use middle::trans::type_use;
 use middle::ty;
 
@@ -34,8 +33,7 @@ use core::local_data;
 use extra::time;
 use syntax::ast;
 
-use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res,Stats,namegen};
-use middle::trans::common::{mono_id,new_namegen};
+use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
 
 use middle::trans::base::{decl_crate_map};
 
@@ -49,7 +47,7 @@ pub struct CrateContext {
      intrinsics: HashMap<&'static str, ValueRef>,
      item_vals: HashMap<ast::node_id, ValueRef>,
      exp_map2: resolve::ExportMap2,
-     reachable: reachable::map,
+     reachable: @mut HashSet<ast::node_id>,
      item_symbols: HashMap<ast::node_id, ~str>,
      link_meta: LinkMeta,
      enum_sizes: HashMap<ty::t, uint>,
@@ -93,7 +91,6 @@ pub struct CrateContext {
      lltypes: HashMap<ty::t, Type>,
      llsizingtypes: HashMap<ty::t, Type>,
      adt_reprs: HashMap<ty::t, @adt::Repr>,
-     names: namegen,
      symbol_hasher: hash::State,
      type_hashcodes: HashMap<ty::t, @str>,
      type_short_names: HashMap<ty::t, ~str>,
@@ -117,10 +114,15 @@ pub struct CrateContext {
 }
 
 impl CrateContext {
-    pub fn new(sess: session::Session, name: &str, tcx: ty::ctxt,
-               emap2: resolve::ExportMap2, maps: astencode::Maps,
-               symbol_hasher: hash::State, link_meta: LinkMeta,
-               reachable: reachable::map) -> CrateContext {
+    pub fn new(sess: session::Session,
+               name: &str,
+               tcx: ty::ctxt,
+               emap2: resolve::ExportMap2,
+               maps: astencode::Maps,
+               symbol_hasher: hash::State,
+               link_meta: LinkMeta,
+               reachable: @mut HashSet<ast::node_id>)
+               -> CrateContext {
         unsafe {
             let llcx = llvm::LLVMContextCreate();
             set_task_llcx(llcx);
@@ -194,7 +196,6 @@ impl CrateContext {
                   lltypes: HashMap::new(),
                   llsizingtypes: HashMap::new(),
                   adt_reprs: HashMap::new(),
-                  names: new_namegen(),
                   symbol_hasher: symbol_hasher,
                   type_hashcodes: HashMap::new(),
                   type_short_names: HashMap::new(),
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index dae3d58d2be..22448f577a3 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -56,7 +56,7 @@ use util::ppaux::ty_to_str;
 
 use core::hashmap::HashMap;
 use core::libc;
-use core::libc::c_uint;
+use core::libc::{c_uint, c_ulonglong};
 use core::cmp;
 use core::ptr;
 use core::str::as_c_str;
@@ -64,6 +64,7 @@ use core::sys;
 use core::vec;
 use syntax::codemap::span;
 use syntax::{ast, codemap, ast_util, ast_map};
+use syntax::parse::token;
 
 static DW_LANG_RUST: int = 0x9000;
 
@@ -86,7 +87,6 @@ static DW_ATE_unsigned_char: int = 0x08;
 
 /// A context object for maintaining all state needed by the debuginfo module.
 pub struct DebugContext {
-    names: namegen,
     crate_file: ~str,
     llcontext: ContextRef,
     builder: DIBuilderRef,
@@ -104,7 +104,6 @@ impl DebugContext {
         // DIBuilder inherits context from the module, so we'd better use the same one
         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
         return DebugContext {
-            names: new_namegen(),
             crate_file: crate,
             llcontext: llcontext,
             builder: builder,
@@ -211,9 +210,17 @@ pub fn create_arg(bcx: block, arg: ast::arg, span: span) -> Option<DIVariable> {
             let ident = path.idents.last();
             let name: &str = cx.sess.str_of(*ident);
             let mdnode = do as_c_str(name) |name| { unsafe {
-                llvm::LLVMDIBuilderCreateLocalVariable(DIB(cx),
-                    ArgVariableTag as u32, context, name,
-                    filemd, loc.line as c_uint, tymd, false, 0, 0)
+                llvm::LLVMDIBuilderCreateLocalVariable(
+                    DIB(cx),
+                    ArgVariableTag as u32,
+                    context,
+                    name,
+                    filemd,
+                    loc.line as c_uint,
+                    tymd,
+                    false,
+                    0,
+                    0)
                     // XXX need to pass in a real argument number
             }};
 
@@ -268,7 +275,8 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
       ast_map::node_expr(expr) => {
         match expr.node {
           ast::expr_fn_block(ref decl, _) => {
-            ((dbg_cx(cx).names)("fn"), decl.output, expr.id)
+            let name = gensym_name("fn");
+            (name, decl.output, expr.id)
           }
           _ => fcx.ccx.sess.span_bug(expr.span,
                   "create_function: expected an expr_fn_block here")
@@ -290,16 +298,17 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
     let ret_ty_md = if cx.sess.opts.extra_debuginfo {
         match ret_ty.node {
           ast::ty_nil => ptr::null(),
-          _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id),
-                         ret_ty.span)
+          _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span)
         }
     } else {
         ptr::null()
     };
 
     let fn_ty = unsafe {
-        llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx),
-            file_md, create_DIArray(DIB(cx), [ret_ty_md]))
+        llvm::LLVMDIBuilderCreateSubroutineType(
+            DIB(cx),
+            file_md,
+            create_DIArray(DIB(cx), [ret_ty_md]))
     };
 
     let fn_md =
@@ -308,13 +317,19 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
             llvm::LLVMDIBuilderCreateFunction(
                 DIB(cx),
                 file_md,
-                name, linkage,
-                file_md, loc.line as c_uint,
-                fn_ty, false, true,
+                name,
+                linkage,
+                file_md,
+                loc.line as c_uint,
+                fn_ty,
+                false,
+                true,
                 loc.line as c_uint,
                 FlagPrototyped as c_uint,
                 cx.sess.opts.optimize != session::No,
-                fcx.llfn, ptr::null(), ptr::null())
+                fcx.llfn,
+                ptr::null(),
+                ptr::null())
             }}};
 
     dbg_cx(cx).created_functions.insert(id, fn_md);
@@ -337,6 +352,9 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
 fn create_compile_unit(cx: @mut CrateContext) {
     let dcx = dbg_cx(cx);
     let crate_name: &str = dcx.crate_file;
+
+    debug!("create_compile_unit: %?", crate_name);
+
     let work_dir = cx.sess.working_dir.to_str();
     let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
 
@@ -352,7 +370,7 @@ fn create_compile_unit(cx: @mut CrateContext) {
     }}}}}};
 }
 
-fn create_file(cx: @mut CrateContext, full_path: &str) -> DIFile {
+fn create_file(cx: &mut CrateContext, full_path: &str) -> DIFile {
     match dbg_cx(cx).created_files.find_equiv(&full_path) {
         Some(file_md) => return *file_md,
         None => ()
@@ -422,7 +440,7 @@ fn create_block(bcx: block) -> DILexicalBlock {
 
 
 
-fn create_basic_type(cx: @mut CrateContext, t: ty::t, _span: span) -> DIType {
+fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType {
     let ty_id = ty::type_id(t);
     match dbg_cx(cx).created_types.find(&ty_id) {
         Some(ty_md) => return *ty_md,
@@ -460,8 +478,11 @@ fn create_basic_type(cx: @mut CrateContext, t: ty::t, _span: span) -> DIType {
     let (size, align) = size_and_align_of(cx, t);
     let ty_md = do as_c_str(name) |name| { unsafe {
             llvm::LLVMDIBuilderCreateBasicType(
-                DIB(cx), name,
-                size * 8 as u64, align * 8 as u64, encoding as c_uint)
+                DIB(cx),
+                name,
+                bytes_to_bits(size),
+                bytes_to_bits(align),
+                encoding as c_uint)
         }};
 
     // One could think that this call is not necessary, as the create_ty() function will insert the
@@ -471,12 +492,16 @@ fn create_basic_type(cx: @mut CrateContext, t: ty::t, _span: span) -> DIType {
     return ty_md;
 }
 
-fn create_pointer_type(cx: @mut CrateContext, t: ty::t, _span: span, pointee: DIType) -> DIType {
+fn create_pointer_type(cx: &mut CrateContext, t: ty::t, _span: span, pointee: DIType) -> DIType {
     let (size, align) = size_and_align_of(cx, t);
     let name = ty_to_str(cx.tcx, t);
     let ptr_md = do as_c_str(name) |name| { unsafe {
-        llvm::LLVMDIBuilderCreatePointerType(DIB(cx),
-                pointee, size * 8 as u64, align * 8 as u64, name)
+        llvm::LLVMDIBuilderCreatePointerType(
+            DIB(cx),
+            pointee,
+            bytes_to_bits(size),
+            bytes_to_bits(align),
+            name)
     }};
     return ptr_md;
 }
@@ -492,9 +517,9 @@ struct StructContext {
 }
 
 impl StructContext {
-    fn new(cx: &CrateContext, name: ~str, file: DIFile, line: uint) -> ~StructContext {
+    fn new(cx: &CrateContext, name: ~str, file: DIFile, line: uint) -> StructContext {
         debug!("StructContext::create: %s", name);
-        let scx = ~StructContext {
+        return StructContext {
             builder: DIB(cx),
             file: file,
             name: name,
@@ -503,18 +528,26 @@ impl StructContext {
             total_size: 0,
             align: 1
         };
-        return scx;
     }
 
     fn add_member(&mut self, name: &str, line: uint, size: uint, align: uint, ty: DIType) {
-        debug!("StructContext(%s)::add_member: %s, size=%u, align=%u",
-                self.name, name, size, align);
         let offset = roundup(self.total_size, align);
+
+        debug!("StructContext(%s)::add_member: %s, size=%u, align=%u, offset=%u",
+                self.name, name, size, align, offset);
+
         let mem_t = do as_c_str(name) |name| { unsafe {
             llvm::LLVMDIBuilderCreateMemberType(
-                self.builder, ptr::null(), name, self.file, line as c_uint,
-                size * 8 as u64, align * 8 as u64, offset * 8 as u64,
-                0, ty)
+                self.builder,
+                self.file,
+                name,
+                self.file,
+                line as c_uint,
+                bytes_to_bits(size),
+                bytes_to_bits(align),
+                bytes_to_bits(offset),
+                0,
+                ty)
             }};
         self.members.push(mem_t);
         self.total_size = offset + size;
@@ -522,29 +555,48 @@ impl StructContext {
         self.align = cmp::max(self.align, align);
     }
 
+    fn get_total_size_with_alignment(&self) -> uint {
+        roundup(self.total_size, self.align)
+    }
+
     fn finalize(&self) -> DICompositeType {
         debug!("StructContext(%s)::finalize: total_size=%u, align=%u",
                 self.name, self.total_size, self.align);
         let members_md = create_DIArray(self.builder, self.members);
 
+        // The size of the struct/tuple must be rounded to the next multiple of its alignment.
+        // Otherwise gdb has trouble reading the struct correctly when it is embedded into another
+        // data structure. This is also the value `sizeof` in C would give.
+        let actual_total_size = self.get_total_size_with_alignment();
+
         let struct_md =
             do as_c_str(self.name) |name| { unsafe {
                 llvm::LLVMDIBuilderCreateStructType(
-                    self.builder, self.file, name,
-                    self.file, self.line as c_uint,
-                    self.total_size * 8 as u64, self.align * 8 as u64, 0, ptr::null(),
-                    members_md, 0, ptr::null())
+                    self.builder,
+                    self.file,
+                    name,
+                    self.file,
+                    self.line as c_uint,
+                    bytes_to_bits(actual_total_size),
+                    bytes_to_bits(self.align),
+                    0,
+                    ptr::null(),
+                    members_md,
+                    0,
+                    ptr::null())
             }};
         return struct_md;
     }
 }
 
-fn create_struct(cx: @mut CrateContext, t: ty::t, fields: ~[ty::field], span: span)
+fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field], span: span)
                 -> DICompositeType {
+    debug!("create_struct: %?", ty::get(struct_type));
+
     let loc = span_start(cx, span);
     let file_md = create_file(cx, loc.file.name);
 
-    let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, t), file_md, loc.line);
+    let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, struct_type), file_md, loc.line);
     for fields.iter().advance |field| {
         let field_t = field.mt.ty;
         let ty_md = create_ty(cx, field_t, span);
@@ -555,22 +607,28 @@ fn create_struct(cx: @mut CrateContext, t: ty::t, fields: ~[ty::field], span: sp
 }
 
 // returns (void* type as a ValueRef, size in bytes, align in bytes)
-fn voidptr(cx: @mut CrateContext) -> (DIDerivedType, uint, uint) {
+fn voidptr(cx: &mut CrateContext) -> (DIDerivedType, uint, uint) {
     let size = sys::size_of::<ValueRef>();
     let align = sys::min_align_of::<ValueRef>();
     let vp = do as_c_str("*void") |name| { unsafe {
-            llvm::LLVMDIBuilderCreatePointerType(DIB(cx), ptr::null(),
-                size*8 as u64, align*8 as u64, name)
+            llvm::LLVMDIBuilderCreatePointerType(
+                DIB(cx),
+                ptr::null(),
+                bytes_to_bits(size),
+                bytes_to_bits(align),
+                name)
         }};
     return (vp, size, align);
 }
 
-fn create_tuple(cx: @mut CrateContext, _t: ty::t, elements: &[ty::t], span: span)
+fn create_tuple(cx: &mut CrateContext, tuple_type: ty::t, elements: &[ty::t], span: span)
                 -> DICompositeType {
+    debug!("create_tuple: %?", ty::get(tuple_type));
+
     let loc = span_start(cx, span);
     let file_md = create_file(cx, loc.file.name);
 
-    let name = (cx.sess.str_of((dbg_cx(cx).names)("tuple"))).to_owned();
+    let name = fmt!("tuple_%u", token::gensym("tuple"));
     let mut scx = StructContext::new(cx, name, file_md, loc.line);
     for elements.iter().advance |element| {
         let ty_md = create_ty(cx, *element, span);
@@ -580,8 +638,10 @@ fn create_tuple(cx: @mut CrateContext, _t: ty::t, elements: &[ty::t], span: span
     return scx.finalize();
 }
 
-fn create_boxed_type(cx: @mut CrateContext, contents: ty::t,
+fn create_boxed_type(cx: &mut CrateContext, contents: ty::t,
                      span: span, boxed: DIType) -> DICompositeType {
+    debug!("create_boxed_type: %?", ty::get(contents));
+
     let loc = span_start(cx, span);
     let file_md = create_file(cx, loc.file.name);
     let int_t = ty::mk_int();
@@ -602,8 +662,10 @@ fn create_boxed_type(cx: @mut CrateContext, contents: ty::t,
     return scx.finalize();
 }
 
-fn create_fixed_vec(cx: @mut CrateContext, _vec_t: ty::t, elem_t: ty::t,
+fn create_fixed_vec(cx: &mut CrateContext, _vec_t: ty::t, elem_t: ty::t,
                     len: uint, span: span) -> DIType {
+    debug!("create_fixed_vec: %?", ty::get(_vec_t));
+
     let elem_ty_md = create_ty(cx, elem_t, span);
     let (size, align) = size_and_align_of(cx, elem_t);
 
@@ -613,23 +675,40 @@ fn create_fixed_vec(cx: @mut CrateContext, _vec_t: ty::t, elem_t: ty::t,
 
     let subscripts = create_DIArray(DIB(cx), [subrange]);
     return unsafe {
-        llvm::LLVMDIBuilderCreateArrayType(DIB(cx),
-            size * len * 8 as u64, align * 8 as u64, elem_ty_md, subscripts)
+        llvm::LLVMDIBuilderCreateArrayType(
+            DIB(cx),
+            bytes_to_bits(size * len),
+            bytes_to_bits(align),
+            elem_ty_md,
+            subscripts)
     };
 }
 
-fn create_boxed_vec(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t,
+fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t,
                     vec_ty_span: span) -> DICompositeType {
+    debug!("create_boxed_vec: %?", ty::get(vec_t));
+
     let loc = span_start(cx, vec_ty_span);
     let file_md = create_file(cx, loc.file.name);
     let elem_ty_md = create_ty(cx, elem_t, vec_ty_span);
 
     let mut vec_scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0);
     let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span);
-    vec_scx.add_member("fill", 0, sys::size_of::<libc::size_t>(),
-               sys::min_align_of::<libc::size_t>(), size_t_type);
-    vec_scx.add_member("alloc", 0, sys::size_of::<libc::size_t>(),
-               sys::min_align_of::<libc::size_t>(), size_t_type);
+
+    vec_scx.add_member(
+        "fill",
+        0,
+        sys::size_of::<libc::size_t>(),
+        sys::min_align_of::<libc::size_t>(),
+        size_t_type);
+
+    vec_scx.add_member(
+        "alloc",
+        0,
+        sys::size_of::<libc::size_t>(),
+        sys::min_align_of::<libc::size_t>(),
+        size_t_type);
+
     let subrange = unsafe {
         llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0_i64, 0_i64)
     };
@@ -638,18 +717,32 @@ fn create_boxed_vec(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t,
 
     let subscripts = create_DIArray(DIB(cx), [subrange]);
     let data_ptr = unsafe {
-        llvm::LLVMDIBuilderCreateArrayType(DIB(cx),
-            arr_size * 8 as u64, arr_align * 8 as u64, elem_ty_md, subscripts)
+        llvm::LLVMDIBuilderCreateArrayType(
+            DIB(cx),
+            bytes_to_bits(arr_size),
+            bytes_to_bits(arr_align),
+            elem_ty_md,
+            subscripts)
     };
-    vec_scx.add_member("data", 0, 0, // clang says the size should be 0
-               sys::min_align_of::<u8>(), data_ptr);
+    vec_scx.add_member(
+        "data",
+        0,
+        0, // clang says the size should be 0
+        sys::min_align_of::<u8>(), data_ptr);
+
     let vec_md = vec_scx.finalize();
 
     let mut box_scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0);
     let int_t = ty::mk_int();
     let refcount_type = create_basic_type(cx, int_t, vec_ty_span);
-    box_scx.add_member("refcnt", 0, sys::size_of::<uint>(),
-               sys::min_align_of::<uint>(), refcount_type);
+
+    box_scx.add_member(
+        "refcnt",
+        0,
+        sys::size_of::<uint>(),
+        sys::min_align_of::<uint>(),
+        refcount_type);
+
     let (vp, vpsize, vpalign) = voidptr(cx);
     box_scx.add_member("tydesc", 0, vpsize, vpalign, vp);
     box_scx.add_member("prev", 0, vpsize, vpalign, vp);
@@ -661,8 +754,10 @@ fn create_boxed_vec(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t,
     return mdval;
 }
 
-fn create_vec_slice(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: span)
+fn create_vec_slice(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: span)
                     -> DICompositeType {
+    debug!("create_vec_slice: %?", ty::get(vec_t));
+
     let loc = span_start(cx, span);
     let file_md = create_file(cx, loc.file.name);
     let elem_ty_md = create_ty(cx, elem_t, span);
@@ -672,13 +767,14 @@ fn create_vec_slice(cx: @mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: sp
     let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0);
     let (_, ptr_size, ptr_align) = voidptr(cx);
     scx.add_member("vec", 0, ptr_size, ptr_align, elem_ptr);
-    scx.add_member("length", 0, sys::size_of::<uint>(),
-                    sys::min_align_of::<uint>(), uint_type);
+    scx.add_member("length", 0, sys::size_of::<uint>(), sys::min_align_of::<uint>(), uint_type);
     return scx.finalize();
 }
 
-fn create_fn_ty(cx: @mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
+fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
                 span: span) -> DICompositeType {
+    debug!("create_fn_ty: %?", ty::get(_fn_ty));
+
     let loc = span_start(cx, span);
     let file_md = create_file(cx, loc.file.name);
     let (vp, _, _) = voidptr(cx);
@@ -688,22 +784,29 @@ fn create_fn_ty(cx: @mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output:
     let members = ~[output_ptr_md, vp] + inputs_vals;
 
     return unsafe {
-        llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_md,
+        llvm::LLVMDIBuilderCreateSubroutineType(
+            DIB(cx),
+            file_md,
             create_DIArray(DIB(cx), members))
     };
 }
 
-fn create_unimpl_ty(cx: @mut CrateContext, t: ty::t) -> DIType {
+fn create_unimpl_ty(cx: &mut CrateContext, t: ty::t) -> DIType {
+    debug!("create_unimpl_ty: %?", ty::get(t));
+
     let name = ty_to_str(cx.tcx, t);
     let md = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe {
         llvm::LLVMDIBuilderCreateBasicType(
-            DIB(cx), name,
-            0_u64, 8_u64, DW_ATE_unsigned as c_uint)
+            DIB(cx),
+            name,
+            0_u64,
+            8_u64,
+            DW_ATE_unsigned as c_uint)
         }};
     return md;
 }
 
-fn create_ty(cx: @mut CrateContext, t: ty::t, span: span) -> DIType {
+fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
     let ty_id = ty::type_id(t);
     match dbg_cx(cx).created_types.find(&ty_id) {
         Some(ty_md) => return *ty_md,
@@ -758,9 +861,9 @@ fn create_ty(cx: @mut CrateContext, t: ty::t, span: span) -> DIType {
             let pointee = create_ty(cx, mt.ty, span);
             create_pointer_type(cx, t, span, pointee)
         },
-        ty::ty_rptr(ref _region, ref _mt) => {
-            cx.sess.span_note(span, "debuginfo for rptr NYI");
-            create_unimpl_ty(cx, t)
+        ty::ty_rptr(_, ref mt) => {
+            let pointee = create_ty(cx, mt.ty, span);
+            create_pointer_type(cx, t, span, pointee)
         },
         ty::ty_bare_fn(ref barefnty) => {
             let inputs = barefnty.sig.inputs.map(|a| *a);
@@ -799,15 +902,15 @@ fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: ui
     let elems = ~[C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
     unsafe {
         let dbg_loc = llvm::LLVMMDNodeInContext(
-                dbg_cx(cx).llcontext, vec::raw::to_ptr(elems),
-                elems.len() as libc::c_uint);
+                dbg_cx(cx).llcontext,
+                vec::raw::to_ptr(elems),
+                elems.len() as c_uint);
+
         llvm::LLVMSetCurrentDebugLocation(cx.builder.B, dbg_loc);
     }
 }
 
 
-
-
 //=-------------------------------------------------------------------------------------------------
 //  Utility Functions
 //=-------------------------------------------------------------------------------------------------
@@ -819,14 +922,18 @@ fn roundup(x: uint, a: uint) -> uint {
 
 /// Return codemap::Loc corresponding to the beginning of the span
 fn span_start(cx: &CrateContext, span: span) -> codemap::Loc {
-    return cx.sess.codemap.lookup_char_pos(span.lo);
+    cx.sess.codemap.lookup_char_pos(span.lo)
 }
 
-fn size_and_align_of(cx: @mut CrateContext, t: ty::t) -> (uint, uint) {
+fn size_and_align_of(cx: &mut CrateContext, t: ty::t) -> (uint, uint) {
     let llty = type_of::type_of(cx, t);
     (machine::llsize_of_real(cx, llty), machine::llalign_of_min(cx, llty))
 }
 
+fn bytes_to_bits(bytes: uint) -> c_ulonglong {
+    (bytes * 8) as c_ulonglong
+}
+
 #[inline]
 fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext {
     cx.dbg_cx.get_mut_ref()
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 02f276cd050..35322730756 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -907,9 +907,12 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
         let scaled_ix = Mul(bcx, ix_val, vt.llunit_size);
         base::maybe_name_value(bcx.ccx(), scaled_ix, "scaled_ix");
 
-        let mut (bcx, base, len) =
+        let (bcx, base, len) =
             base_datum.get_vec_base_and_len(bcx, index_expr.span,
                                             index_expr.id, 0);
+        let mut bcx = bcx;
+        let mut base = base;
+        let mut len = len;
 
         if ty::type_is_str(base_ty) {
             // acccount for null terminator in the case of string
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 6263ffb318e..7672f3b615d 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -555,7 +555,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
                                decl,
                                item.id,
                                output_type,
-                               None,
                                Some(substs),
                                Some(item.span));
 
@@ -1183,7 +1182,6 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
                  no_self,
                  None,
                  id,
-                 None,
                  []);
         return llfndecl;
     }
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index 01849ac6e8f..11c02f165b6 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -127,7 +127,6 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
                        self_kind,
                        None,
                        mth.id,
-                       Some(impl_did),
                        []);
           }
           local_def(mth.id)
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index ebcc3d811eb..0b051662781 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -32,7 +32,6 @@ use util::ppaux::Repr;
 
 use middle::trans::type_::Type;
 
-use core::str;
 use core::vec;
 use syntax::ast_map::{path, path_mod, path_name};
 use syntax::ast_util;
@@ -68,8 +67,7 @@ pub fn trans_impl(ccx: @mut CrateContext,
                          path,
                          *method,
                          None,
-                         llfn,
-                         ast_util::local_def(id));
+                         llfn);
         }
     }
 }
@@ -90,8 +88,7 @@ pub fn trans_method(ccx: @mut CrateContext,
                     path: path,
                     method: &ast::method,
                     param_substs: Option<@param_substs>,
-                    llfn: ValueRef,
-                    impl_id: ast::def_id) {
+                    llfn: ValueRef) {
     // figure out how self is being passed
     let self_arg = match method.explicit_self.node {
       ast::sty_static => {
@@ -110,9 +107,7 @@ pub fn trans_method(ccx: @mut CrateContext,
         debug!("calling trans_fn with self_ty %s",
                self_ty.repr(ccx.tcx));
         match method.explicit_self.node {
-          ast::sty_value => {
-            impl_owned_self(self_ty)
-          }
+          ast::sty_value => impl_owned_self(self_ty),
           _ => {
             impl_self(self_ty)
           }
@@ -129,7 +124,6 @@ pub fn trans_method(ccx: @mut CrateContext,
              self_arg,
              param_substs,
              method.id,
-             Some(impl_id),
              []);
 }
 
@@ -141,10 +135,10 @@ pub fn trans_self_arg(bcx: block,
 
     // Compute the type of self.
     let self_ty = monomorphize_type(bcx, mentry.self_ty);
-
     let result = trans_arg_expr(bcx,
                                 self_ty,
                                 mentry.self_mode,
+                                mentry.explicit_self,
                                 base,
                                 &mut temp_cleanups,
                                 None,
@@ -175,21 +169,6 @@ pub fn trans_method_callee(bcx: block,
     // Replace method_self with method_static here.
     let mut origin = mentry.origin;
     match origin {
-        typeck::method_self(trait_id, method_index) => {
-            // Get the ID of the impl we're inside.
-            let impl_def_id = bcx.fcx.impl_id.get();
-
-            debug!("impl_def_id is %?", impl_def_id);
-
-            // Get the ID of the method we're calling.
-            let method_name =
-                ty::trait_method(tcx, trait_id, method_index).ident;
-            let method_id =
-                method_with_name_or_default(bcx.ccx(),
-                                            impl_def_id,
-                                            method_name);
-            origin = typeck::method_static(method_id);
-        }
         typeck::method_super(trait_id, method_index) => {
             // <self_ty> is the self type for this method call
             let self_ty = node_id_type(bcx, this.id);
@@ -214,6 +193,7 @@ pub fn trans_method_callee(bcx: block,
                                             impl_id,
                                             method_name));
         }
+        typeck::method_self(*) |
         typeck::method_static(*) | typeck::method_param(*) |
         typeck::method_trait(*) => {}
     }
@@ -231,6 +211,7 @@ pub fn trans_method_callee(bcx: block,
                     llself: val,
                     self_ty: node_id_type(bcx, this.id),
                     self_mode: mentry.self_mode,
+                    explicit_self: mentry.explicit_self
                 })
             }
         }
@@ -250,6 +231,21 @@ pub fn trans_method_callee(bcx: block,
                 None => fail!("trans_method_callee: missing param_substs")
             }
         }
+
+        typeck::method_self(trait_id, method_index) => {
+            match bcx.fcx.param_substs {
+                Some(@param_substs
+                     {self_vtable: Some(ref vtbl), _}) => {
+                    trans_monomorphized_callee(bcx, callee_id, this, mentry,
+                                               trait_id, method_index,
+                                               copy *vtbl)
+                }
+                _ => {
+                    fail!("trans_method_callee: missing self_vtable")
+                }
+            }
+        }
+
         typeck::method_trait(_, off, store) => {
             trans_trait_callee(bcx,
                                callee_id,
@@ -258,9 +254,9 @@ pub fn trans_method_callee(bcx: block,
                                store,
                                mentry.explicit_self)
         }
-        typeck::method_self(*) | typeck::method_super(*) => {
-            fail!("method_self or method_super should have been handled \
-                above")
+            typeck::method_super(*) => {
+            fail!("method_super should have been handled \
+                   above")
         }
     }
 }
@@ -292,15 +288,9 @@ pub fn trans_static_method_callee(bcx: block,
     //
     // So when we see a call to this function foo, we have to figure
     // out which impl the `Trait<T1...Tn>` bound on the type `self` was
-    // bound to.  Due to the fact that we use a flattened list of
-    // impls, one per bound, this means we have to total up the bounds
-    // found on the type parametesr T1...Tn to find the index of the
-    // one we are interested in.
-    let bound_index = {
-        let trait_def = ty::lookup_trait_def(bcx.tcx(), trait_id);
-        ty::count_traits_and_supertraits(
-            bcx.tcx(), *trait_def.generics.type_param_defs)
-    };
+    // bound to.
+    let bound_index = ty::lookup_trait_def(bcx.tcx(), trait_id).
+        generics.type_param_defs.len();
 
     let mname = if method_id.crate == ast::local_crate {
         match bcx.tcx().items.get_copy(&method_id.node) {
@@ -322,17 +312,17 @@ pub fn trans_static_method_callee(bcx: block,
     let vtbls = resolve_vtables_in_fn_ctxt(
         bcx.fcx, ccx.maps.vtable_map.get_copy(&callee_id));
 
-    match vtbls[bound_index] {
+    match vtbls[bound_index][0] {
         typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
             assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
             let mth_id = method_with_name_or_default(bcx.ccx(),
                                                      impl_did,
                                                      mname);
-            let callee_substs = combine_impl_and_methods_tps(
-                bcx, mth_id, impl_did, callee_id, *rcvr_substs);
-            let callee_origins = combine_impl_and_methods_origins(
-                bcx, mth_id, impl_did, callee_id, rcvr_origins);
+            let (callee_substs, callee_origins) =
+                combine_impl_and_methods_tps(
+                    bcx, mth_id, impl_did, callee_id,
+                    *rcvr_substs, rcvr_origins);
 
             let FnData {llfn: lval} =
                 trans_fn_ref_with_vtables(bcx,
@@ -428,10 +418,10 @@ pub fn trans_monomorphized_callee(bcx: block,
 
           // create a concatenated set of substitutions which includes
           // those from the impl and those from the method:
-          let callee_substs = combine_impl_and_methods_tps(
-              bcx, mth_id, impl_did, callee_id, *rcvr_substs);
-          let callee_origins = combine_impl_and_methods_origins(
-              bcx, mth_id, impl_did, callee_id, rcvr_origins);
+          let (callee_substs, callee_origins) =
+              combine_impl_and_methods_tps(
+                  bcx, mth_id, impl_did, callee_id,
+                  *rcvr_substs, rcvr_origins);
 
           // translate the function
           let callee = trans_fn_ref_with_vtables(bcx,
@@ -453,12 +443,16 @@ pub fn trans_monomorphized_callee(bcx: block,
                   llself: llself_val,
                   self_ty: node_id_type(bcx, base.id),
                   self_mode: mentry.self_mode,
+                  explicit_self: mentry.explicit_self
               })
           }
       }
       typeck::vtable_param(*) => {
           fail!("vtable_param left in monomorphized function's vtable substs");
       }
+      typeck::vtable_self(*) => {
+          fail!("vtable_self left in monomorphized function's vtable substs");
+      }
     };
 
 }
@@ -467,8 +461,9 @@ pub fn combine_impl_and_methods_tps(bcx: block,
                                     mth_did: ast::def_id,
                                     impl_did: ast::def_id,
                                     callee_id: ast::node_id,
-                                    rcvr_substs: &[ty::t])
-                                    -> ~[ty::t] {
+                                    rcvr_substs: &[ty::t],
+                                    rcvr_origins: typeck::vtable_res)
+                                    -> (~[ty::t], typeck::vtable_res) {
     /*!
     *
     * Creates a concatenated set of substitutions which includes
@@ -492,58 +487,23 @@ pub fn combine_impl_and_methods_tps(bcx: block,
     debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t)));
     let ty_substs
         = vec::append(rcvr_substs.to_owned(),
-                      vec::tailn(node_substs,
-                                 node_substs.len() - n_m_tps));
+                      node_substs.tailn(node_substs.len() - n_m_tps));
     debug!("n_m_tps=%?", n_m_tps);
     debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t)));
     debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t)));
 
-    return ty_substs;
-}
 
-pub fn combine_impl_and_methods_origins(bcx: block,
-                                        mth_did: ast::def_id,
-                                        impl_did: ast::def_id,
-                                        callee_id: ast::node_id,
-                                        rcvr_origins: typeck::vtable_res)
-                                     -> typeck::vtable_res {
-    /*!
-     *
-     * Similar to `combine_impl_and_methods_tps`, but for vtables.
-     * This is much messier because of the flattened layout we are
-     * currently using (for some reason that I fail to understand).
-     * The proper fix is described in #3446.
-     */
-
-
-    // Find the bounds for the method, which are the tail of the
-    // bounds found in the item type, as the item type combines the
-    // rcvr + method bounds.
-    let ccx = bcx.ccx();
-    let tcx = bcx.tcx();
-    let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did);
-    let ty::ty_param_bounds_and_ty {
-        generics: r_m_generics,
-        _
-    } = ty::lookup_item_type(tcx, mth_did);
-    let n_r_m_tps = r_m_generics.type_param_defs.len(); // rcvr + method tps
-    let m_type_param_defs =
-        vec::slice(*r_m_generics.type_param_defs, n_r_m_tps - n_m_tps, n_r_m_tps);
-
-    // Flatten out to find the number of vtables the method expects.
-    let m_vtables = ty::count_traits_and_supertraits(tcx, m_type_param_defs);
-
-    // Find the vtables we computed at type check time and monomorphize them
+    // Now, do the same work for the vtables.  The vtables might not
+    // exist, in which case we need to make them.
     let r_m_origins = match node_vtables(bcx, callee_id) {
         Some(vt) => vt,
-        None => @~[]
+        None => @vec::from_elem(node_substs.len(), @~[])
     };
+    let vtables
+        = @vec::append(rcvr_origins.to_owned(),
+                       r_m_origins.tailn(r_m_origins.len() - n_m_tps));
 
-    // Extract those that belong to method:
-    let m_origins = vec::tailn(*r_m_origins, r_m_origins.len() - m_vtables);
-
-    // Combine rcvr + method to find the final result:
-    @vec::append(/*bad*/copy *rcvr_origins, m_origins)
+    return (ty_substs, vtables);
 }
 
 
@@ -693,6 +653,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
             llself: llself,
             self_ty: ty::mk_opaque_box(bcx.tcx()),
             self_mode: self_mode,
+            explicit_self: explicit_self
             /* XXX: Some(llbox) */
         })
     };
@@ -755,8 +716,8 @@ pub fn make_vtable(ccx: &mut CrateContext,
         }
 
         let tbl = C_struct(components);
-        let vtable = ccx.sess.str_of((ccx.names)("vtable"));
-        let vt_gvar = do str::as_c_str(vtable) |buf| {
+        let vtable = ccx.sess.str_of(gensym_name("vtable"));
+        let vt_gvar = do vtable.as_c_str |buf| {
             llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(vt_gvar, tbl);
@@ -840,7 +801,7 @@ pub fn trans_trait_cast(bcx: block,
     bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
 
     // Store the vtable into the pair or triple.
-    let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0];
+    let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0][0];
     let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig);
     let vtable = get_vtable(bcx, v_ty, orig);
     Store(bcx, vtable, PointerCast(bcx,
diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs
index c2a25d80998..64d6bbec87c 100644
--- a/src/librustc/middle/trans/mod.rs
+++ b/src/librustc/middle/trans/mod.rs
@@ -37,7 +37,6 @@ pub mod foreign;
 pub mod reflect;
 pub mod debuginfo;
 pub mod type_use;
-pub mod reachable;
 pub mod machine;
 pub mod adt;
 pub mod asm;
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 1ffe26e3aff..92d8192aee6 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -43,6 +43,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
                       fn_id: ast::def_id,
                       real_substs: &ty::substs,
                       vtables: Option<typeck::vtable_res>,
+                      self_vtable: Option<typeck::vtable_origin>,
                       impl_did_opt: Option<ast::def_id>,
                       ref_id: Option<ast::node_id>)
     -> (ValueRef, bool)
@@ -161,9 +162,11 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
     }
     ccx.monomorphizing.insert(fn_id, depth + 1);
 
-    let pt = vec::append(/*bad*/copy *pt,
-                         [path_name((ccx.names)(ccx.sess.str_of(name)))]);
+    let elt = path_name(gensym_name(ccx.sess.str_of(name)));
+    let mut pt = /* bad */copy (*pt);
+    pt.push(elt);
     let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty);
+    debug!("monomorphize_fn mangled to %s", s);
 
     let mk_lldecl = || {
         let lldecl = decl_internal_cdecl_fn(ccx.llmod, /*bad*/copy s, llfty);
@@ -174,8 +177,8 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
     let psubsts = Some(@param_substs {
         tys: substs,
         vtables: vtables,
-        type_param_defs: tpt.generics.type_param_defs,
-        self_ty: real_substs.self_ty
+        self_ty: real_substs.self_ty,
+        self_vtable: self_vtable
     });
 
     let lldecl = match map_node {
@@ -193,7 +196,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
                  no_self,
                  psubsts,
                  fn_id.node,
-                 None,
                  []);
         d
       }
@@ -221,27 +223,17 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
         }
         d
       }
-      ast_map::node_method(mth, supplied_impl_did, _) => {
+      ast_map::node_method(mth, _, _) => {
         // XXX: What should the self type be here?
         let d = mk_lldecl();
         set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
-
-        // Override the impl def ID if necessary.
-        let impl_did;
-        match impl_did_opt {
-            None => impl_did = supplied_impl_did,
-            Some(override_impl_did) => impl_did = override_impl_did
-        }
-
-        meth::trans_method(ccx, pt, mth, psubsts, d, impl_did);
+        meth::trans_method(ccx, pt, mth, psubsts, d);
         d
       }
       ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
         let d = mk_lldecl();
         set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
-        debug!("monomorphic_fn impl_did_opt is %?", impl_did_opt);
-        meth::trans_method(ccx, /*bad*/copy *pt, mth, psubsts, d,
-                           impl_did_opt.get());
+        meth::trans_method(ccx, /*bad*/copy *pt, mth, psubsts, d);
         d
       }
       ast_map::node_struct_ctor(struct_def, _, _) => {
@@ -336,14 +328,10 @@ pub fn make_mono_id(ccx: @mut CrateContext,
                     param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
     let precise_param_ids = match vtables {
       Some(vts) => {
-        let item_ty = ty::lookup_item_type(ccx.tcx, item);
-        let mut i = 0;
-        vec::map_zip(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| {
-            let mut v = ~[];
-            for type_param_def.bounds.trait_bounds.iter().advance |_bound| {
-                v.push(meth::vtable_id(ccx, &vts[i]));
-                i += 1;
-            }
+        debug!("make_mono_id vtables=%s substs=%s",
+               vts.repr(ccx.tcx), substs.repr(ccx.tcx));
+        vec::map_zip(*vts, substs, |vtable, subst| {
+            let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
             (*subst, if !v.is_empty() { Some(@v) } else { None })
         })
       }
diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs
deleted file mode 100644
index e950c24c49e..00000000000
--- a/src/librustc/middle/trans/reachable.rs
+++ /dev/null
@@ -1,246 +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.
-
-// Finds items that are externally reachable, to determine which items
-// need to have their metadata (and possibly their AST) serialized.
-// All items that can be referred to through an exported name are
-// reachable, and when a reachable thing is inline or generic, it
-// makes all other generics or inline functions that it references
-// reachable as well.
-
-use core::prelude::*;
-
-use middle::resolve;
-use middle::ty;
-use middle::typeck;
-
-use core::hashmap::HashSet;
-use syntax::ast;
-use syntax::ast::*;
-use syntax::ast_util::def_id_of_def;
-use syntax::attr;
-use syntax::codemap;
-use syntax::print::pprust::expr_to_str;
-use syntax::{visit, ast_map};
-
-pub type map = @HashSet<node_id>;
-
-struct ctx<'self> {
-    exp_map2: resolve::ExportMap2,
-    tcx: ty::ctxt,
-    method_map: typeck::method_map,
-    rmap: &'self mut HashSet<node_id>,
-}
-
-pub fn find_reachable(crate_mod: &_mod, exp_map2: resolve::ExportMap2,
-                      tcx: ty::ctxt, method_map: typeck::method_map) -> map {
-    let mut rmap = HashSet::new();
-    {
-        let cx = @mut ctx {
-            exp_map2: exp_map2,
-            tcx: tcx,
-            method_map: method_map,
-            rmap: &mut rmap
-        };
-        traverse_public_mod(cx, ast::crate_node_id, crate_mod);
-        traverse_all_resources_and_impls(cx, crate_mod);
-    }
-    return @rmap;
-}
-
-fn traverse_exports(cx: @mut ctx, mod_id: node_id) -> bool {
-    let mut found_export = false;
-    match cx.exp_map2.find(&mod_id) {
-      Some(ref exp2s) => {
-        for (*exp2s).iter().advance |e2| {
-            found_export = true;
-            traverse_def_id(cx, e2.def_id)
-        };
-      }
-      None => ()
-    }
-    return found_export;
-}
-
-fn traverse_def_id(cx: @mut ctx, did: def_id) {
-    if did.crate != local_crate { return; }
-    match cx.tcx.items.find(&did.node) {
-        None => (), // This can happen for self, for example
-        Some(&ast_map::node_item(item, _)) => traverse_public_item(cx, item),
-        Some(&ast_map::node_method(_, impl_id, _)) => traverse_def_id(cx, impl_id),
-        Some(&ast_map::node_foreign_item(item, _, _, _)) => {
-            let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut
-            cx.rmap.insert(item.id);
-        }
-        Some(&ast_map::node_variant(ref v, _, _)) => {
-            let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut
-            cx.rmap.insert(v.node.id);
-        }
-        _ => ()
-    }
-}
-
-fn traverse_public_mod(cx: @mut ctx, mod_id: node_id, m: &_mod) {
-    if !traverse_exports(cx, mod_id) {
-        // No exports, so every local item is exported
-        for m.items.iter().advance |item| {
-            traverse_public_item(cx, *item);
-        }
-    }
-}
-
-fn traverse_public_item(cx: @mut ctx, item: @item) {
-    {
-        // FIXME #6021: naming rmap shouldn't be necessary
-        let cx = &mut *cx;
-        let rmap: &mut HashSet<node_id> = cx.rmap;
-        if rmap.contains(&item.id) { return; }
-        rmap.insert(item.id);
-    }
-
-    match item.node {
-      item_mod(ref m) => traverse_public_mod(cx, item.id, m),
-      item_foreign_mod(ref nm) => {
-          if !traverse_exports(cx, item.id) {
-              for nm.items.iter().advance |item| {
-                  let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut
-                  cx.rmap.insert(item.id);
-              }
-          }
-      }
-      item_fn(_, _, _, ref generics, ref blk) => {
-        if generics.ty_params.len() > 0u ||
-           attr::find_inline_attr(item.attrs) != attr::ia_none {
-            traverse_inline_body(cx, blk);
-        }
-      }
-      item_impl(ref generics, _, _, ref ms) => {
-        for ms.iter().advance |m| {
-            if generics.ty_params.len() > 0u ||
-                m.generics.ty_params.len() > 0u ||
-                attr::find_inline_attr(m.attrs) != attr::ia_none
-            {
-                {
-                    let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut
-                    cx.rmap.insert(m.id);
-                }
-                traverse_inline_body(cx, &m.body);
-            }
-        }
-      }
-      item_struct(ref struct_def, _) => {
-        for struct_def.ctor_id.iter().advance |&ctor_id| {
-            let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut
-            cx.rmap.insert(ctor_id);
-        }
-      }
-      item_ty(t, _) => {
-        traverse_ty(t, (cx,
-                        visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty,
-                                                      ..*visit::default_visitor()})))
-      }
-      item_static(*) |
-      item_enum(*) | item_trait(*) => (),
-      item_mac(*) => fail!("item macros unimplemented")
-    }
-}
-
-fn traverse_ty<'a>(ty: @Ty, (cx, v): (@mut ctx<'a>, visit::vt<@mut ctx<'a>>)) {
-    {
-        let cx = &mut *cx; // FIXME(#6269) reborrow @mut to &mut
-        if cx.rmap.contains(&ty.id) { return; }
-        cx.rmap.insert(ty.id);
-    }
-
-    match ty.node {
-      ty_path(p, _bounds, p_id) => {
-        match cx.tcx.def_map.find(&p_id) {
-          // Kind of a hack to check this here, but I'm not sure what else
-          // to do
-          Some(&def_prim_ty(_)) => { /* do nothing */ }
-          Some(&d) => traverse_def_id(cx, def_id_of_def(d)),
-          None    => { /* do nothing -- but should we fail here? */ }
-        }
-        for p.types.iter().advance |t| {
-            (v.visit_ty)(*t, (cx, v));
-        }
-      }
-      _ => visit::visit_ty(ty, (cx, v))
-    }
-}
-
-fn traverse_inline_body(cx: @mut ctx, body: &blk) {
-    fn traverse_expr<'a>(e: @expr, (cx, v): (@mut ctx<'a>,
-                                             visit::vt<@mut ctx<'a>>)) {
-        match e.node {
-          expr_path(_) => {
-            match cx.tcx.def_map.find(&e.id) {
-                Some(&d) => {
-                    traverse_def_id(cx, def_id_of_def(d));
-                }
-                None => cx.tcx.sess.span_bug(
-                    e.span,
-                    fmt!("Unbound node id %? while traversing %s",
-                         e.id,
-                         expr_to_str(e, cx.tcx.sess.intr())))
-            }
-          }
-          expr_method_call(*) => {
-            match cx.method_map.find(&e.id) {
-              Some(&typeck::method_map_entry {
-                  origin: typeck::method_static(did),
-                  _
-                }) => {
-                traverse_def_id(cx, did);
-              }
-              Some(_) => {}
-              None => {
-                cx.tcx.sess.span_bug(e.span, "expr_method_call not in \
-                                              method map");
-              }
-            }
-          }
-          _ => ()
-        }
-        visit::visit_expr(e, (cx, v));
-    }
-    // Don't ignore nested items: for example if a generic fn contains a
-    // generic impl (as in deque::create), we need to monomorphize the
-    // impl as well
-    fn traverse_item(i: @item, (cx, _v): (@mut ctx, visit::vt<@mut ctx>)) {
-      traverse_public_item(cx, i);
-    }
-    visit::visit_block(body, (cx, visit::mk_vt(@visit::Visitor {
-        visit_expr: traverse_expr,
-        visit_item: traverse_item,
-         ..*visit::default_visitor()
-    })));
-}
-
-fn traverse_all_resources_and_impls(cx: @mut ctx, crate_mod: &_mod) {
-    visit::visit_mod(
-        crate_mod,
-        codemap::dummy_sp(),
-        0,
-        (cx,
-        visit::mk_vt(@visit::Visitor {
-            visit_expr: |_e, (_cx, _v)| { },
-            visit_item: |i, (cx, v)| {
-                visit::visit_item(i, (cx, v));
-                match i.node {
-                    item_impl(*) => {
-                        traverse_public_item(cx, i);
-                    }
-                    _ => ()
-                }
-            },
-            ..*visit::default_visitor()
-        })));
-}
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index d34befddad5..b8ee1eee26e 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -52,7 +52,7 @@ use syntax;
 
 // Data types
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct field {
     ident: ast::ident,
     mt: mt
@@ -96,13 +96,13 @@ impl Method {
     }
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct mt {
     ty: t,
     mutbl: ast::mutability,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable, IterBytes)]
 pub enum vstore {
     vstore_fixed(uint),
     vstore_uniq,
@@ -133,7 +133,7 @@ pub struct field_ty {
 
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct creader_cache_key {
     cnum: int,
     pos: uint,
@@ -142,14 +142,6 @@ pub struct creader_cache_key {
 
 type creader_cache = @mut HashMap<creader_cache_key, t>;
 
-impl to_bytes::IterBytes for creader_cache_key {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.cnum.iter_bytes(lsb0, f) &&
-        self.pos.iter_bytes(lsb0, f) &&
-        self.len.iter_bytes(lsb0, f)
-    }
-}
-
 struct intern_key {
     sty: *sty,
 }
@@ -168,6 +160,8 @@ impl cmp::Eq for intern_key {
     }
 }
 
+// NB: Do not replace this with #[deriving(IterBytes)], as above. (Figured
+// this out the hard way.)
 impl to_bytes::IterBytes for intern_key {
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
         unsafe {
@@ -372,14 +366,14 @@ pub fn type_has_regions(t: t) -> bool {
 }
 pub fn type_id(t: t) -> uint { get(t).id }
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct BareFnTy {
     purity: ast::purity,
     abis: AbiSet,
     sig: FnSig
 }
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct ClosureTy {
     purity: ast::purity,
     sigil: ast::Sigil,
@@ -396,32 +390,13 @@ pub struct ClosureTy {
  * - `lifetimes` is the list of region names bound in this fn.
  * - `inputs` is the list of arguments and their modes.
  * - `output` is the return type. */
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct FnSig {
     bound_lifetime_names: OptVec<ast::ident>,
     inputs: ~[t],
     output: t
 }
 
-impl to_bytes::IterBytes for BareFnTy {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.purity.iter_bytes(lsb0, f) &&
-        self.abis.iter_bytes(lsb0, f) &&
-        self.sig.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for ClosureTy {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.purity.iter_bytes(lsb0, f) &&
-        self.sigil.iter_bytes(lsb0, f) &&
-        self.onceness.iter_bytes(lsb0, f) &&
-        self.region.iter_bytes(lsb0, f) &&
-        self.sig.iter_bytes(lsb0, f) &&
-        self.bounds.iter_bytes(lsb0, f)
-    }
-}
-
 #[deriving(Eq, IterBytes)]
 pub struct param_ty {
     idx: uint,
@@ -526,7 +501,7 @@ type opt_region = Option<Region>;
  * - `self_ty` is the type to which `self` should be remapped, if any.  The
  *   `self` type is rather funny in that it can only appear on traits and is
  *   always substituted away to the implementing type for a trait. */
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct substs {
     self_r: opt_region,
     self_ty: Option<ty::t>,
@@ -582,7 +557,7 @@ mod primitives {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub enum sty {
     ty_nil,
     ty_bot,
@@ -686,8 +661,8 @@ pub type BuiltinBounds = EnumSet<BuiltinBound>;
 pub enum BuiltinBound {
     BoundCopy,
     BoundStatic,
-    BoundOwned,
-    BoundConst,
+    BoundSend,
+    BoundFreeze,
     BoundSized,
 }
 
@@ -699,8 +674,8 @@ pub fn AllBuiltinBounds() -> BuiltinBounds {
     let mut set = EnumSet::empty();
     set.add(BoundCopy);
     set.add(BoundStatic);
-    set.add(BoundOwned);
-    set.add(BoundConst);
+    set.add(BoundSend);
+    set.add(BoundFreeze);
     set.add(BoundSized);
     set
 }
@@ -714,62 +689,33 @@ impl CLike for BuiltinBound {
     }
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct TyVid(uint);
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct IntVid(uint);
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct FloatVid(uint);
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable, IterBytes)]
 pub struct RegionVid {
     id: uint
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub enum InferTy {
     TyVar(TyVid),
     IntVar(IntVid),
     FloatVar(FloatVid)
 }
 
-impl to_bytes::IterBytes for InferTy {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            TyVar(ref tv) => {
-                0u8.iter_bytes(lsb0, f) && tv.iter_bytes(lsb0, f)
-            }
-            IntVar(ref iv) => {
-                1u8.iter_bytes(lsb0, f) && iv.iter_bytes(lsb0, f)
-            }
-            FloatVar(ref fv) => {
-                2u8.iter_bytes(lsb0, f) && fv.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
-#[deriving(Encodable, Decodable)]
+#[deriving(Encodable, Decodable, IterBytes)]
 pub enum InferRegion {
     ReVar(RegionVid),
     ReSkolemized(uint, bound_region)
 }
 
-impl to_bytes::IterBytes for InferRegion {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ReVar(ref rv) => {
-                0u8.iter_bytes(lsb0, f) && rv.iter_bytes(lsb0, f)
-            }
-            ReSkolemized(ref v, _) => {
-                1u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 impl cmp::Eq for InferRegion {
     fn eq(&self, other: &InferRegion) -> bool {
         match ((*self), *other) {
@@ -849,30 +795,6 @@ impl ToStr for IntVarValue {
     }
 }
 
-impl to_bytes::IterBytes for TyVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for IntVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for FloatVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for RegionVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
 pub struct TypeParameterDef {
     def_id: ast::def_id,
     bounds: @ParamBounds
@@ -1319,15 +1241,15 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
       }
       ty_enum(_, ref substs) | ty_struct(_, ref substs) |
       ty_trait(_, ref substs, _, _, _) => {
-        for (*substs).tps.iter().advance |subty| { maybe_walk_ty(*subty, f); }
+        for (*substs).tps.iter().advance |subty| { maybe_walk_ty(*subty, |x| f(x)); }
       }
-      ty_tup(ref ts) => { for ts.iter().advance |tt| { maybe_walk_ty(*tt, f); } }
+      ty_tup(ref ts) => { for ts.iter().advance |tt| { maybe_walk_ty(*tt, |x| f(x)); } }
       ty_bare_fn(ref ft) => {
-        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, f); }
+        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, |x| f(x)); }
         maybe_walk_ty(ft.sig.output, f);
       }
       ty_closure(ref ft) => {
-        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, f); }
+        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, |x| f(x)); }
         maybe_walk_ty(ft.sig.output, f);
       }
     }
@@ -1409,7 +1331,7 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
 
 // Folds types from the bottom up.
 pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
-    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
+    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), |t| fldop(t)));
     fldop(mk_t(cx, sty))
 }
 
@@ -1423,8 +1345,8 @@ pub fn walk_regions_and_ty(
         fold_regions_and_ty(
             cx, ty,
             |r| { walkr(r); r },
-            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
-            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
+            |t| { walk_regions_and_ty(cx, t, |r| walkr(r), |t| walkt(t)); t },
+            |t| { walk_regions_and_ty(cx, t, |r| walkr(r), |t| walkt(t)); t });
     }
 }
 
@@ -1504,8 +1426,8 @@ pub fn fold_regions(
         fold_regions_and_ty(
             cx, ty,
             |r| fldr(r, in_fn),
-            |t| do_fold(cx, t, true, fldr),
-            |t| do_fold(cx, t, in_fn, fldr))
+            |t| do_fold(cx, t, true,  |r,b| fldr(r,b)),
+            |t| do_fold(cx, t, in_fn, |r,b| fldr(r,b)))
     }
     do_fold(cx, ty, false, fldr)
 }
@@ -1838,8 +1760,8 @@ impl TypeContents {
         match bb {
             BoundCopy => self.is_copy(cx),
             BoundStatic => self.is_static(cx),
-            BoundConst => self.is_const(cx),
-            BoundOwned => self.is_owned(cx),
+            BoundFreeze => self.is_freezable(cx),
+            BoundSend => self.is_sendable(cx),
             BoundSized => self.is_sized(cx),
         }
     }
@@ -1865,23 +1787,23 @@ impl TypeContents {
         TC_BORROWED_POINTER
     }
 
-    pub fn is_owned(&self, cx: ctxt) -> bool {
-        !self.intersects(TypeContents::nonowned(cx))
+    pub fn is_sendable(&self, cx: ctxt) -> bool {
+        !self.intersects(TypeContents::nonsendable(cx))
     }
 
-    pub fn nonowned(_cx: ctxt) -> TypeContents {
-        TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED
+    pub fn nonsendable(_cx: ctxt) -> TypeContents {
+        TC_MANAGED + TC_BORROWED_POINTER + TC_NON_SENDABLE
     }
 
     pub fn contains_managed(&self) -> bool {
         self.intersects(TC_MANAGED)
     }
 
-    pub fn is_const(&self, cx: ctxt) -> bool {
-        !self.intersects(TypeContents::nonconst(cx))
+    pub fn is_freezable(&self, cx: ctxt) -> bool {
+        !self.intersects(TypeContents::nonfreezable(cx))
     }
 
-    pub fn nonconst(_cx: ctxt) -> TypeContents {
+    pub fn nonfreezable(_cx: ctxt) -> TypeContents {
         TC_MUTABLE
     }
 
@@ -1906,14 +1828,16 @@ impl TypeContents {
             // Currently all noncopyable existentials are 2nd-class types
             // behind owned pointers. With dynamically-sized types, remove
             // this assertion.
-            assert!(self.intersects(TC_OWNED_POINTER));
+            assert!(self.intersects(TC_OWNED_POINTER) ||
+                    // (...or stack closures without a copy bound.)
+                    self.intersects(TC_BORROWED_POINTER));
         }
-        let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
+        let tc = TC_MANAGED + TC_DTOR + TypeContents::sendable(cx);
         self.intersects(tc)
     }
 
-    pub fn owned(_cx: ctxt) -> TypeContents {
-        //! Any kind of owned contents.
+    pub fn sendable(_cx: ctxt) -> TypeContents {
+        //! Any kind of sendable contents.
         TC_OWNED_POINTER + TC_OWNED_VEC
     }
 }
@@ -1969,8 +1893,8 @@ static TC_ONCE_CLOSURE: TypeContents =     TypeContents{bits: 0b0001_0000_0000};
 /// An enum with no variants.
 static TC_EMPTY_ENUM: TypeContents =       TypeContents{bits: 0b0010_0000_0000};
 
-/// Contains a type marked with `#[non_owned]`
-static TC_NON_OWNED: TypeContents =        TypeContents{bits: 0b0100_0000_0000};
+/// Contains a type marked with `#[no_send]`
+static TC_NON_SENDABLE: TypeContents =     TypeContents{bits: 0b0100_0000_0000};
 
 /// Is a bare vector, str, function, trait, etc (only relevant at top level).
 static TC_DYNAMIC_SIZE: TypeContents =     TypeContents{bits: 0b1000_0000_0000};
@@ -1986,12 +1910,12 @@ pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
     type_contents(cx, t).is_static(cx)
 }
 
-pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
-    type_contents(cx, t).is_owned(cx)
+pub fn type_is_sendable(cx: ctxt, t: ty::t) -> bool {
+    type_contents(cx, t).is_sendable(cx)
 }
 
-pub fn type_is_const(cx: ctxt, t: ty::t) -> bool {
-    type_contents(cx, t).is_const(cx)
+pub fn type_is_freezable(cx: ctxt, t: ty::t) -> bool {
+    type_contents(cx, t).is_freezable(cx)
 }
 
 pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
@@ -2045,7 +1969,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         let _i = indenter();
 
         let result = match get(ty).sty {
-            // Scalar and unique types are sendable, constant, and owned
+            // Scalar and unique types are sendable, freezable, and durable
             ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
             ty_bare_fn(_) | ty_ptr(_) => {
                 TC_NONE
@@ -2060,7 +1984,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             }
 
             ty_box(mt) => {
-                TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
+                TC_MANAGED +
+                    statically_sized(nonsendable(tc_mt(cx, mt, cache)))
             }
 
             ty_trait(_, _, store, mutbl, bounds) => {
@@ -2069,7 +1994,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
 
             ty_rptr(r, mt) => {
                 borrowed_contents(r, mt.mutbl) +
-                    statically_sized(nonowned(tc_mt(cx, mt, cache)))
+                    statically_sized(nonsendable(tc_mt(cx, mt, cache)))
             }
 
             ty_uniq(mt) => {
@@ -2081,12 +2006,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             }
 
             ty_evec(mt, vstore_box) => {
-                TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache)))
+                TC_MANAGED +
+                    statically_sized(nonsendable(tc_mt(cx, mt, cache)))
             }
 
             ty_evec(mt, vstore_slice(r)) => {
                 borrowed_contents(r, mt.mutbl) +
-                    statically_sized(nonowned(tc_mt(cx, mt, cache)))
+                    statically_sized(nonsendable(tc_mt(cx, mt, cache)))
             }
 
             ty_evec(mt, vstore_fixed(_)) => {
@@ -2118,7 +2044,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                     TC_NONE,
                     |tc, f| tc + tc_mt(cx, f.mt, cache));
                 if ty::has_dtor(cx, did) {
-                    res += TC_DTOR;
+                    res = res + TC_DTOR;
                 }
                 apply_tc_attr(cx, did, res)
             }
@@ -2202,11 +2128,11 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
     }
 
     fn apply_tc_attr(cx: ctxt, did: def_id, mut tc: TypeContents) -> TypeContents {
-        if has_attr(cx, did, "mutable") {
-            tc += TC_MUTABLE;
+        if has_attr(cx, did, "no_freeze") {
+            tc = tc + TC_MUTABLE;
         }
-        if has_attr(cx, did, "non_owned") {
-            tc += TC_NON_OWNED;
+        if has_attr(cx, did, "no_send") {
+            tc = tc + TC_NON_SENDABLE;
         }
         tc
     }
@@ -2227,7 +2153,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         mc + rc
     }
 
-    fn nonowned(pointee: TypeContents) -> TypeContents {
+    fn nonsendable(pointee: TypeContents) -> TypeContents {
         /*!
          *
          * Given a non-owning pointer to some type `T` with
@@ -2270,7 +2196,14 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             ast::Once => TC_ONCE_CLOSURE,
             ast::Many => TC_NONE
         };
-        st + rt + ot
+        // Prevent noncopyable types captured in the environment from being copied.
+        let ct = if cty.bounds.contains_elem(BoundCopy) ||
+                    cty.sigil == ast::ManagedSigil {
+            TC_NONE
+        } else {
+            TC_NONCOPY_TRAIT
+        };
+        st + rt + ot + ct
     }
 
     fn trait_contents(store: TraitStore, mutbl: ast::mutability,
@@ -2291,11 +2224,11 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 BoundCopy if store == UniqTraitStore
                             => TC_NONCOPY_TRAIT,
                 BoundCopy   => TC_NONE, // @Trait/&Trait are copyable either way
-                BoundStatic if bounds.contains_elem(BoundOwned)
-                            => TC_NONE, // Owned bound implies static bound.
+                BoundStatic if bounds.contains_elem(BoundSend)
+                            => TC_NONE, // Send bound implies static bound.
                 BoundStatic => TC_BORROWED_POINTER, // Useful for "@Trait:'static"
-                BoundOwned  => TC_NON_OWNED,
-                BoundConst  => TC_MUTABLE,
+                BoundSend   => TC_NON_SENDABLE,
+                BoundFreeze => TC_MUTABLE,
                 BoundSized  => TC_NONE, // don't care if interior is sized
             };
         }
@@ -2314,8 +2247,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             tc = tc - match bound {
                 BoundCopy => TypeContents::noncopyable(cx),
                 BoundStatic => TypeContents::nonstatic(cx),
-                BoundOwned => TypeContents::nonowned(cx),
-                BoundConst => TypeContents::nonconst(cx),
+                BoundSend => TypeContents::nonsendable(cx),
+                BoundFreeze => TypeContents::nonfreezable(cx),
                 // The dynamic-size bit can be removed at pointer-level, etc.
                 BoundSized => TypeContents::dynamically_sized(cx),
             };
@@ -2450,7 +2383,7 @@ pub fn type_structurally_contains(cx: ctxt,
         for (*enum_variants(cx, did)).iter().advance |variant| {
             for variant.args.iter().advance |aty| {
                 let sty = subst(cx, substs, *aty);
-                if type_structurally_contains(cx, sty, test) { return true; }
+                if type_structurally_contains(cx, sty, |x| test(x)) { return true; }
             }
         }
         return false;
@@ -2459,14 +2392,14 @@ pub fn type_structurally_contains(cx: ctxt,
         let r = lookup_struct_fields(cx, did);
         for r.iter().advance |field| {
             let ft = lookup_field_type(cx, did, field.id, substs);
-            if type_structurally_contains(cx, ft, test) { return true; }
+            if type_structurally_contains(cx, ft, |x| test(x)) { return true; }
         }
         return false;
       }
 
       ty_tup(ref ts) => {
         for ts.iter().advance |tt| {
-            if type_structurally_contains(cx, *tt, test) { return true; }
+            if type_structurally_contains(cx, *tt, |x| test(x)) { return true; }
         }
         return false;
       }
@@ -2742,123 +2675,6 @@ impl cmp::TotalEq for bound_region {
     }
 }
 
-impl to_bytes::IterBytes for vstore {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            vstore_fixed(ref u) => {
-                0u8.iter_bytes(lsb0, f) && u.iter_bytes(lsb0, f)
-            }
-            vstore_uniq => 1u8.iter_bytes(lsb0, f),
-            vstore_box => 2u8.iter_bytes(lsb0, f),
-
-            vstore_slice(ref r) => {
-                3u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
-impl to_bytes::IterBytes for substs {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.self_r.iter_bytes(lsb0, f) &&
-        self.self_ty.iter_bytes(lsb0, f) &&
-        self.tps.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for mt {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.ty.iter_bytes(lsb0, f) && self.mutbl.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for field {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.ident.iter_bytes(lsb0, f) && self.mt.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for FnSig {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.inputs.iter_bytes(lsb0, f) && self.output.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for sty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ty_nil => 0u8.iter_bytes(lsb0, f),
-            ty_bool => 1u8.iter_bytes(lsb0, f),
-
-            ty_int(ref t) => 2u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
-
-            ty_uint(ref t) => 3u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
-
-            ty_float(ref t) => 4u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
-
-            ty_estr(ref v) => 5u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f),
-
-            ty_enum(ref did, ref substs) => {
-                6u8.iter_bytes(lsb0, f) &&
-                did.iter_bytes(lsb0, f) &&
-                substs.iter_bytes(lsb0, f)
-            }
-
-            ty_box(ref mt) => 7u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_evec(ref mt, ref v) => {
-                8u8.iter_bytes(lsb0, f) &&
-                mt.iter_bytes(lsb0, f) &&
-                v.iter_bytes(lsb0, f)
-            }
-
-            ty_unboxed_vec(ref mt) => 9u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_tup(ref ts) => 10u8.iter_bytes(lsb0, f) && ts.iter_bytes(lsb0, f),
-
-            ty_bare_fn(ref ft) => 12u8.iter_bytes(lsb0, f) && ft.iter_bytes(lsb0, f),
-
-            ty_self(ref did) => 13u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f),
-
-            ty_infer(ref v) => 14u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f),
-
-            ty_param(ref p) => 15u8.iter_bytes(lsb0, f) && p.iter_bytes(lsb0, f),
-
-            ty_type => 16u8.iter_bytes(lsb0, f),
-            ty_bot => 17u8.iter_bytes(lsb0, f),
-
-            ty_ptr(ref mt) => 18u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_uniq(ref mt) => 19u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_trait(ref did, ref substs, ref v, ref mutbl, bounds) => {
-                20u8.iter_bytes(lsb0, f) &&
-                did.iter_bytes(lsb0, f) &&
-                substs.iter_bytes(lsb0, f) &&
-                v.iter_bytes(lsb0, f) &&
-                mutbl.iter_bytes(lsb0, f) &&
-                bounds.iter_bytes(lsb0, f)
-            }
-
-            ty_opaque_closure_ptr(ref ck) => 21u8.iter_bytes(lsb0, f) && ck.iter_bytes(lsb0, f),
-
-            ty_opaque_box => 22u8.iter_bytes(lsb0, f),
-
-            ty_struct(ref did, ref substs) => {
-                23u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f) && substs.iter_bytes(lsb0, f)
-            }
-
-            ty_rptr(ref r, ref mt) => {
-                24u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f)
-            }
-
-            ty_err => 25u8.iter_bytes(lsb0, f),
-
-            ty_closure(ref ct) => 26u8.iter_bytes(lsb0, f) && ct.iter_bytes(lsb0, f),
-        }
-    }
-}
-
 pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
     match cx.trait_refs.find(&id) {
        Some(&t) => t,
@@ -3904,7 +3720,7 @@ impl DtorKind {
 pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
     match cx.destructor_for_type.find(&struct_id) {
         Some(&method_def_id) => {
-            let flag = !has_attr(cx, struct_id, "no_drop_flag");
+            let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
 
             TraitDtor(method_def_id, flag)
         }
@@ -3954,7 +3770,7 @@ pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
           }
 
           ast_map::node_variant(ref variant, _, path) => {
-            vec::append_one(vec::to_owned(vec::init(*path)),
+            vec::append_one(vec::to_owned(path.init()),
                             ast_map::path_name((*variant).node.name))
           }
 
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index b7242e64f23..07fb23fea48 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -753,7 +753,7 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBou
     //! 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
+    //! like `Copy` or `Send`. Used to translate the bounds that
     //! appear in closure and trait types, where only builtin bounds are
     //! legal.
     //! If no bounds were specified, we choose a "default" bound based on
@@ -788,9 +788,9 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBou
             }
             builtin_bounds
         },
-        // ~Trait is sugar for ~Trait:Owned.
+        // ~Trait is sugar for ~Trait:Send.
         (&None, ty::UniqTraitStore) => {
-            let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundOwned); set
+            let mut set = ty::EmptyBuiltinBounds(); set.add(ty::BoundSend); set
         }
         // @Trait is sugar for @Trait:'static.
         // &'static Trait is sugar for &'static Trait:'static.
@@ -807,19 +807,19 @@ 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
+    //! traits, like `Copy` or `Send`, 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);
+    if trait_def_id == li.send_trait() {
+        builtin_bounds.add(ty::BoundSend);
         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);
+    } else if trait_def_id == li.freeze_trait() {
+        builtin_bounds.add(ty::BoundFreeze);
         true
     } else if trait_def_id == li.sized_trait() {
         builtin_bounds.add(ty::BoundSized);
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index de6b792032b..58a527f3501 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -538,7 +538,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
           check_pointer_pat(pcx, Managed, inner, pat.id, pat.span, expected);
       }
       ast::pat_uniq(inner) => {
-          check_pointer_pat(pcx, Owned, inner, pat.id, pat.span, expected);
+          check_pointer_pat(pcx, Send, inner, pat.id, pat.span, expected);
       }
       ast::pat_region(inner) => {
           check_pointer_pat(pcx, Borrowed, inner, pat.id, pat.span, expected);
@@ -624,7 +624,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
         ty::ty_box(e_inner) if pointer_kind == Managed => {
             check_inner(e_inner);
         }
-        ty::ty_uniq(e_inner) if pointer_kind == Owned => {
+        ty::ty_uniq(e_inner) if pointer_kind == Send => {
             check_inner(e_inner);
         }
         ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
@@ -641,7 +641,7 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
                 Some(expected),
                 fmt!("%s pattern", match pointer_kind {
                     Managed => "an @-box",
-                    Owned => "a ~-box",
+                    Send => "a ~-box",
                     Borrowed => "an &-pointer"
                 }),
                 None);
@@ -651,4 +651,4 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
 }
 
 #[deriving(Eq)]
-enum PointerKind { Managed, Owned, Borrowed }
+enum PointerKind { Managed, Send, Borrowed }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 777b11186c6..4bebca3c9a8 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -976,7 +976,9 @@ 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_explicit_self(candidate.method_ty.explicit_self);
+        // FIXME(#7411): We always pass self by-ref since we stuff it in the environment slot.
+        // Eventually that should not be the case
+        let self_mode = ty::ByRef;
 
         // before we only checked whether self_ty could be a subtype
         // of rcvr_ty; now we actually make it so (this may cause
@@ -1086,16 +1088,19 @@ impl<'self> LookupContext<'self> {
             _ => {}
         }
 
-        return match candidate.method_ty.explicit_self {
+        let result = match candidate.method_ty.explicit_self {
             sty_static => {
+                debug!("(is relevant?) explicit self is static");
                 false
             }
 
             sty_value => {
+                debug!("(is relevant?) explicit self is by-value");
                 self.fcx.can_mk_subty(rcvr_ty, candidate.rcvr_ty).is_ok()
             }
 
             sty_region(_, m) => {
+                debug!("(is relevant?) explicit self is a region");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_rptr(_, mt) => {
                         mutability_matches(mt.mutbl, m) &&
@@ -1107,6 +1112,7 @@ impl<'self> LookupContext<'self> {
             }
 
             sty_box(m) => {
+                debug!("(is relevant?) explicit self is a box");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_box(mt) => {
                         mutability_matches(mt.mutbl, m) &&
@@ -1118,6 +1124,7 @@ impl<'self> LookupContext<'self> {
             }
 
             sty_uniq(m) => {
+                debug!("(is relevant?) explicit self is a unique pointer");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(mt) => {
                         mutability_matches(mt.mutbl, m) &&
@@ -1129,6 +1136,10 @@ impl<'self> LookupContext<'self> {
             }
         };
 
+        debug!("(is relevant?) %s", if result { "yes" } else { "no" });
+
+        return result;
+
         fn mutability_matches(self_mutbl: ast::mutability,
                               candidate_mutbl: ast::mutability) -> bool {
             //! True if `self_mutbl <: candidate_mutbl`
@@ -1242,10 +1253,3 @@ impl<'self> LookupContext<'self> {
         self.tcx().sess.bug(s)
     }
 }
-
-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 97e0cd4baf8..23266767124 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -213,6 +213,13 @@ impl PurityState {
     }
 }
 
+/// Whether `check_binop` allows overloaded operators to be invoked.
+#[deriving(Eq)]
+enum AllowOverloadedOperatorsFlag {
+    AllowOverloadedOperators,
+    DontAllowOverloadedOperators,
+}
+
 pub struct FnCtxt {
     // Number of errors that had been reported when we started
     // checking this function. On exit, if we find that *more* errors
@@ -602,6 +609,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
         for ms.iter().advance |m| {
             check_method(ccx, *m);
         }
+        vtable::resolve_impl(ccx, it);
       }
       ast::item_trait(_, _, ref trait_methods) => {
         for (*trait_methods).iter().advance |trait_method| {
@@ -784,10 +792,6 @@ impl FnCtxt {
         ast_ty_to_ty(self, self, ast_t)
     }
 
-    pub fn expr_to_str(&self, expr: @ast::expr) -> ~str {
-        expr.repr(self.tcx())
-    }
-
     pub fn pat_to_str(&self, pat: @ast::pat) -> ~str {
         pat.repr(self.tcx())
     }
@@ -796,9 +800,8 @@ impl FnCtxt {
         match self.inh.node_types.find(&ex.id) {
             Some(&t) => t,
             None => {
-                self.tcx().sess.bug(
-                    fmt!("no type for %s in fcx %s",
-                         self.expr_to_str(ex), self.tag()));
+                self.tcx().sess.bug(fmt!("no type for expr in fcx %s",
+                                         self.tag()));
             }
         }
     }
@@ -1138,7 +1141,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                                expr: @ast::expr,
                                expected: Option<ty::t>,
                                unifier: &fn()) {
-    debug!(">> typechecking %s", fcx.expr_to_str(expr));
+    debug!(">> typechecking");
 
     fn check_method_argument_types(
         fcx: @mut FnCtxt,
@@ -1391,6 +1394,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                 method_map.insert(expr.id, (*entry));
             }
             None => {
+                debug!("(checking method call) failing expr is %d", expr.id);
+
                 fcx.type_error_message(expr.span,
                   |actual| {
                       fmt!("type `%s` does not implement any method in scope \
@@ -1487,7 +1492,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
                    lhs: @ast::expr,
                    rhs: @ast::expr,
                    // Used only in the error case
-                   expected_result: Option<ty::t>
+                   expected_result: Option<ty::t>,
+                   allow_overloaded_operators: AllowOverloadedOperatorsFlag
                   ) {
         let tcx = fcx.ccx.tcx;
 
@@ -1537,8 +1543,30 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
 
         }
 
-        let result_t = check_user_binop(fcx, callee_id, expr, lhs, lhs_t, op, rhs,
-                                       expected_result);
+        // Check for overloaded operators if allowed.
+        let result_t;
+        if allow_overloaded_operators == AllowOverloadedOperators {
+            result_t = check_user_binop(fcx,
+                                        callee_id,
+                                        expr,
+                                        lhs,
+                                        lhs_t,
+                                        op,
+                                        rhs,
+                                        expected_result);
+        } else {
+            fcx.type_error_message(expr.span,
+                                   |actual| {
+                                        fmt!("binary operation %s cannot be \
+                                              applied to type `%s`",
+                                             ast_util::binop_to_str(op),
+                                             actual)
+                                   },
+                                   lhs_t,
+                                   None);
+            result_t = ty::mk_err();
+        }
+
         fcx.write_ty(expr.id, result_t);
         if ty::type_is_error(result_t) {
             fcx.write_ty(rhs.id, result_t);
@@ -1704,8 +1732,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
             ty::mk_closure(tcx, fn_ty_copy)
         };
 
-        debug!("check_expr_fn_with_unifier %s fty=%s",
-               fcx.expr_to_str(expr),
+        debug!("check_expr_fn_with_unifier fty=%s",
                fcx.infcx().ty_to_str(fty));
 
         fcx.write_ty(expr.id, fty);
@@ -2229,7 +2256,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         fcx.write_ty(id, typ);
       }
       ast::expr_binary(callee_id, op, lhs, rhs) => {
-        check_binop(fcx, callee_id, expr, op, lhs, rhs, expected);
+        check_binop(fcx,
+                    callee_id,
+                    expr,
+                    op,
+                    lhs,
+                    rhs,
+                    expected,
+                    AllowOverloadedOperators);
+
         let lhs_ty = fcx.expr_ty(lhs);
         let rhs_ty = fcx.expr_ty(rhs);
         if ty::type_is_error(lhs_ty) ||
@@ -2242,7 +2277,15 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
         }
       }
       ast::expr_assign_op(callee_id, op, lhs, rhs) => {
-        check_binop(fcx, callee_id, expr, op, lhs, rhs, expected);
+        check_binop(fcx,
+                    callee_id,
+                    expr,
+                    op,
+                    lhs,
+                    rhs,
+                    expected,
+                    DontAllowOverloadedOperators);
+
         let lhs_t = fcx.expr_ty(lhs);
         let result_t = fcx.expr_ty(expr);
         demand::suptype(fcx, expr.span, result_t, lhs_t);
@@ -3247,6 +3290,9 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
       ast::def_self_ty(*) => {
         fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
       }
+      ast::def_method(*) => {
+        fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
+      }
     }
 }
 
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 69d4d82d15f..df81ebd48aa 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -230,7 +230,7 @@ fn constrain_bindings_in_pat(pat: @ast::pat, rcx: @mut Rcx) {
 }
 
 fn visit_expr(expr: @ast::expr, (rcx, v): (@mut Rcx, rvt)) {
-    debug!("regionck::visit_expr(e=%s)", rcx.fcx.expr_to_str(expr));
+    debug!("regionck::visit_expr(e=?)");
 
     let has_method_map = rcx.fcx.inh.method_map.contains_key(&expr.id);
 
@@ -520,8 +520,7 @@ fn constrain_derefs(rcx: @mut Rcx,
     let tcx = rcx.fcx.tcx();
     let r_deref_expr = ty::re_scope(deref_expr.id);
     for uint::range(0, derefs) |i| {
-        debug!("constrain_derefs(deref_expr=%s, derefd_ty=%s, derefs=%?/%?",
-               rcx.fcx.expr_to_str(deref_expr),
+        debug!("constrain_derefs(deref_expr=?, derefd_ty=%s, derefs=%?/%?",
                rcx.fcx.infcx().ty_to_str(derefd_ty),
                i, derefs);
 
@@ -576,8 +575,7 @@ fn constrain_index(rcx: @mut Rcx,
 
     let tcx = rcx.fcx.tcx();
 
-    debug!("constrain_index(index_expr=%s, indexed_ty=%s",
-           rcx.fcx.expr_to_str(index_expr),
+    debug!("constrain_index(index_expr=?, indexed_ty=%s",
            rcx.fcx.infcx().ty_to_str(indexed_ty));
 
     let r_index_expr = ty::re_scope(index_expr.id);
@@ -808,7 +806,7 @@ pub mod guarantor {
          * to the lifetime of its guarantor (if any).
          */
 
-        debug!("guarantor::for_addr_of(base=%s)", rcx.fcx.expr_to_str(base));
+        debug!("guarantor::for_addr_of(base=?)");
 
         let guarantor = guarantor(rcx, base);
         link(rcx, expr.span, expr.id, guarantor);
@@ -842,8 +840,7 @@ pub mod guarantor {
          * region pointers.
          */
 
-        debug!("guarantor::for_autoref(expr=%s, autoref=%?)",
-               rcx.fcx.expr_to_str(expr), autoref);
+        debug!("guarantor::for_autoref(autoref=%?)", autoref);
 
         let mut expr_ct = categorize_unadjusted(rcx, expr);
         debug!("    unadjusted cat=%?", expr_ct.cat);
@@ -970,7 +967,7 @@ pub mod guarantor {
          * `&expr`).
          */
 
-        debug!("guarantor(expr=%s)", rcx.fcx.expr_to_str(expr));
+        debug!("guarantor()");
         match expr.node {
             ast::expr_unary(_, ast::deref, b) => {
                 let cat = categorize(rcx, b);
@@ -1034,7 +1031,7 @@ pub mod guarantor {
     }
 
     fn categorize(rcx: @mut Rcx, expr: @ast::expr) -> ExprCategorization {
-        debug!("categorize(expr=%s)", rcx.fcx.expr_to_str(expr));
+        debug!("categorize()");
 
         let mut expr_ct = categorize_unadjusted(rcx, expr);
         debug!("before adjustments, cat=%?", expr_ct.cat);
@@ -1086,7 +1083,7 @@ pub mod guarantor {
     fn categorize_unadjusted(rcx: @mut Rcx,
                              expr: @ast::expr)
                           -> ExprCategorizationType {
-        debug!("categorize_unadjusted(expr=%s)", rcx.fcx.expr_to_str(expr));
+        debug!("categorize_unadjusted()");
 
         let guarantor = {
             if rcx.fcx.inh.method_map.contains_key(&expr.id) {
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index 160737142c8..fb79a7c3c99 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -112,7 +112,7 @@ pub fn replace_bound_regions_in_fn_sig(
             // kinds of types.  This had already caused me several
             // bugs so I decided to switch over.
             do ty::fold_regions(tcx, *ty) |r, in_fn| {
-                if !in_fn { isr = append_isr(isr, to_r, r); }
+                if !in_fn { isr = append_isr(isr, |br| to_r(br), r); }
                 r
             };
 
@@ -211,18 +211,18 @@ pub fn relate_nested_regions(
         match ty::get(ty).sty {
             ty::ty_rptr(r, ref mt) |
             ty::ty_evec(ref mt, ty::vstore_slice(r)) => {
-                relate(*the_stack, r, relate_op);
+                relate(*the_stack, r, |x,y| relate_op(x,y));
                 the_stack.push(r);
-                walk_ty(tcx, the_stack, mt.ty, relate_op);
+                walk_ty(tcx, the_stack, mt.ty, |x,y| relate_op(x,y));
                 the_stack.pop();
             }
             _ => {
                 ty::fold_regions_and_ty(
                     tcx,
                     ty,
-                    |r| { relate(*the_stack, r, relate_op); r },
-                    |t| { walk_ty(tcx, the_stack, t, relate_op); t },
-                    |t| { walk_ty(tcx, the_stack, t, relate_op); t });
+                    |r| { relate(     *the_stack, r, |x,y| relate_op(x,y)); r },
+                    |t| { walk_ty(tcx, the_stack, t, |x,y| relate_op(x,y)); t },
+                    |t| { walk_ty(tcx, the_stack, t, |x,y| relate_op(x,y)); t });
             }
         }
     }
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index bd78e9cc5fb..0bf20f9fbcb 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -17,8 +17,8 @@ use middle::typeck::check::{structurally_resolved_type};
 use middle::typeck::infer::fixup_err_to_str;
 use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
 use middle::typeck::infer;
-use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res};
-use middle::typeck::vtable_static;
+use middle::typeck::{CrateCtxt, vtable_origin, vtable_res};
+use middle::typeck::{vtable_static, vtable_param, vtable_self};
 use middle::subst::Subst;
 use util::common::indenter;
 use util::ppaux::tys_to_str;
@@ -90,6 +90,7 @@ fn lookup_vtables(vcx: &VtableContext,
     let mut i = 0u;
     for substs.tps.iter().advance |ty| {
         // ty is the value supplied for the type parameter A...
+        let mut param_result = ~[];
 
         for ty::each_bound_trait_and_supertraits(
             tcx, type_param_defs[i].bounds) |trait_ref|
@@ -106,7 +107,7 @@ fn lookup_vtables(vcx: &VtableContext,
             debug!("after subst: %s", trait_ref.repr(tcx));
 
             match lookup_vtable(vcx, location_info, *ty, &trait_ref, is_early) {
-                Some(vtable) => result.push(vtable),
+                Some(vtable) => param_result.push(vtable),
                 None => {
                     vcx.tcx().sess.span_fatal(
                         location_info.span,
@@ -117,6 +118,7 @@ fn lookup_vtables(vcx: &VtableContext,
                 }
             }
         }
+        result.push(@param_result);
         i += 1u;
     }
     debug!("lookup_vtables result(\
@@ -237,6 +239,17 @@ fn lookup_vtable(vcx: &VtableContext,
             }
         }
 
+        ty::ty_self(trait_id) => {
+            debug!("trying to find %? vtable for type %?",
+                   trait_ref.def_id, trait_id);
+
+            if trait_id == trait_ref.def_id {
+                let vtable = vtable_self(trait_id);
+                debug!("found self vtable: %?", vtable);
+                return Some(vtable);
+            }
+        }
+
         _ => {
             let mut found = ~[];
 
@@ -467,6 +480,12 @@ pub fn location_info_for_expr(expr: @ast::expr) -> LocationInfo {
         id: expr.id
     }
 }
+pub fn location_info_for_item(item: @ast::item) -> LocationInfo {
+    LocationInfo {
+        span: item.span,
+        id: item.id
+    }
+}
 
 pub fn early_resolve_expr(ex: @ast::expr,
                           fcx: @mut FnCtxt,
@@ -583,7 +602,8 @@ pub fn early_resolve_expr(ex: @ast::expr,
                                   // vtable (that is: "ex has vtable
                                   // <vtable>")
                                   if !is_early {
-                                      insert_vtables(fcx, ex.id, @~[vtable]);
+                                      insert_vtables(fcx, ex.id,
+                                                     @~[@~[vtable]]);
                                   }
                               }
                               None => {
@@ -650,6 +670,27 @@ fn resolve_expr(ex: @ast::expr,
     visit::visit_expr(ex, (fcx, v));
 }
 
+pub fn resolve_impl(ccx: @mut CrateCtxt, impl_item: @ast::item) {
+    let def_id = ast_util::local_def(impl_item.id);
+    match ty::impl_trait_ref(ccx.tcx, def_id) {
+        None => {},
+        Some(trait_ref) => {
+            let infcx = infer::new_infer_ctxt(ccx.tcx);
+            let vcx = VtableContext { ccx: ccx, infcx: infcx };
+            let trait_def = ty::lookup_trait_def(ccx.tcx, trait_ref.def_id);
+
+            let vtbls = lookup_vtables(&vcx,
+                                       &location_info_for_item(impl_item),
+                                       *trait_def.generics.type_param_defs,
+                                       &trait_ref.substs,
+                                       false);
+
+            // FIXME(#7450): Doesn't work cross crate
+            ccx.vtable_map.insert(impl_item.id, vtbls);
+        }
+    }
+}
+
 // Detect points where a trait-bounded type parameter is
 // instantiated, resolve the impls for the parameters.
 pub fn resolve_in_block(fcx: @mut FnCtxt, bl: &ast::blk) {
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index dd9d68beb1f..e2efdc51fca 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -20,7 +20,8 @@ use middle::typeck::check::{FnCtxt, SelfInfo};
 use middle::typeck::infer::{force_all, resolve_all, resolve_region};
 use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
-use middle::typeck::{vtable_origin, vtable_static, vtable_param};
+use middle::typeck::{vtable_res, vtable_origin};
+use middle::typeck::{vtable_static, vtable_param, vtable_self};
 use middle::typeck::method_map_entry;
 use middle::typeck::write_substs_to_tcx;
 use middle::typeck::write_ty_to_tcx;
@@ -84,7 +85,7 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
     match fcx.inh.vtable_map.find(&id) {
         None => {}
         Some(origins) => {
-            let r_origins = @origins.map(|o| resolve_origin(fcx, sp, o));
+            let r_origins = resolve_origins(fcx, sp, *origins);
             let vtable_map = fcx.ccx.vtable_map;
             vtable_map.insert(id, r_origins);
             debug!("writeback::resolve_vtable_map_entry(id=%d, vtables=%?)",
@@ -92,18 +93,26 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
         }
     }
 
+    fn resolve_origins(fcx: @mut FnCtxt, sp: span,
+                       vtbls: vtable_res) -> vtable_res {
+        @vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o)))
+    }
+
     fn resolve_origin(fcx: @mut FnCtxt,
                       sp: span,
                       origin: &vtable_origin) -> vtable_origin {
         match origin {
             &vtable_static(def_id, ref tys, origins) => {
                 let r_tys = resolve_type_vars_in_types(fcx, sp, *tys);
-                let r_origins = @origins.map(|o| resolve_origin(fcx, sp, o));
+                let r_origins = resolve_origins(fcx, sp, origins);
                 vtable_static(def_id, r_tys, r_origins)
             }
             &vtable_param(n, b) => {
                 vtable_param(n, b)
             }
+            &vtable_self(def_id) => {
+                vtable_self(def_id)
+            }
         }
     }
 }
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 6da9895534b..a537d0cc72c 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -17,7 +17,7 @@
 use core::prelude::*;
 
 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};
 use metadata::decoder::{dl_def, dl_field, dl_impl};
 use middle::resolve::{Impl, MethodInfo};
@@ -788,7 +788,7 @@ impl CoherenceChecker {
                              `%s` to impl",
                             provided_method.method_info
                             .ident.repr(self.crate_context.tcx));
-                        vec::push(all_methods, provided_method.method_info);
+                        all_methods.push(provided_method.method_info);
                     }
                 }
             }
@@ -855,92 +855,81 @@ impl CoherenceChecker {
 
     // External crate handling
 
-    pub fn add_impls_for_module(&self,
-                                impls_seen: &mut HashSet<def_id>,
-                                crate_store: @mut CStore,
-                                module_def_id: def_id) {
-        let implementations = get_impls_for_mod(crate_store,
-                                                module_def_id,
-                                                None);
-        for implementations.iter().advance |implementation| {
-            debug!("coherence: adding impl from external crate: %s",
-                   ty::item_path_str(self.crate_context.tcx,
-                                     implementation.did));
-
-            // Make sure we don't visit the same implementation
-            // multiple times.
-            if !impls_seen.insert(implementation.did) {
-                // Skip this one.
-                loop;
-            }
-            // Good. Continue.
+    pub fn add_external_impl(&self,
+                             impls_seen: &mut HashSet<def_id>,
+                             crate_store: @mut CStore,
+                             impl_def_id: def_id) {
+        let implementation = csearch::get_impl(crate_store, impl_def_id);
 
-            let self_type = lookup_item_type(self.crate_context.tcx,
-                                             implementation.did);
-            let associated_traits = get_impl_trait(self.crate_context.tcx,
-                                                    implementation.did);
+        debug!("coherence: adding impl from external crate: %s",
+               ty::item_path_str(self.crate_context.tcx, implementation.did));
 
-            // Do a sanity check to make sure that inherent methods have base
-            // types.
+        // Make sure we don't visit the same implementation multiple times.
+        if !impls_seen.insert(implementation.did) {
+            // Skip this one.
+            return
+        }
+        // Good. Continue.
 
-            if associated_traits.is_none() {
-                match get_base_type_def_id(self.inference_context,
-                                           dummy_sp(),
-                                           self_type.ty) {
-                    None => {
-                        let session = self.crate_context.tcx.sess;
-                        session.bug(fmt!(
-                            "no base type for external impl \
-                             with no trait: %s (type %s)!",
-                             session.str_of(implementation.ident),
-                             ty_to_str(self.crate_context.tcx,self_type.ty)));
-                    }
-                    Some(_) => {
-                        // Nothing to do.
-                    }
+        let self_type = lookup_item_type(self.crate_context.tcx,
+                                         implementation.did);
+        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.is_none() {
+            match get_base_type_def_id(self.inference_context,
+                                       dummy_sp(),
+                                       self_type.ty) {
+                None => {
+                    let session = self.crate_context.tcx.sess;
+                    session.bug(fmt!("no base type for external impl with no \
+                                      trait: %s (type %s)!",
+                                     session.str_of(implementation.ident),
+                                     ty_to_str(self.crate_context.tcx,
+                                               self_type.ty)));
                 }
+                Some(_) => {} // Nothing to do.
             }
+        }
 
-            let mut implementation = *implementation;
-
-            // Record all the trait methods.
-            for associated_traits.iter().advance |trait_ref| {
-                self.instantiate_default_methods(implementation.did,
-                                                 &**trait_ref);
-                // Could we avoid these copies when we don't need them?
-                let mut methods = /*bad?*/ copy implementation.methods;
-                self.add_provided_methods_to_impl(
-                    &mut methods,
-                    &trait_ref.def_id,
-                    &implementation.did);
-                implementation = @Impl { methods: methods,
-                                        .. *implementation };
-
-
-                self.add_trait_method(trait_ref.def_id, implementation);
-            }
+        // Record all the trait methods.
+        let mut implementation = @implementation;
+        for associated_traits.iter().advance |trait_ref| {
+            self.instantiate_default_methods(implementation.did,
+                                             *trait_ref);
+
+            // XXX(sully): We could probably avoid this copy if there are no
+            // default methods.
+            let mut methods = copy implementation.methods;
+            self.add_provided_methods_to_impl(&mut methods,
+                                              &trait_ref.def_id,
+                                              &implementation.did);
+            implementation = @Impl {
+                methods: methods,
+                ..*implementation
+            };
 
-            // Add the implementation to the mapping from
-            // implementation to base type def ID, if there is a base
-            // type for this implementation.
+            self.add_trait_method(trait_ref.def_id, implementation);
+        }
 
-            match get_base_type_def_id(self.inference_context,
-                                     dummy_sp(),
-                                     self_type.ty) {
-                None => {
-                    // Nothing to do.
+        // Add the implementation to the mapping from implementation to base
+        // type def ID, if there is a base type for this implementation.
+        match get_base_type_def_id(self.inference_context,
+                                   dummy_sp(),
+                                   self_type.ty) {
+            None => {} // Nothing to do.
+            Some(base_type_def_id) => {
+                // inherent methods apply to `impl Type` but not
+                // `impl Trait for Type`:
+                if associated_traits.is_none() {
+                    self.add_inherent_method(base_type_def_id,
+                                             implementation);
                 }
-                Some(base_type_def_id) => {
-                    // inherent methods apply to `impl Type` but not
-                    // `impl Trait for Type`:
-                    if associated_traits.is_none() {
-                        self.add_inherent_method(base_type_def_id,
-                                                 implementation);
-                    }
 
-                    self.base_type_def_ids.insert(implementation.did,
-                                                  base_type_def_id);
-                }
+                self.base_type_def_ids.insert(implementation.did,
+                                              base_type_def_id);
             }
         }
     }
@@ -952,22 +941,14 @@ impl CoherenceChecker {
 
         let crate_store = self.crate_context.tcx.sess.cstore;
         do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
-            self.add_impls_for_module(&mut impls_seen,
-                                      crate_store,
-                                      def_id { crate: crate_number,
-                                               node: 0 });
-
             for each_path(crate_store, crate_number) |_, def_like, _| {
                 match def_like {
-                    dl_def(def_mod(def_id)) => {
-                        self.add_impls_for_module(&mut impls_seen,
-                                                  crate_store,
-                                                  def_id);
-                    }
-                    dl_def(_) | dl_impl(_) | dl_field => {
-                        // Skip this.
-                        loop;
+                    dl_impl(def_id) => {
+                        self.add_external_impl(&mut impls_seen,
+                                               crate_store,
+                                               def_id)
                     }
+                    dl_def(_) | dl_field => loop,   // Skip this.
                 }
             }
         }
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 0e118adb8f4..5065a475a40 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -81,10 +81,20 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: &ast::crate) {
         })));
 }
 
-impl CrateCtxt {
+pub trait ToTy {
     fn to_ty<RS:region_scope + Copy + 'static>(
-        &self, rs: &RS, ast_ty: &ast::Ty) -> ty::t
-    {
+             &self,
+             rs: &RS,
+             ast_ty: &ast::Ty)
+             -> ty::t;
+}
+
+impl ToTy for CrateCtxt {
+    fn to_ty<RS:region_scope + Copy + 'static>(
+             &self,
+             rs: &RS,
+             ast_ty: &ast::Ty)
+             -> ty::t {
         ast_ty_to_ty(self, rs, ast_ty)
     }
 }
@@ -1165,7 +1175,7 @@ pub fn ty_generics(ccx: &CrateCtxt,
          * enum consisting of a newtyped Ty or a region) to ty's
          * notion of ty param bounds, which can either be user-defined
          * traits, or one of the four built-in traits (formerly known
-         * as kinds): Const, Copy, and Send.
+         * as kinds): Freeze, Copy, and Send.
          */
 
         let mut param_bounds = ty::ParamBounds {
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index 884f72b57f0..7a4ea0999ef 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -64,7 +64,8 @@ use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::lub::Lub;
 use middle::typeck::infer::sub::Sub;
 use middle::typeck::infer::to_str::InferStr;
-use middle::typeck::infer::{cres, InferCtxt, ures};
+use middle::typeck::infer::unify::{InferCtxtMethods, UnifyInferCtxtMethods};
+use middle::typeck::infer::{InferCtxt, cres, ures};
 use util::common::indent;
 
 use core::result::{iter_vec2, map_vec2};
diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs
index 658fd67ee58..ed19310d5d6 100644
--- a/src/librustc/middle/typeck/infer/lattice.rs
+++ b/src/librustc/middle/typeck/infer/lattice.rs
@@ -71,15 +71,53 @@ impl LatticeValue for ty::t {
     }
 }
 
-impl CombineFields {
-    pub fn var_sub_var<T:Copy + InferStr + LatticeValue,
-                       V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
-                                                                        a_id:
-                                                                        V,
-                                                                        b_id:
-                                                                        V)
-                                                                        ->
-                                                                        ures {
+pub trait CombineFieldsLatticeMethods {
+    fn var_sub_var<T:Copy + InferStr + LatticeValue,
+                   V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
+                                                                    a_id: V,
+                                                                    b_id: V)
+                                                                    -> ures;
+    /// make variable a subtype of T
+    fn var_sub_t<T:Copy + InferStr + LatticeValue,
+                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                 &self,
+                 a_id: V,
+                 b: T)
+                 -> ures;
+    fn t_sub_var<T:Copy + InferStr + LatticeValue,
+                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                 &self,
+                 a: T,
+                 b_id: V)
+                 -> ures;
+    fn merge_bnd<T:Copy + InferStr + LatticeValue>(
+                 &self,
+                 a: &Bound<T>,
+                 b: &Bound<T>,
+                 lattice_op: LatticeOp<T>)
+                 -> cres<Bound<T>>;
+    fn set_var_to_merged_bounds<T:Copy + InferStr + LatticeValue,
+                                V:Copy+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
+                                &self,
+                                v_id: V,
+                                a: &Bounds<T>,
+                                b: &Bounds<T>,
+                                rank: uint)
+                                -> ures;
+    fn bnds<T:Copy + InferStr + LatticeValue>(
+            &self,
+            a: &Bound<T>,
+            b: &Bound<T>)
+            -> ures;
+}
+
+impl CombineFieldsLatticeMethods for CombineFields {
+    fn var_sub_var<T:Copy + InferStr + LatticeValue,
+                   V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                   &self,
+                   a_id: V,
+                   b_id: V)
+                   -> ures {
         /*!
          *
          * Make one variable a subtype of another variable.  This is a
@@ -127,12 +165,12 @@ impl CombineFields {
     }
 
     /// make variable a subtype of T
-    pub fn var_sub_t<T:Copy + InferStr + LatticeValue,
-                     V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
-                                                                      a_id: V,
-                                                                      b: T)
-                                                                      -> ures
-                                                                      {
+    fn var_sub_t<T:Copy + InferStr + LatticeValue,
+                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                 &self,
+                 a_id: V,
+                 b: T)
+                 -> ures {
         /*!
          *
          * Make a variable (`a_id`) a subtype of the concrete type `b` */
@@ -151,12 +189,12 @@ impl CombineFields {
             a_id, a_bounds, b_bounds, node_a.rank)
     }
 
-    pub fn t_sub_var<T:Copy + InferStr + LatticeValue,
-                     V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(&self,
-                                                                      a: T,
-                                                                      b_id: V)
-                                                                      -> ures
-                                                                      {
+    fn t_sub_var<T:Copy + InferStr + LatticeValue,
+                 V:Copy + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>(
+                 &self,
+                 a: T,
+                 b_id: V)
+                 -> ures {
         /*!
          *
          * Make a concrete type (`a`) a subtype of the variable `b_id` */
@@ -175,12 +213,12 @@ impl CombineFields {
             b_id, a_bounds, b_bounds, node_b.rank)
     }
 
-    pub fn merge_bnd<T:Copy + InferStr + LatticeValue>(&self,
-                                                       a: &Bound<T>,
-                                                       b: &Bound<T>,
-                                                       lattice_op:
-                                                       LatticeOp<T>)
-                                                       -> cres<Bound<T>> {
+    fn merge_bnd<T:Copy + InferStr + LatticeValue>(
+                 &self,
+                 a: &Bound<T>,
+                 b: &Bound<T>,
+                 lattice_op: LatticeOp<T>)
+                 -> cres<Bound<T>> {
         /*!
          *
          * Combines two bounds into a more general bound. */
@@ -202,14 +240,14 @@ impl CombineFields {
         }
     }
 
-    pub fn set_var_to_merged_bounds<T:Copy + InferStr + LatticeValue,
-                                    V:Copy+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
-                                    &self,
-                                    v_id: V,
-                                    a: &Bounds<T>,
-                                    b: &Bounds<T>,
-                                    rank: uint)
-                                    -> ures {
+    fn set_var_to_merged_bounds<T:Copy + InferStr + LatticeValue,
+                                V:Copy+Eq+ToStr+Vid+UnifyVid<Bounds<T>>>(
+                                &self,
+                                v_id: V,
+                                a: &Bounds<T>,
+                                b: &Bounds<T>,
+                                rank: uint)
+                                -> ures {
         /*!
          *
          * Updates the bounds for the variable `v_id` to be the intersection
@@ -264,10 +302,10 @@ impl CombineFields {
         uok()
     }
 
-    pub fn bnds<T:Copy + InferStr + LatticeValue>(&self,
-                                                  a: &Bound<T>,
-                                                  b: &Bound<T>)
-                                                  -> ures {
+    fn bnds<T:Copy + InferStr + LatticeValue>(&self,
+                                              a: &Bound<T>,
+                                              b: &Bound<T>)
+                                              -> ures {
         debug!("bnds(%s <: %s)", a.inf_str(self.infcx),
                b.inf_str(self.infcx));
         let _r = indenter();
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index 1bfe452f25e..3e2d4a71dfb 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -582,7 +582,7 @@ impl InferCtxt {
 
         debug!("commit()");
         do indent {
-            let r = self.try(f);
+            let r = self.try(|| f());
 
             self.ty_var_bindings.bindings.truncate(0);
             self.int_var_bindings.bindings.truncate(0);
@@ -836,6 +836,6 @@ pub fn fold_regions_in_sig(
     fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig
 {
     do ty::fold_sig(fn_sig) |t| {
-        ty::fold_regions(tcx, t, fldr)
+        ty::fold_regions(tcx, t, |r, in_fn| fldr(r, in_fn))
     }
 }
diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs
index 0aad161a678..4380711b78e 100644
--- a/src/librustc/middle/typeck/infer/region_inference.rs
+++ b/src/librustc/middle/typeck/infer/region_inference.rs
@@ -548,43 +548,18 @@ use util::ppaux::note_and_explain_region;
 
 use core::cell::Cell;
 use core::hashmap::{HashMap, HashSet};
-use core::to_bytes;
 use core::uint;
 use core::vec;
 use syntax::codemap::span;
 use syntax::ast;
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 enum Constraint {
     ConstrainVarSubVar(RegionVid, RegionVid),
     ConstrainRegSubVar(Region, RegionVid),
     ConstrainVarSubReg(RegionVid, Region)
 }
 
-impl to_bytes::IterBytes for Constraint {
-   fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ConstrainVarSubVar(ref v0, ref v1) => {
-                0u8.iter_bytes(lsb0, f) &&
-                v0.iter_bytes(lsb0, f) &&
-                v1.iter_bytes(lsb0, f)
-            }
-
-            ConstrainRegSubVar(ref ra, ref va) => {
-                1u8.iter_bytes(lsb0, f) &&
-                ra.iter_bytes(lsb0, f) &&
-                va.iter_bytes(lsb0, f)
-            }
-
-            ConstrainVarSubReg(ref va, ref ra) => {
-                2u8.iter_bytes(lsb0, f) &&
-                va.iter_bytes(lsb0, f) &&
-                ra.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 #[deriving(Eq, IterBytes)]
 struct TwoRegions {
     a: Region,
diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs
index ab52ef36978..1311907eed2 100644
--- a/src/librustc/middle/typeck/infer/resolve.rs
+++ b/src/librustc/middle/typeck/infer/resolve.rs
@@ -54,7 +54,7 @@ use middle::ty;
 use middle::typeck::infer::{Bounds, cyclic_ty, fixup_err, fres, InferCtxt};
 use middle::typeck::infer::{region_var_bound_by_region_var, unresolved_ty};
 use middle::typeck::infer::to_str::InferStr;
-use middle::typeck::infer::unify::Root;
+use middle::typeck::infer::unify::{Root, UnifyInferCtxtMethods};
 use util::common::{indent, indenter};
 use util::ppaux::ty_to_str;
 
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 4462d43015c..eb912aa2dda 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -18,6 +18,7 @@ use middle::typeck::infer::combine::*;
 use middle::typeck::infer::cres;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::InferCtxt;
+use middle::typeck::infer::lattice::CombineFieldsLatticeMethods;
 use middle::typeck::infer::lub::Lub;
 use middle::typeck::infer::to_str::InferStr;
 use util::common::{indent, indenter};
diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs
index 371d389f712..a185633a7ac 100644
--- a/src/librustc/middle/typeck/infer/unify.rs
+++ b/src/librustc/middle/typeck/infer/unify.rs
@@ -40,9 +40,31 @@ pub trait UnifyVid<T> {
                                       -> &'v mut ValsAndBindings<Self, T>;
 }
 
-impl InferCtxt {
-    pub fn get<T:Copy, V:Copy+Eq+Vid+UnifyVid<T>>(&mut self, vid: V)
-                                                  -> Node<V, T> {
+pub trait UnifyInferCtxtMethods {
+    fn get<T:Copy,
+           V:Copy + Eq + Vid + UnifyVid<T>>(
+           &mut self,
+           vid: V)
+           -> Node<V, T>;
+    fn set<T:Copy + InferStr,
+           V:Copy + Vid + ToStr + UnifyVid<T>>(
+           &mut self,
+           vid: V,
+           new_v: VarValue<V, T>);
+    fn unify<T:Copy + InferStr,
+             V:Copy + Vid + ToStr + UnifyVid<T>>(
+             &mut self,
+             node_a: &Node<V, T>,
+             node_b: &Node<V, T>)
+             -> (V, uint);
+}
+
+impl UnifyInferCtxtMethods for InferCtxt {
+    fn get<T:Copy,
+           V:Copy + Eq + Vid + UnifyVid<T>>(
+           &mut self,
+           vid: V)
+           -> Node<V, T> {
         /*!
          *
          * Find the root node for `vid`. This uses the standard
@@ -84,10 +106,11 @@ impl InferCtxt {
         }
     }
 
-    pub fn set<T:Copy + InferStr,
-               V:Copy + Vid + ToStr + UnifyVid<T>>(&mut self,
-                                                   vid: V,
-                                                   new_v: VarValue<V, T>) {
+    fn set<T:Copy + InferStr,
+           V:Copy + Vid + ToStr + UnifyVid<T>>(
+           &mut self,
+           vid: V,
+           new_v: VarValue<V, T>) {
         /*!
          *
          * Sets the value for `vid` to `new_v`.  `vid` MUST be a root node!
@@ -102,11 +125,12 @@ impl InferCtxt {
         vb.vals.insert(vid.to_uint(), new_v);
     }
 
-    pub fn unify<T:Copy + InferStr,
-                 V:Copy + Vid + ToStr + UnifyVid<T>>(&mut self,
-                                                     node_a: &Node<V, T>,
-                                                     node_b: &Node<V, T>)
-                                                     -> (V, uint) {
+    fn unify<T:Copy + InferStr,
+             V:Copy + Vid + ToStr + UnifyVid<T>>(
+             &mut self,
+             node_a: &Node<V, T>,
+             node_b: &Node<V, T>)
+             -> (V, uint) {
         // Rank optimization: if you don't know what it is, check
         // out <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>
 
@@ -155,14 +179,31 @@ pub fn mk_err<T:SimplyUnifiable>(a_is_expected: bool,
     }
 }
 
-impl InferCtxt {
-    pub fn simple_vars<T:Copy+Eq+InferStr+SimplyUnifiable,
-                       V:Copy+Eq+Vid+ToStr+UnifyVid<Option<T>>>(&mut self,
-                                                                a_is_expected:
-                                                                bool,
-                                                                a_id: V,
-                                                                b_id: V)
-                                                                -> ures {
+pub trait InferCtxtMethods {
+    fn simple_vars<T:Copy + Eq + InferStr + SimplyUnifiable,
+                   V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+                   &mut self,
+                   a_is_expected: bool,
+                   a_id: V,
+                   b_id: V)
+                   -> ures;
+    fn simple_var_t<T:Copy + Eq + InferStr + SimplyUnifiable,
+                    V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+                    &mut self,
+                    a_is_expected: bool,
+                    a_id: V,
+                    b: T)
+                    -> ures;
+}
+
+impl InferCtxtMethods for InferCtxt {
+    fn simple_vars<T:Copy + Eq + InferStr + SimplyUnifiable,
+                   V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+                   &mut self,
+                   a_is_expected: bool,
+                   a_id: V,
+                   b_id: V)
+                   -> ures {
         /*!
          *
          * Unifies two simple variables.  Because simple variables do
@@ -194,13 +235,13 @@ impl InferCtxt {
         return uok();
     }
 
-    pub fn simple_var_t<T:Copy+Eq+InferStr+SimplyUnifiable,
-                        V:Copy+Eq+Vid+ToStr+UnifyVid<Option<T>>>(&mut self,
-                                                                 a_is_expected
-                                                                 : bool,
-                                                                 a_id: V,
-                                                                 b: T)
-                                                                 -> ures {
+    fn simple_var_t<T:Copy + Eq + InferStr + SimplyUnifiable,
+                    V:Copy + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
+                    &mut self,
+                    a_is_expected: bool,
+                    a_id: V,
+                    b: T)
+                    -> ures {
         /*!
          *
          * Sets the value of the variable `a_id` to `b`.  Because
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index d834998d4ee..98f7af4bfd4 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -135,8 +135,9 @@ pub struct method_map_entry {
 // of the method to be invoked
 pub type method_map = @mut HashMap<ast::node_id, method_map_entry>;
 
+pub type vtable_param_res = @~[vtable_origin];
 // Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res = @~[vtable_origin];
+pub type vtable_res = @~[vtable_param_res];
 
 pub enum vtable_origin {
     /*
@@ -154,7 +155,12 @@ pub enum vtable_origin {
       The first uint is the param number (identifying T in the example),
       and the second is the bound number (identifying baz)
      */
-    vtable_param(uint, uint)
+    vtable_param(uint, uint),
+
+    /*
+     Dynamic vtable, comes from self.
+    */
+    vtable_self(ast::def_id)
 }
 
 impl Repr for vtable_origin {
@@ -171,6 +177,9 @@ impl Repr for vtable_origin {
             vtable_param(x, y) => {
                 fmt!("vtable_param(%?, %?)", x, y)
             }
+            vtable_self(def_id) => {
+                fmt!("vtable_self(%?)", def_id)
+            }
         }
     }
 }
diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs
index a27838b5d11..957cf02ed77 100644
--- a/src/librustc/rustc.rs
+++ b/src/librustc/rustc.rs
@@ -80,6 +80,7 @@ pub mod middle {
     pub mod moves;
     pub mod entry;
     pub mod effect;
+    pub mod reachable;
 }
 
 pub mod front {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 3194df269c0..548eebaea0b 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -488,7 +488,9 @@ pub fn parameterized(cx: ctxt,
         }
     };
 
-    strs += vec::map(tps, |t| ty_to_str(cx, *t));
+    for tps.iter().advance |t| {
+        strs.push(ty_to_str(cx, *t))
+    }
 
     if strs.len() > 0u {
         fmt!("%s<%s>", base, strs.connect(","))
@@ -575,8 +577,8 @@ impl Repr for ty::ParamBounds {
             res.push(match b {
                 ty::BoundCopy => ~"Copy",
                 ty::BoundStatic => ~"'static",
-                ty::BoundOwned => ~"Owned",
-                ty::BoundConst => ~"Const",
+                ty::BoundSend => ~"Send",
+                ty::BoundFreeze => ~"Freeze",
                 ty::BoundSized => ~"Sized",
             });
         }
@@ -781,8 +783,8 @@ impl UserString for ty::BuiltinBound {
         match *self {
             ty::BoundCopy => ~"Copy",
             ty::BoundStatic => ~"'static",
-            ty::BoundOwned => ~"Owned",
-            ty::BoundConst => ~"Const",
+            ty::BoundSend => ~"Send",
+            ty::BoundFreeze => ~"Freeze",
             ty::BoundSized => ~"Sized",
         }
     }
diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs
index 3775aafb569..27ab3aca020 100644
--- a/src/librustdoc/astsrv.rs
+++ b/src/librustdoc/astsrv.rs
@@ -99,7 +99,7 @@ fn act(po: &Port<Msg>, source: @str, parse: Parser) {
     }
 }
 
-pub fn exec<T:Owned>(
+pub fn exec<T:Send>(
     srv: Srv,
     f: ~fn(ctxt: Ctxt) -> T
 ) -> T {
diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs
index 1c34007c99d..a2e50d37fb6 100644
--- a/src/librustdoc/attr_pass.rs
+++ b/src/librustdoc/attr_pass.rs
@@ -101,7 +101,7 @@ fn fold_item(
     }
 }
 
-fn parse_item_attrs<T:Owned>(
+fn parse_item_attrs<T:Send>(
     srv: astsrv::Srv,
     id: doc::AstId,
     parse_attrs: ~fn(a: ~[ast::attribute]) -> T) -> T {
diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs
index 6622ea1551b..e9deef6b223 100644
--- a/src/librustdoc/markdown_pass.rs
+++ b/src/librustdoc/markdown_pass.rs
@@ -152,7 +152,7 @@ pub fn header_kind(doc: doc::ItemTag) -> ~str {
             ~"Function"
         }
         doc::ConstTag(_) => {
-            ~"Const"
+            ~"Freeze"
         }
         doc::EnumTag(_) => {
             ~"Enum"
@@ -192,11 +192,11 @@ pub fn header_name(doc: doc::ItemTag) -> ~str {
             let mut trait_part = ~"";
             for doc.trait_types.iter().enumerate().advance |(i, trait_type)| {
                 if i == 0 {
-                    trait_part += " of ";
+                    trait_part.push_str(" of ");
                 } else {
-                    trait_part += ", ";
+                    trait_part.push_str(", ");
                 }
-                trait_part += *trait_type;
+                trait_part.push_str(*trait_type);
             }
             fmt!("%s for %s%s", trait_part, *self_ty, bounds)
         }
@@ -786,7 +786,7 @@ mod test {
     #[test]
     fn should_write_const_header() {
         let markdown = render(~"static a: bool = true;");
-        assert!(markdown.contains("## Const `a`\n\n"));
+        assert!(markdown.contains("## Freeze `a`\n\n"));
     }
 
     #[test]
diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs
index 35315276326..a093824e453 100644
--- a/src/librustdoc/markdown_writer.rs
+++ b/src/librustdoc/markdown_writer.rs
@@ -130,7 +130,7 @@ fn generic_writer(process: ~fn(markdown: ~str)) -> Writer {
         let mut keep_going = true;
         while keep_going {
             match po.recv() {
-              Write(s) => markdown += s,
+              Write(s) => markdown.push_str(s),
               Done => keep_going = false
             }
         }
@@ -214,7 +214,7 @@ fn future_writer() -> (Writer, future::Future<~str>) {
         let mut res = ~"";
         loop {
             match port.recv() {
-              Write(s) => res += s,
+              Write(s) => res.push_str(s),
               Done => break
             }
         }
diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs
index 584e6ccc887..35a433ec9de 100644
--- a/src/librustdoc/page_pass.rs
+++ b/src/librustdoc/page_pass.rs
@@ -70,7 +70,7 @@ fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc {
     loop {
         let val = page_port.recv();
         if val.is_some() {
-            pages += [val.unwrap()];
+            pages.push(val.unwrap());
         } else {
             break;
         }
diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc
new file mode 100644
index 00000000000..5873f361ad7
--- /dev/null
+++ b/src/librusti/rusti.rc
@@ -0,0 +1,666 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * rusti - A REPL using the JIT backend
+ *
+ * Rusti works by serializing state between lines of input. This means that each
+ * line can be run in a separate task, and the only limiting factor is that all
+ * local bound variables are encodable.
+ *
+ * This is accomplished by feeding in generated input to rustc for execution in
+ * the JIT compiler. Currently input actually gets fed in three times to get
+ * information about the program.
+ *
+ * - Pass #1
+ *   In this pass, the input is simply thrown at the parser and the input comes
+ *   back. This validates the structure of the program, and at this stage the
+ *   global items (fns, structs, impls, traits, etc.) are filtered from the
+ *   input into the "global namespace". These declarations shadow all previous
+ *   declarations of an item by the same name.
+ *
+ * - Pass #2
+ *   After items have been stripped, the remaining input is passed to rustc
+ *   along with all local variables declared (initialized to nothing). This pass
+ *   runs up to typechecking. From this, we can learn about the types of each
+ *   bound variable, what variables are bound, and also ensure that all the
+ *   types are encodable (the input can actually be run).
+ *
+ * - Pass #3
+ *   Finally, a program is generated to deserialize the local variable state,
+ *   run the code input, and then reserialize all bindings back into a local
+ *   hash map. Once this code runs, the input has fully been run and the REPL
+ *   waits for new input.
+ *
+ * Encoding/decoding is done with EBML, and there is simply a map of ~str ->
+ * ~[u8] maintaining the values of each local binding (by name).
+ */
+
+#[link(name = "rusti",
+       vers = "0.7-pre",
+       uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc",
+       url = "https://github.com/mozilla/rust/tree/master/src/rusti")];
+
+#[license = "MIT/ASL2"];
+#[crate_type = "lib"];
+
+extern mod extra;
+extern mod rustc;
+extern mod syntax;
+
+use std::{libc, io, os, task, vec};
+use std::cell::Cell;
+use extra::rl;
+
+use rustc::driver::{driver, session};
+use syntax::{ast, diagnostic};
+use syntax::ast_util::*;
+use syntax::parse::token;
+use syntax::print::pprust;
+
+use program::Program;
+use utils::*;
+
+mod program;
+pub mod utils;
+
+/**
+ * A structure shared across REPL instances for storing history
+ * such as statements and view items. I wish the AST was sendable.
+ */
+pub struct Repl {
+    prompt: ~str,
+    binary: ~str,
+    running: bool,
+    lib_search_paths: ~[~str],
+
+    program: Program,
+}
+
+// Action to do after reading a :command
+enum CmdAction {
+    action_none,
+    action_run_line(~str),
+}
+
+/// Run an input string in a Repl, returning the new Repl.
+fn run(mut repl: Repl, input: ~str) -> Repl {
+    // Build some necessary rustc boilerplate for compiling things
+    let binary = repl.binary.to_managed();
+    let options = @session::options {
+        crate_type: session::unknown_crate,
+        binary: binary,
+        addl_lib_search_paths: @mut repl.lib_search_paths.map(|p| Path(*p)),
+        jit: true,
+        .. copy *session::basic_options()
+    };
+    // Because we assume that everything is encodable (and assert so), add some
+    // extra helpful information if the error crops up. Otherwise people are
+    // bound to be very confused when they find out code is running that they
+    // never typed in...
+    let sess = driver::build_session(options, |cm, msg, lvl| {
+        diagnostic::emit(cm, msg, lvl);
+        if msg.contains("failed to find an implementation of trait") &&
+           msg.contains("extra::serialize::Encodable") {
+            diagnostic::emit(cm,
+                             "Currrently rusti serializes bound locals between \
+                              different lines of input. This means that all \
+                              values of local variables need to be encodable, \
+                              and this type isn't encodable",
+                             diagnostic::note);
+        }
+    });
+    let intr = token::get_ident_interner();
+
+    //
+    // Stage 1: parse the input and filter it into the program (as necessary)
+    //
+    debug!("parsing: %s", input);
+    let crate = parse_input(sess, binary, input);
+    let mut to_run = ~[];       // statements to run (emitted back into code)
+    let new_locals = @mut ~[];  // new locals being defined
+    let mut result = None;      // resultant expression (to print via pp)
+    do find_main(crate, sess) |blk| {
+        // Fish out all the view items, be sure to record 'extern mod' items
+        // differently beause they must appear before all 'use' statements
+        for blk.node.view_items.iter().advance |vi| {
+            let s = do with_pp(intr) |pp, _| {
+                pprust::print_view_item(pp, *vi);
+            };
+            match vi.node {
+                ast::view_item_extern_mod(*) => {
+                    repl.program.record_extern(s);
+                }
+                ast::view_item_use(*) => { repl.program.record_view_item(s); }
+            }
+        }
+
+        // Iterate through all of the block's statements, inserting them into
+        // the correct portions of the program
+        for blk.node.stmts.iter().advance |stmt| {
+            let s = do with_pp(intr) |pp, _| { pprust::print_stmt(pp, *stmt); };
+            match stmt.node {
+                ast::stmt_decl(d, _) => {
+                    match d.node {
+                        ast::decl_item(it) => {
+                            let name = sess.str_of(it.ident);
+                            match it.node {
+                                // Structs are treated specially because to make
+                                // them at all usable they need to be decorated
+                                // with #[deriving(Encoable, Decodable)]
+                                ast::item_struct(*) => {
+                                    repl.program.record_struct(name, s);
+                                }
+                                // Item declarations are hoisted out of main()
+                                _ => { repl.program.record_item(name, s); }
+                            }
+                        }
+
+                        // Local declarations must be specially dealt with,
+                        // record all local declarations for use later on
+                        ast::decl_local(l) => {
+                            let mutbl = l.node.is_mutbl;
+                            do each_binding(l) |path, _| {
+                                let s = do with_pp(intr) |pp, _| {
+                                    pprust::print_path(pp, path, false);
+                                };
+                                new_locals.push((s, mutbl));
+                            }
+                            to_run.push(s);
+                        }
+                    }
+                }
+
+                // run statements with expressions (they have effects)
+                ast::stmt_mac(*) | ast::stmt_semi(*) | ast::stmt_expr(*) => {
+                    to_run.push(s);
+                }
+            }
+        }
+        result = do blk.node.expr.map_consume |e| {
+            do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); }
+        };
+    }
+    // return fast for empty inputs
+    if to_run.len() == 0 && result.is_none() {
+        return repl;
+    }
+
+    //
+    // Stage 2: run everything up to typeck to learn the types of the new
+    //          variables introduced into the program
+    //
+    info!("Learning about the new types in the program");
+    repl.program.set_cache(); // before register_new_vars (which changes them)
+    let input = to_run.connect("\n");
+    let test = repl.program.test_code(input, &result, *new_locals);
+    debug!("testing with ^^^^^^ %?", (||{ println(test) })());
+    let dinput = driver::str_input(test.to_managed());
+    let cfg = driver::build_configuration(sess, binary, &dinput);
+    let outputs = driver::build_output_filenames(&dinput, &None, &None, [], sess);
+    let (crate, tcx) = driver::compile_upto(sess, copy cfg, &dinput,
+                                            driver::cu_typeck, Some(outputs));
+    // Once we're typechecked, record the types of all local variables defined
+    // in this input
+    do find_main(crate.expect("crate after cu_typeck"), sess) |blk| {
+        repl.program.register_new_vars(blk, tcx.expect("tcx after cu_typeck"));
+    }
+
+    //
+    // Stage 3: Actually run the code in the JIT
+    //
+    info!("actually running code");
+    let code = repl.program.code(input, &result);
+    debug!("actually running ^^^^^^ %?", (||{ println(code) })());
+    let input = driver::str_input(code.to_managed());
+    let cfg = driver::build_configuration(sess, binary, &input);
+    let outputs = driver::build_output_filenames(&input, &None, &None, [], sess);
+    let sess = driver::build_session(options, diagnostic::emit);
+    driver::compile_upto(sess, cfg, &input, driver::cu_everything,
+                         Some(outputs));
+
+    //
+    // Stage 4: Inform the program that computation is done so it can update all
+    //          local variable bindings.
+    //
+    info!("cleaning up after code");
+    repl.program.consume_cache();
+
+    return repl;
+
+    fn parse_input(sess: session::Session, binary: @str,
+                   input: &str) -> @ast::crate {
+        let code = fmt!("fn main() {\n %s \n}", input);
+        let input = driver::str_input(code.to_managed());
+        let cfg = driver::build_configuration(sess, binary, &input);
+        let outputs = driver::build_output_filenames(&input, &None, &None, [], sess);
+        let (crate, _) = driver::compile_upto(sess, cfg, &input,
+                                              driver::cu_parse, Some(outputs));
+        crate.expect("parsing should return a crate")
+    }
+
+    fn find_main(crate: @ast::crate, sess: session::Session,
+                 f: &fn(&ast::blk)) {
+        for crate.node.module.items.iter().advance |item| {
+            match item.node {
+                ast::item_fn(_, _, _, _, ref blk) => {
+                    if item.ident == sess.ident_of("main") {
+                        return f(blk);
+                    }
+                }
+                _ => {}
+            }
+        }
+        fail!("main function was expected somewhere...");
+    }
+}
+
+// Compiles a crate given by the filename as a library if the compiled
+// version doesn't exist or is older than the source file. Binary is
+// the name of the compiling executable. Returns Some(true) if it
+// successfully compiled, Some(false) if the crate wasn't compiled
+// because it already exists and is newer than the source file, or
+// None if there were compile errors.
+fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
+    match do task::try {
+        let src_path = Path(src_filename);
+        let binary = binary.to_managed();
+        let options = @session::options {
+            binary: binary,
+            addl_lib_search_paths: @mut ~[os::getcwd()],
+            .. copy *session::basic_options()
+        };
+        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 outputs = driver::build_output_filenames(
+            &input, &None, &None, [], sess);
+        // If the library already exists and is newer than the source
+        // file, skip compilation and return None.
+        let mut should_compile = true;
+        let dir = os::list_dir_path(&Path(outputs.out_filename.dirname()));
+        let maybe_lib_path = do dir.iter().find_ |file| {
+            // The actual file's name has a hash value and version
+            // number in it which is unknown at this time, so looking
+            // for a file that matches out_filename won't work,
+            // instead we guess which file is the library by matching
+            // the prefix and suffix of out_filename to files in the
+            // directory.
+            let file_str = file.filename().get();
+            file_str.starts_with(outputs.out_filename.filestem().get())
+                && file_str.ends_with(outputs.out_filename.filetype().get())
+        };
+        match maybe_lib_path {
+            Some(lib_path) => {
+                let (src_mtime, _) = src_path.get_mtime().get();
+                let (lib_mtime, _) = lib_path.get_mtime().get();
+                if lib_mtime >= src_mtime {
+                    should_compile = false;
+                }
+            },
+            None => { },
+        }
+        if (should_compile) {
+            println(fmt!("compiling %s...", src_filename));
+            driver::compile_upto(sess, cfg, &input, driver::cu_everything,
+                                 Some(outputs));
+            true
+        } else { false }
+    } {
+        Ok(true) => Some(true),
+        Ok(false) => Some(false),
+        Err(_) => None,
+    }
+}
+
+/// 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> {
+    if use_rl {
+        let result = unsafe { rl::read(prompt) };
+
+        match result {
+            None => None,
+            Some(line) => {
+                unsafe { rl::add_history(line) };
+                Some(line)
+            }
+        }
+    } else {
+        if io::stdin().eof() {
+            None
+        } else {
+            Some(io::stdin().read_line())
+        }
+    }
+}
+
+/// Run a command, e.g. :clear, :exit, etc.
+fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
+           cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction {
+    let mut action = action_none;
+    match cmd {
+        ~"exit" => repl.running = false,
+        ~"clear" => {
+            repl.program.clear();
+
+            // XXX: Win32 version of linenoise can't do this
+            //rl::clear();
+        }
+        ~"help" => {
+            println(
+                ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\
+                 :load <crate> ... - loads given crates as dynamic libraries\n\
+                 :clear - clear the bindings\n\
+                 :exit - exit from the repl\n\
+                 :help - show this message");
+        }
+        ~"load" => {
+            let mut loaded_crates: ~[~str] = ~[];
+            for args.iter().advance |arg| {
+                let (crate, filename) =
+                    if arg.ends_with(".rs") || arg.ends_with(".rc") {
+                    (arg.slice_to(arg.len() - 3).to_owned(), copy *arg)
+                } else {
+                    (copy *arg, *arg + ".rs")
+                };
+                match compile_crate(filename, copy repl.binary) {
+                    Some(_) => loaded_crates.push(crate),
+                    None => { }
+                }
+            }
+            for loaded_crates.iter().advance |crate| {
+                let crate_path = Path(*crate);
+                let crate_dir = crate_path.dirname();
+                repl.program.record_extern(fmt!("extern mod %s;", *crate));
+                if !repl.lib_search_paths.iter().any_(|x| x == &crate_dir) {
+                    repl.lib_search_paths.push(crate_dir);
+                }
+            }
+            if loaded_crates.is_empty() {
+                println("no crates loaded");
+            } else {
+                println(fmt!("crates loaded: %s",
+                                 loaded_crates.connect(", ")));
+            }
+        }
+        ~"{" => {
+            let mut multiline_cmd = ~"";
+            let mut end_multiline = false;
+            while (!end_multiline) {
+                match get_line(use_rl, "rusti| ") {
+                    None => fail!("unterminated multiline command :{ .. :}"),
+                    Some(line) => {
+                        if line.trim() == ":}" {
+                            end_multiline = true;
+                        } else {
+                            multiline_cmd.push_str(line);
+                            multiline_cmd.push_char('\n');
+                        }
+                    }
+                }
+            }
+            action = action_run_line(multiline_cmd);
+        }
+        _ => println(~"unknown cmd: " + cmd)
+    }
+    return action;
+}
+
+/// Executes a line of input, which may either be rust code or a
+/// :command. Returns a new Repl if it has changed.
+pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
+                use_rl: bool)
+    -> Option<Repl> {
+    if line.starts_with(":") {
+        // drop the : and the \n (one byte each)
+        let full = line.slice(1, line.len());
+        let split: ~[~str] = full.word_iter().transform(|s| s.to_owned()).collect();
+        let len = split.len();
+
+        if len > 0 {
+            let cmd = copy split[0];
+
+            if !cmd.is_empty() {
+                let args = if len > 1 {
+                    vec::slice(split, 1, len).to_owned()
+                } else { ~[] };
+
+                match run_cmd(repl, in, out, cmd, args, use_rl) {
+                    action_none => { }
+                    action_run_line(multiline_cmd) => {
+                        if !multiline_cmd.is_empty() {
+                            return run_line(repl, in, out, multiline_cmd, use_rl);
+                        }
+                    }
+                }
+                return None;
+            }
+        }
+    }
+
+    let line = Cell::new(line);
+    let r = Cell::new(copy *repl);
+    let result = do task::try {
+        run(r.take(), line.take())
+    };
+
+    if result.is_ok() {
+        return Some(result.get());
+    }
+    return None;
+}
+
+pub fn main() {
+    let args = os::args();
+    let in = io::stdin();
+    let out = io::stdout();
+    let mut repl = Repl {
+        prompt: ~"rusti> ",
+        binary: copy args[0],
+        running: true,
+        lib_search_paths: ~[],
+
+        program: Program::new(),
+    };
+
+    let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
+
+    // only print this stuff if the user is actually typing into rusti
+    if istty {
+        println("WARNING: The Rust REPL is experimental and may be");
+        println("unstable. If you encounter problems, please use the");
+        println("compiler instead. Type :help for help.");
+
+        unsafe {
+            do rl::complete |line, suggest| {
+                if line.starts_with(":") {
+                    suggest(~":clear");
+                    suggest(~":exit");
+                    suggest(~":help");
+                    suggest(~":load");
+                }
+            }
+        }
+    }
+
+    while repl.running {
+        match get_line(istty, repl.prompt) {
+            None => break,
+            Some(line) => {
+                if line.is_empty() {
+                    if istty {
+                        println("()");
+                    }
+                    loop;
+                }
+                match run_line(&mut repl, in, out, line, istty) {
+                    Some(new_repl) => repl = new_repl,
+                    None => { }
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::io;
+    use std::iterator::IteratorUtil;
+    use program::Program;
+    use super::*;
+
+    fn repl() -> Repl {
+        Repl {
+            prompt: ~"rusti> ",
+            binary: ~"rusti",
+            running: true,
+            lib_search_paths: ~[],
+            program: Program::new(),
+        }
+    }
+
+    fn run_program(prog: &str) {
+        let mut r = repl();
+        for prog.split_iter('\n').advance |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]
+    // FIXME: #7220 rusti on 32bit mac doesn't work.
+    #[cfg(not(target_word_size="32",
+              target_os="macos"))]
+    fn run_all() {
+        // FIXME(#7071):
+        // 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_program("");
+
+        debug!("regression test for #5937");
+        run_program("use std::hashmap;");
+
+        debug!("regression test for #5784");
+        run_program("let a = 3;");
+
+        // XXX: can't spawn new tasks because the JIT code is cleaned up
+        //      after the main function is done.
+        // debug!("regression test for #5803");
+        // run_program("
+        //     spawn( || println(\"Please don't segfault\") );
+        //     do spawn { println(\"Please?\"); }
+        // ");
+
+        debug!("inferred integers are usable");
+        run_program("let a = 2;\n()\n");
+        run_program("
+            let a = 3;
+            let b = 4u;
+            assert!((a as uint) + b == 7)
+        ");
+
+        debug!("local variables can be shadowed");
+        run_program("
+            let a = 3;
+            let a = 5;
+            assert!(a == 5)
+        ");
+
+        debug!("strings are usable");
+        run_program("
+            let a = ~\"\";
+            let b = \"\";
+            let c = @\"\";
+            let d = a + b + c;
+            assert!(d.len() == 0);
+        ");
+
+        debug!("vectors are usable");
+        run_program("
+            let a = ~[1, 2, 3];
+            let b = &[1, 2, 3];
+            let c = @[1, 2, 3];
+            let d = a + b + c;
+            assert!(d.len() == 9);
+            let e: &[int] = [];
+        ");
+
+        debug!("structs are usable");
+        run_program("
+            struct A{ a: int }
+            let b = A{ a: 3 };
+            assert!(b.a == 3)
+        ");
+
+        debug!("mutable variables");
+        run_program("
+            let mut a = 3;
+            a = 5;
+            let mut b = std::hashmap::HashSet::new::<int>();
+            b.insert(a);
+            assert!(b.contains(&5))
+            assert!(b.len() == 1)
+        ");
+
+        debug!("functions are cached");
+        run_program("
+            fn fib(x: int) -> int { if x < 2 {x} else { fib(x - 1) + fib(x - 2) } }
+            let a = fib(3);
+            let a = a + fib(4);
+            assert!(a == 5)
+        ");
+
+        debug!("modules are cached");
+        run_program("
+            mod b { pub fn foo() -> uint { 3 } }
+            assert!(b::foo() == 3)
+        ");
+
+        debug!("multiple function definitions are allowed");
+        run_program("
+            fn f() {}
+            fn f() {}
+            f()
+        ");
+
+        debug!("multiple item definitions are allowed");
+        run_program("
+            fn f() {}
+            mod f {}
+            struct f;
+            enum f {}
+            fn f() {}
+            f()
+        ");
+    }
+
+    #[test]
+    // FIXME: #7220 rusti on 32bit mac doesn't work.
+    #[cfg(not(target_word_size="32",
+              target_os="macos"))]
+    fn exit_quits() {
+        let mut r = repl();
+        assert!(r.running);
+        let result = run_line(&mut r, io::stdin(), io::stdout(),
+                              ~":exit", false);
+        assert!(result.is_none());
+        assert!(!r.running);
+    }
+}
diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs
index 54a404d971e..abb0cf271ec 100644
--- a/src/librusti/rusti.rs
+++ b/src/librusti/rusti.rs
@@ -55,7 +55,7 @@ extern mod extra;
 extern mod rustc;
 extern mod syntax;
 
-use std::{libc, io, os, task, vec};
+use std::{libc, io, os, task};
 use std::cell::Cell;
 use extra::rl;
 
@@ -402,7 +402,8 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
                         if line.trim() == ":}" {
                             end_multiline = true;
                         } else {
-                            multiline_cmd += line + "\n";
+                            multiline_cmd.push_str(line);
+                            multiline_cmd.push_char('\n');
                         }
                     }
                 }
@@ -430,7 +431,7 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str,
 
             if !cmd.is_empty() {
                 let args = if len > 1 {
-                    vec::slice(split, 1, len).to_owned()
+                    split.slice(1, len).to_owned()
                 } else { ~[] };
 
                 match run_cmd(repl, in, out, cmd, args, use_rl) {
diff --git a/src/librustpkg/package_source.rs b/src/librustpkg/package_source.rs
index 9b727e9d3e0..ebdea2537ac 100644
--- a/src/librustpkg/package_source.rs
+++ b/src/librustpkg/package_source.rs
@@ -12,7 +12,7 @@ use target::*;
 use package_id::PkgId;
 use core::path::Path;
 use core::option::*;
-use core::{os, run, str, vec};
+use core::{os, run, str};
 use context::*;
 use crate::Crate;
 use messages::*;
@@ -146,8 +146,7 @@ impl PkgSrc {
     fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
         assert!(p.components.len() > prefix);
         let mut sub = Path("");
-        for vec::slice(p.components, prefix,
-                       p.components.len()).iter().advance |c| {
+        for p.components.slice(prefix, p.components.len()).iter().advance |c| {
             sub = sub.push(*c);
         }
         debug!("found crate %s", sub.to_str());
diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs
index 6d146145f36..f0a3f24c307 100644
--- a/src/librustpkg/path_util.rs
+++ b/src/librustpkg/path_util.rs
@@ -22,11 +22,39 @@ use core::iterator::IteratorUtil;
 use messages::*;
 use package_id::*;
 
+fn push_if_exists(vec: &mut ~[Path], p: &Path) {
+    let maybe_dir = p.push(".rust");
+    if os::path_exists(&maybe_dir) {
+        vec.push(maybe_dir);
+    }
+}
+
+#[cfg(windows)]
+static path_entry_separator: &'static str = ";";
+#[cfg(not(windows))]
+static path_entry_separator: &'static str = ":";
+
 /// Returns the value of RUST_PATH, as a list
-/// of Paths. In general this should be read from the
-/// environment; for now, it's hard-wired to just be "."
+/// of Paths. Includes default entries for, if they exist:
+/// $HOME/.rust
+/// DIR/.rust for any DIR that's the current working directory
+/// or an ancestor of it
 pub fn rust_path() -> ~[Path] {
-    ~[Path(".")]
+    let mut env_rust_path: ~[Path] = match os::getenv("RUST_PATH") {
+        Some(env_path) => {
+            let env_path_components: ~[&str] =
+                env_path.split_str_iter(path_entry_separator).collect();
+            env_path_components.map(|&s| Path(s))
+        }
+        None => ~[]
+    };
+    let cwd = os::getcwd();
+    // now add in default entries
+    env_rust_path.push(copy cwd);
+    do cwd.each_parent() |p| { push_if_exists(&mut env_rust_path, p) };
+    let h = os::homedir();
+    for h.iter().advance |h| { push_if_exists(&mut env_rust_path, h); }
+    env_rust_path
 }
 
 pub static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs
index d70428e7338..550a3411b5d 100644
--- a/src/librustpkg/rustpkg.rs
+++ b/src/librustpkg/rustpkg.rs
@@ -185,7 +185,21 @@ impl<'self> PkgScript<'self> {
 
 }
 
-impl Ctx {
+pub trait CtxMethods {
+    fn run(&self, cmd: &str, args: ~[~str]);
+    fn do_cmd(&self, _cmd: &str, _pkgname: &str);
+    fn build(&self, workspace: &Path, pkgid: &PkgId);
+    fn clean(&self, workspace: &Path, id: &PkgId);
+    fn info(&self);
+    fn install(&self, workspace: &Path, id: &PkgId);
+    fn install_no_build(&self, workspace: &Path, id: &PkgId);
+    fn prefer(&self, _id: &str, _vers: Option<~str>);
+    fn test(&self);
+    fn uninstall(&self, _id: &str, _vers: Option<~str>);
+    fn unprefer(&self, _id: &str, _vers: Option<~str>);
+}
+
+impl CtxMethods for Ctx {
 
     fn run(&self, cmd: &str, args: ~[~str]) {
         match cmd {
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index afeb6407533..44a8e696bde 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -12,7 +12,7 @@
 
 use context::Ctx;
 use core::hashmap::HashMap;
-use core::{io, libc, os, result, run, str};
+use core::{io, libc, os, result, run, str, vec};
 use core::prelude::*;
 use extra::tempfile::mkdtemp;
 use core::run::ProcessOutput;
@@ -25,7 +25,7 @@ use path_util::{target_executable_in_workspace, target_library_in_workspace,
                make_dir_rwx, u_rwx, library_in_workspace,
                built_bench_in_workspace, built_test_in_workspace,
                built_library_in_workspace, built_executable_in_workspace,
-                installed_library_in_workspace};
+                installed_library_in_workspace, rust_path};
 use target::*;
 
 /// Returns the last-modified date as an Option
@@ -144,10 +144,10 @@ fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
                                                            err_fd: None
                                                           });
     let output = prog.finish_with_output();
-    io::println(fmt!("Output from command %s with args %? was %s {%s}[%?]",
+    debug!("Output from command %s with args %? was %s {%s}[%?]",
                     cmd, args, str::from_bytes(output.output),
                    str::from_bytes(output.error),
-                   output.status));
+                   output.status);
 /*
 By the way, rustpkg *won't* return a nonzero exit code if it fails --
 see #4547
@@ -248,7 +248,7 @@ fn command_line_test_output(args: &[~str]) -> ~[~str] {
     let p_output = command_line_test(args, &os::getcwd());
     let test_output = str::from_bytes(p_output.output);
     for test_output.split_iter('\n').advance |s| {
-        result += [s.to_owned()];
+        result.push(s.to_owned());
     }
     result
 }
@@ -562,13 +562,58 @@ fn package_script_with_default_build() {
 }
 
 #[test]
-#[ignore (reason = "RUST_PATH not yet implemented -- #5682")]
+#[ignore (reason = "Un-ignore when #7071 is fixed")]
 fn rust_path_test() {
-    let dir = mk_workspace(&Path("/home/more_rust"),
-                           &normalize(RemotePath(Path("foo"))),
-                           &NoVersion);
-  //  command_line_test("RUST_PATH=/home/rust:/home/more_rust rustpkg install foo");
-    command_line_test([~"install", ~"foo"], &dir);
+    let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed");
+    let dir = mk_workspace(&dir_for_path, &normalize(RemotePath(Path("foo"))), &NoVersion);
+    debug!("dir = %s", dir.to_str());
+    writeFile(&Path("/Users/tjc/more_rust/src/foo-0.1/main.rs"),
+              "fn main() { let _x = (); }");
+
+    let cwd = os::getcwd();
+    debug!("cwd = %s", cwd.to_str());
+    let mut prog = run::Process::new("rustpkg",
+                                     [~"install", ~"foo"],
+                                     run::ProcessOptions { env: Some(&[(~"RUST_PATH",
+                                                                       dir_for_path.to_str())]),
+                                                          dir: Some(&cwd),
+                                                          in_fd: None,
+                                                          out_fd: None,
+                                                          err_fd: None
+                                                         });
+    prog.finish_with_output();
+    assert_executable_exists(&dir_for_path, "foo");
+}
+
+#[test]
+fn rust_path_contents() {
+    let dir = mkdtemp(&os::tmpdir(), "rust_path").expect("rust_path_contents failed");
+    let abc = &dir.push("A").push("B").push("C");
+    assert!(os::mkdir_recursive(&abc.push(".rust"), u_rwx));
+    assert!(os::mkdir_recursive(&abc.pop().push(".rust"), u_rwx));
+    assert!(os::mkdir_recursive(&abc.pop().pop().push(".rust"), u_rwx));
+    assert!(do os::change_dir_locked(&dir.push("A").push("B").push("C")) {
+        let p = rust_path();
+        let cwd = os::getcwd().push(".rust");
+        let parent = cwd.pop().pop().push(".rust");
+        let grandparent = cwd.pop().pop().pop().push(".rust");
+        assert!(vec::contains(p, &cwd));
+        assert!(vec::contains(p, &parent));
+        assert!(vec::contains(p, &grandparent));
+        for p.iter().advance() |a_path| {
+            assert!(!a_path.components.is_empty());
+        }
+    });
+}
+
+#[test]
+fn rust_path_parse() {
+    os::setenv("RUST_PATH", "/a/b/c:/d/e/f:/g/h/i");
+    let paths = rust_path();
+    assert!(vec::contains(paths, &Path("/g/h/i")));
+    assert!(vec::contains(paths, &Path("/d/e/f")));
+    assert!(vec::contains(paths, &Path("/a/b/c")));
+    os::unsetenv("RUST_PATH");
 }
 
 #[test]
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 38e6a4824af..cb9bbf80ea8 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -187,7 +187,7 @@ pub fn compile_input(ctxt: &Ctx,
         Lib => lib_crate,
         Test | Bench | Main => bin_crate
     };
-    let matches = getopts(~[~"-Z", ~"time-passes"]
+    let matches = getopts(debug_flags()
                           + match what {
                               Lib => ~[~"--lib"],
                               // --test compiles both #[test] and #[bench] fns
@@ -415,3 +415,7 @@ mod test {
     }
 
 }
+
+// tjc: cheesy
+fn debug_flags() -> ~[~str] { ~[] }
+// static debug_flags: ~[~str] = ~[~"-Z", ~"time-passes"];
\ No newline at end of file
diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs
index e1d2b246dd3..53ea11f2b05 100644
--- a/src/libstd/cell.rs
+++ b/src/libstd/cell.rs
@@ -22,7 +22,8 @@ A dynamic, mutable location.
 Similar to a mutable option type, but friendlier.
 */
 
-#[mutable]
+#[mutable] // XXX remove after snap
+#[no_freeze]
 #[deriving(Clone, DeepClone, Eq)]
 #[allow(missing_doc)]
 pub struct Cell<T> {
diff --git a/src/libstd/char.rs b/src/libstd/char.rs
index 797fd9e8c02..8f0870af513 100644
--- a/src/libstd/char.rs
+++ b/src/libstd/char.rs
@@ -10,6 +10,7 @@
 
 //! Utilities for manipulating the char type
 
+use container::Container;
 use option::{None, Option, Some};
 use str;
 use str::{StrSlice, OwnedStr};
diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs
index 046693632c6..947aa5708c2 100644
--- a/src/libstd/clone.rs
+++ b/src/libstd/clone.rs
@@ -22,7 +22,7 @@ by convention implementing the `Clone` trait and calling the
 
 */
 
-use core::kinds::Const;
+use core::kinds::Freeze;
 
 /// A common trait for cloning an object.
 pub trait Clone {
@@ -112,17 +112,17 @@ impl<T: DeepClone> DeepClone for ~T {
     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
+// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
+impl<T: Freeze + DeepClone> DeepClone for @T {
+    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
     /// a deep clone of a potentially cyclical type.
     #[inline]
     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
+// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
+impl<T: Freeze + DeepClone> DeepClone for @mut T {
+    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
     /// a deep clone of a potentially cyclical type.
     #[inline]
     fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }
diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs
index 7918abe4ae6..8316a33ecf1 100644
--- a/src/libstd/comm.rs
+++ b/src/libstd/comm.rs
@@ -17,7 +17,7 @@ Message passing
 use cast::{transmute, transmute_mut};
 use container::Container;
 use either::{Either, Left, Right};
-use kinds::Owned;
+use kinds::Send;
 use option::{Option, Some, None};
 use uint;
 use vec::OwnedVector;
@@ -77,7 +77,7 @@ pub struct Port<T> {
 These allow sending or receiving an unlimited number of messages.
 
 */
-pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
+pub fn stream<T:Send>() -> (Port<T>, Chan<T>) {
     let (port, chan) = match rt::context() {
         rt::OldTaskContext => match pipesy::stream() {
             (p, c) => (Left(p), Left(c))
@@ -91,7 +91,7 @@ pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
     return (port, chan);
 }
 
-impl<T: Owned> GenericChan<T> for Chan<T> {
+impl<T: Send> GenericChan<T> for Chan<T> {
     fn send(&self, x: T) {
         match self.inner {
             Left(ref chan) => chan.send(x),
@@ -100,7 +100,7 @@ impl<T: Owned> GenericChan<T> for Chan<T> {
     }
 }
 
-impl<T: Owned> GenericSmartChan<T> for Chan<T> {
+impl<T: Send> GenericSmartChan<T> for Chan<T> {
     fn try_send(&self, x: T) -> bool {
         match self.inner {
             Left(ref chan) => chan.try_send(x),
@@ -109,7 +109,7 @@ impl<T: Owned> GenericSmartChan<T> for Chan<T> {
     }
 }
 
-impl<T: Owned> GenericPort<T> for Port<T> {
+impl<T: Send> GenericPort<T> for Port<T> {
     fn recv(&self) -> T {
         match self.inner {
             Left(ref port) => port.recv(),
@@ -125,7 +125,7 @@ impl<T: Owned> GenericPort<T> for Port<T> {
     }
 }
 
-impl<T: Owned> Peekable<T> for Port<T> {
+impl<T: Send> Peekable<T> for Port<T> {
     fn peek(&self) -> bool {
         match self.inner {
             Left(ref port) => port.peek(),
@@ -134,7 +134,7 @@ impl<T: Owned> Peekable<T> for Port<T> {
     }
 }
 
-impl<T: Owned> Selectable for Port<T> {
+impl<T: Send> Selectable for Port<T> {
     fn header(&mut self) -> *mut PacketHeader {
         match self.inner {
             Left(ref mut port) => port.header(),
@@ -149,7 +149,7 @@ pub struct PortSet<T> {
     ports: ~[pipesy::Port<T>],
 }
 
-impl<T: Owned> PortSet<T> {
+impl<T: Send> PortSet<T> {
     pub fn new() -> PortSet<T> {
         PortSet {
             ports: ~[]
@@ -175,7 +175,7 @@ impl<T: Owned> PortSet<T> {
     }
 }
 
-impl<T:Owned> GenericPort<T> for PortSet<T> {
+impl<T:Send> GenericPort<T> for PortSet<T> {
     fn try_recv(&self) -> Option<T> {
         unsafe {
             let self_ports = transmute_mut(&self.ports);
@@ -204,7 +204,7 @@ impl<T:Owned> GenericPort<T> for PortSet<T> {
     }
 }
 
-impl<T: Owned> Peekable<T> for PortSet<T> {
+impl<T: Send> Peekable<T> for PortSet<T> {
     fn peek(&self) -> bool {
         // It'd be nice to use self.port.each, but that version isn't
         // pure.
@@ -223,7 +223,7 @@ pub struct SharedChan<T> {
     ch: Exclusive<pipesy::Chan<T>>
 }
 
-impl<T: Owned> SharedChan<T> {
+impl<T: Send> SharedChan<T> {
     /// Converts a `chan` into a `shared_chan`.
     pub fn new(c: Chan<T>) -> SharedChan<T> {
         let Chan { inner } = c;
@@ -235,7 +235,7 @@ impl<T: Owned> SharedChan<T> {
     }
 }
 
-impl<T: Owned> GenericChan<T> for SharedChan<T> {
+impl<T: Send> GenericChan<T> for SharedChan<T> {
     fn send(&self, x: T) {
         unsafe {
             let mut xx = Some(x);
@@ -247,7 +247,7 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> {
     }
 }
 
-impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
+impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
     fn try_send(&self, x: T) -> bool {
         unsafe {
             let mut xx = Some(x);
@@ -259,7 +259,7 @@ impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
     }
 }
 
-impl<T: Owned> ::clone::Clone for SharedChan<T> {
+impl<T: Send> ::clone::Clone for SharedChan<T> {
     fn clone(&self) -> SharedChan<T> {
         SharedChan { ch: self.ch.clone() }
     }
@@ -273,7 +273,7 @@ pub struct ChanOne<T> {
     inner: Either<pipesy::ChanOne<T>, rtcomm::ChanOne<T>>
 }
 
-pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
+pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
     let (port, chan) = match rt::context() {
         rt::OldTaskContext => match pipesy::oneshot() {
             (p, c) => (Left(p), Left(c)),
@@ -287,7 +287,7 @@ pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
     return (port, chan);
 }
 
-impl<T: Owned> PortOne<T> {
+impl<T: Send> PortOne<T> {
     pub fn recv(self) -> T {
         let PortOne { inner } = self;
         match inner {
@@ -305,7 +305,7 @@ impl<T: Owned> PortOne<T> {
     }
 }
 
-impl<T: Owned> ChanOne<T> {
+impl<T: Send> ChanOne<T> {
     pub fn send(self, data: T) {
         let ChanOne { inner } = self;
         match inner {
@@ -323,7 +323,7 @@ impl<T: Owned> ChanOne<T> {
     }
 }
 
-pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
+pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
     let PortOne { inner } = port;
     match inner {
         Left(p) => pipesy::recv_one(p),
@@ -331,7 +331,7 @@ pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
     }
 }
 
-pub fn try_recv_one<T: Owned>(port: PortOne<T>) -> Option<T> {
+pub fn try_recv_one<T: Send>(port: PortOne<T>) -> Option<T> {
     let PortOne { inner } = port;
     match inner {
         Left(p) => pipesy::try_recv_one(p),
@@ -339,7 +339,7 @@ pub fn try_recv_one<T: Owned>(port: PortOne<T>) -> Option<T> {
     }
 }
 
-pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
+pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
     let ChanOne { inner } = chan;
     match inner {
         Left(c) => pipesy::send_one(c, data),
@@ -347,7 +347,7 @@ pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
     }
 }
 
-pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
+pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T) -> bool {
     let ChanOne { inner } = chan;
     match inner {
         Left(c) => pipesy::try_send_one(c, data),
@@ -357,7 +357,7 @@ pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
 
 mod pipesy {
 
-    use kinds::Owned;
+    use kinds::Send;
     use option::{Option, Some, None};
     use pipes::{recv, try_recv, peek, PacketHeader};
     use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable};
@@ -365,17 +365,17 @@ mod pipesy {
     use util::replace;
 
     /*proto! oneshot (
-        Oneshot:send<T:Owned> {
+        Oneshot:send<T:Send> {
             send(T) -> !
         }
     )*/
 
     #[allow(non_camel_case_types)]
     pub mod oneshot {
-        priv use core::kinds::Owned;
+        priv use core::kinds::Send;
         use ptr::to_mut_unsafe_ptr;
 
-        pub fn init<T: Owned>() -> (server::Oneshot<T>, client::Oneshot<T>) {
+        pub fn init<T: Send>() -> (server::Oneshot<T>, client::Oneshot<T>) {
             pub use core::pipes::HasBuffer;
 
             let buffer = ~::core::pipes::Buffer {
@@ -399,10 +399,10 @@ mod pipesy {
         #[allow(non_camel_case_types)]
         pub mod client {
 
-            priv use core::kinds::Owned;
+            priv use core::kinds::Send;
 
             #[allow(non_camel_case_types)]
-            pub fn try_send<T: Owned>(pipe: Oneshot<T>, x_0: T) ->
+            pub fn try_send<T: Send>(pipe: Oneshot<T>, x_0: T) ->
                 ::core::option::Option<()> {
                 {
                     use super::send;
@@ -414,7 +414,7 @@ mod pipesy {
             }
 
             #[allow(non_camel_case_types)]
-            pub fn send<T: Owned>(pipe: Oneshot<T>, x_0: T) {
+            pub fn send<T: Send>(pipe: Oneshot<T>, x_0: T) {
                 {
                     use super::send;
                     let message = send(x_0);
@@ -464,12 +464,12 @@ mod pipesy {
     }
 
     /// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
-    pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
+    pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
         let (port, chan) = oneshot::init();
         (PortOne::new(port), ChanOne::new(chan))
     }
 
-    impl<T: Owned> PortOne<T> {
+    impl<T: Send> PortOne<T> {
         pub fn recv(self) -> T { recv_one(self) }
         pub fn try_recv(self) -> Option<T> { try_recv_one(self) }
         pub fn unwrap(self) -> oneshot::server::Oneshot<T> {
@@ -479,7 +479,7 @@ mod pipesy {
         }
     }
 
-    impl<T: Owned> ChanOne<T> {
+    impl<T: Send> ChanOne<T> {
         pub fn send(self, data: T) { send_one(self, data) }
         pub fn try_send(self, data: T) -> bool { try_send_one(self, data) }
         pub fn unwrap(self) -> oneshot::client::Oneshot<T> {
@@ -493,7 +493,7 @@ mod pipesy {
     * Receive a message from a oneshot pipe, failing if the connection was
     * closed.
     */
-    pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
+    pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
         match port {
             PortOne { contents: port } => {
                 let oneshot::send(message) = recv(port);
@@ -503,7 +503,7 @@ mod pipesy {
     }
 
     /// Receive a message from a oneshot pipe unless the connection was closed.
-    pub fn try_recv_one<T: Owned> (port: PortOne<T>) -> Option<T> {
+    pub fn try_recv_one<T: Send> (port: PortOne<T>) -> Option<T> {
         match port {
             PortOne { contents: port } => {
                 let message = try_recv(port);
@@ -519,7 +519,7 @@ mod pipesy {
     }
 
     /// Send a message on a oneshot pipe, failing if the connection was closed.
-    pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
+    pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
         match chan {
             ChanOne { contents: chan } => oneshot::client::send(chan, data),
         }
@@ -529,7 +529,7 @@ mod pipesy {
     * Send a message on a oneshot pipe, or return false if the connection was
     * closed.
     */
-    pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
+    pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T) -> bool {
         match chan {
             ChanOne { contents: chan } => {
                 oneshot::client::try_send(chan, data).is_some()
@@ -540,16 +540,16 @@ mod pipesy {
     // Streams - Make pipes a little easier in general.
 
     /*proto! streamp (
-        Open:send<T: Owned> {
+        Open:send<T: Send> {
             data(T) -> Open<T>
         }
     )*/
 
     #[allow(non_camel_case_types)]
     pub mod streamp {
-        priv use core::kinds::Owned;
+        priv use core::kinds::Send;
 
-        pub fn init<T: Owned>() -> (server::Open<T>, client::Open<T>) {
+        pub fn init<T: Send>() -> (server::Open<T>, client::Open<T>) {
             pub use core::pipes::HasBuffer;
             ::core::pipes::entangle()
         }
@@ -559,10 +559,10 @@ mod pipesy {
 
         #[allow(non_camel_case_types)]
         pub mod client {
-            priv use core::kinds::Owned;
+            priv use core::kinds::Send;
 
             #[allow(non_camel_case_types)]
-            pub fn try_data<T: Owned>(pipe: Open<T>, x_0: T) ->
+            pub fn try_data<T: Send>(pipe: Open<T>, x_0: T) ->
                 ::core::option::Option<Open<T>> {
                 {
                     use super::data;
@@ -575,7 +575,7 @@ mod pipesy {
             }
 
             #[allow(non_camel_case_types)]
-            pub fn data<T: Owned>(pipe: Open<T>, x_0: T) -> Open<T> {
+            pub fn data<T: Send>(pipe: Open<T>, x_0: T) -> Open<T> {
                 {
                     use super::data;
                     let (s, c) = ::core::pipes::entangle();
@@ -613,7 +613,7 @@ mod pipesy {
     These allow sending or receiving an unlimited number of messages.
 
     */
-    pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
+    pub fn stream<T:Send>() -> (Port<T>, Chan<T>) {
         let (s, c) = streamp::init();
 
         (Port {
@@ -623,7 +623,7 @@ mod pipesy {
         })
     }
 
-    impl<T: Owned> GenericChan<T> for Chan<T> {
+    impl<T: Send> GenericChan<T> for Chan<T> {
         #[inline]
         fn send(&self, x: T) {
             unsafe {
@@ -634,7 +634,7 @@ mod pipesy {
         }
     }
 
-    impl<T: Owned> GenericSmartChan<T> for Chan<T> {
+    impl<T: Send> GenericSmartChan<T> for Chan<T> {
         #[inline]
         fn try_send(&self, x: T) -> bool {
             unsafe {
@@ -651,7 +651,7 @@ mod pipesy {
         }
     }
 
-    impl<T: Owned> GenericPort<T> for Port<T> {
+    impl<T: Send> GenericPort<T> for Port<T> {
         #[inline]
         fn recv(&self) -> T {
             unsafe {
@@ -679,7 +679,7 @@ mod pipesy {
         }
     }
 
-    impl<T: Owned> Peekable<T> for Port<T> {
+    impl<T: Send> Peekable<T> for Port<T> {
         #[inline]
         fn peek(&self) -> bool {
             unsafe {
@@ -695,7 +695,7 @@ mod pipesy {
         }
     }
 
-    impl<T: Owned> Selectable for Port<T> {
+    impl<T: Send> Selectable for Port<T> {
         fn header(&mut self) -> *mut PacketHeader {
             match self.endp {
                 Some(ref mut endp) => endp.header(),
@@ -723,15 +723,15 @@ pub fn select2i<A:Selectable, B:Selectable>(a: &mut A, b: &mut B)
 }
 
 /// Receive a message from one of two endpoints.
-pub trait Select2<T: Owned, U: Owned> {
+pub trait Select2<T: Send, U: Send> {
     /// Receive a message or return `None` if a connection closes.
     fn try_select(&mut self) -> Either<Option<T>, Option<U>>;
     /// Receive a message or fail if a connection closes.
     fn select(&mut self) -> Either<T, U>;
 }
 
-impl<T:Owned,
-     U:Owned,
+impl<T:Send,
+     U:Send,
      Left:Selectable + GenericPort<T>,
      Right:Selectable + GenericPort<U>>
      Select2<T, U>
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
index 8e88bfb4632..6c3fcd41ed3 100644
--- a/src/libstd/hash.rs
+++ b/src/libstd/hash.rs
@@ -24,6 +24,7 @@
 use container::Container;
 use iterator::IteratorUtil;
 use rt::io::Writer;
+use str::OwnedStr;
 use to_bytes::IterBytes;
 use uint;
 use vec::ImmutableVector;
@@ -369,7 +370,7 @@ impl Streaming for SipState {
         let r = self.result_bytes();
         let mut s = ~"";
         for r.iter().advance |b| {
-            s += uint::to_str_radix(*b as uint, 16u);
+            s.push_str(uint::to_str_radix(*b as uint, 16u));
         }
         s
     }
@@ -471,7 +472,7 @@ mod tests {
         fn to_hex_str(r: &[u8, ..8]) -> ~str {
             let mut s = ~"";
             for r.iter().advance |b| {
-                s += uint::to_str_radix(*b as uint, 16u);
+                s.push_str(uint::to_str_radix(*b as uint, 16u));
             }
             s
         }
@@ -492,7 +493,7 @@ mod tests {
 
             assert!(f == i && f == v);
 
-            buf += [t as u8];
+            buf.push(t as u8);
             stream_inc.input([t as u8]);
 
             t += 1;
diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs
index bfa0f2fa124..7f9fb6ad938 100644
--- a/src/libstd/hashmap.rs
+++ b/src/libstd/hashmap.rs
@@ -671,7 +671,7 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
     fn symmetric_difference(&self,
                             other: &HashSet<T>,
                             f: &fn(&T) -> bool) -> bool {
-        self.difference(other, f) && other.difference(self, f)
+        self.difference(other, |t| f(t)) && other.difference(self, |t| f(t))
     }
 
     /// Visit the values representing the intersection
@@ -681,7 +681,8 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
 
     /// Visit the values representing the union
     fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
-        self.iter().advance(f) && other.iter().advance(|v| self.contains(v) || f(v))
+        self.iter().advance(|t| f(t)) &&
+            other.iter().advance(|v| self.contains(v) || f(v))
     }
 }
 
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index a78be9c8b2b..59ac58a514f 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -65,7 +65,7 @@ use str::StrSlice;
 use to_str::ToStr;
 use uint;
 use vec;
-use vec::{ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
+use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
 
 #[allow(non_camel_case_types)] // not sure what to do about this
 pub type fd_t = c_int;
@@ -698,7 +698,7 @@ impl<T:Reader> ReaderUtil for T {
             // over-read by reading 1-byte per char needed
             nbread = if ncreq > nbreq { ncreq } else { nbreq };
             if nbread > 0 {
-                bytes = vec::slice(bytes, offset, bytes.len()).to_owned();
+                bytes = bytes.slice(offset, bytes.len()).to_owned();
             }
         }
         chars
@@ -771,7 +771,9 @@ impl<T:Reader> ReaderUtil for T {
     fn read_le_uint_n(&self, nbytes: uint) -> u64 {
         assert!(nbytes > 0 && nbytes <= 8);
 
-        let mut (val, pos, i) = (0u64, 0, nbytes);
+        let mut val = 0u64;
+        let mut pos = 0;
+        let mut i = nbytes;
         while i > 0 {
             val += (self.read_u8() as u64) << pos;
             pos += 8;
@@ -787,7 +789,8 @@ impl<T:Reader> ReaderUtil for T {
     fn read_be_uint_n(&self, nbytes: uint) -> u64 {
         assert!(nbytes > 0 && nbytes <= 8);
 
-        let mut (val, i) = (0u64, nbytes);
+        let mut val = 0u64;
+        let mut i = nbytes;
         while i > 0 {
             i -= 1;
             val += (self.read_u8() as u64) << i * 8;
@@ -1053,7 +1056,7 @@ impl Reader for BytesReader {
     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
         let count = uint::min(len, self.bytes.len() - *self.pos);
 
-        let view = vec::slice(self.bytes, *self.pos, self.bytes.len());
+        let view = self.bytes.slice(*self.pos, self.bytes.len());
         vec::bytes::copy_memory(bytes, view, count);
 
         *self.pos += count;
@@ -1658,12 +1661,12 @@ impl Writer for BytesWriter {
 
         let bytes = &mut *self.bytes;
         let count = uint::max(bytes.len(), *self.pos + v_len);
-        vec::reserve(bytes, count);
+        bytes.reserve(count);
 
         unsafe {
             vec::raw::set_len(bytes, count);
 
-            let view = vec::mut_slice(*bytes, *self.pos, count);
+            let view = bytes.mut_slice(*self.pos, count);
             vec::bytes::copy_memory(view, v, v_len);
         }
 
@@ -1909,8 +1912,7 @@ mod tests {
                 if len <= ivals.len() {
                     assert_eq!(res.len(), len);
                 }
-                assert!(vec::slice(ivals, 0u, res.len()) ==
-                             vec::map(res, |x| *x as int));
+                assert!(ivals.slice(0u, res.len()) == vec::map(res, |x| *x as int));
             }
         }
         let mut i = 0;
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 9e434272198..976ca8bae7a 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -964,7 +964,7 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
                     return Some(x)
                 }
             }
-            match self.iter.next().map_consume(self.f) {
+            match self.iter.next().map_consume(|x| (self.f)(x)) {
                 None => return None,
                 next => self.subiter = next,
             }
@@ -983,7 +983,7 @@ impl<'self, A, St> UnfoldrIterator<'self, A, St> {
     /// Creates a new iterator with the specified closure as the "iterator
     /// function" and an initial state to eventually pass to the iterator
     #[inline]
-    pub fn new<'a>(f: &'a fn(&mut St) -> Option<A>, initial_state: St)
+    pub fn new<'a>(initial_state: St, f: &'a fn(&mut St) -> Option<A>)
         -> UnfoldrIterator<'a, A, St> {
         UnfoldrIterator {
             f: f,
@@ -1030,7 +1030,6 @@ mod tests {
     use super::*;
     use prelude::*;
 
-    use iter;
     use uint;
 
     #[test]
@@ -1175,7 +1174,7 @@ mod tests {
             }
         }
 
-        let mut it = UnfoldrIterator::new(count, 0);
+        let mut it = UnfoldrIterator::new(0, count);
         let mut i = 0;
         for it.advance |counted| {
             assert_eq!(counted, i);
diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs
index 05c963a32cc..f350e106168 100644
--- a/src/libstd/kinds.rs
+++ b/src/libstd/kinds.rs
@@ -24,11 +24,10 @@ The 4 kinds are
   scalar types and managed pointers, and exludes owned pointers. It
   also excludes types that implement `Drop`.
 
-* Owned - owned types and types containing owned types.  These types
+* Send - owned types and types containing owned types.  These types
   may be transferred across task boundaries.
 
-* Const - types that are deeply immutable. Const types are used for
-  freezable data structures.
+* Freeze - types that are deeply immutable.
 
 `Copy` types include both implicitly copyable types that the compiler
 will copy automatically and non-implicitly copyable types that require
@@ -44,14 +43,28 @@ pub trait Copy {
     // Empty.
 }
 
+#[cfg(stage0)]
 #[lang="owned"]
-pub trait Owned {
-    // Empty.
+pub trait Send {
+    // empty.
+}
+
+#[cfg(not(stage0))]
+#[lang="send"]
+pub trait Send {
+    // empty.
 }
 
+#[cfg(stage0)]
 #[lang="const"]
-pub trait Const {
-    // Empty.
+pub trait Freeze {
+    // empty.
+}
+
+#[cfg(not(stage0))]
+#[lang="freeze"]
+pub trait Freeze {
+    // empty.
 }
 
 #[lang="sized"]
diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs
index 3c2ae93b656..41b78afded1 100644
--- a/src/libstd/libc.rs
+++ b/src/libstd/libc.rs
@@ -349,7 +349,6 @@ pub mod types {
                 use libc::types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t};
                 use libc::types::os::arch::c99::{c_longlong, c_ulonglong};
                 use libc::types::os::arch::posix88::{uid_t, gid_t, ino_t};
-                use libc::types::os::arch::posix88::{uid_t};
 
                 pub type nlink_t = u16;
                 pub type blksize_t = u32;
diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs
index 82c01c998cf..c5f2c8ae584 100644
--- a/src/libstd/local_data.rs
+++ b/src/libstd/local_data.rs
@@ -46,7 +46,7 @@ use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handl
  *
  * These two cases aside, the interface is safe.
  */
-pub type LocalDataKey<'self,T> = &'self fn(v: @T);
+pub type LocalDataKey<'self,T> = &'self fn:Copy(v: @T);
 
 /**
  * Remove a task-local data value from the table, returning the
@@ -92,14 +92,12 @@ fn test_tls_multitask() {
         fn my_key(_x: @~str) { }
         local_data_set(my_key, @~"parent data");
         do task::spawn {
-            unsafe {
-                // TLS shouldn't carry over.
-                assert!(local_data_get(my_key).is_none());
-                local_data_set(my_key, @~"child data");
-                assert!(*(local_data_get(my_key).get()) ==
+            // TLS shouldn't carry over.
+            assert!(local_data_get(my_key).is_none());
+            local_data_set(my_key, @~"child data");
+            assert!(*(local_data_get(my_key).get()) ==
                     ~"child data");
-                // should be cleaned up for us
-            }
+            // should be cleaned up for us
         }
         // Must work multiple times
         assert!(*(local_data_get(my_key).get()) == ~"parent data");
@@ -206,12 +204,11 @@ fn test_tls_cleanup_on_failure() {
         local_data_set(str_key, @~"parent data");
         local_data_set(box_key, @@());
         do task::spawn {
-            unsafe { // spawn_linked
-                local_data_set(str_key, @~"string data");
-                local_data_set(box_key, @@());
-                local_data_set(int_key, @42);
-                fail!();
-            }
+            // spawn_linked
+            local_data_set(str_key, @~"string data");
+            local_data_set(box_key, @@());
+            local_data_set(int_key, @42);
+            fail!();
         }
         // Not quite nondeterministic.
         local_data_set(int_key, @31337);
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs
index 74ec46ccfcd..845152f8552 100644
--- a/src/libstd/num/int_macros.rs
+++ b/src/libstd/num/int_macros.rs
@@ -400,7 +400,8 @@ impl Integer for $T {
     #[inline]
     fn gcd(&self, other: &$T) -> $T {
         // Use Euclid's algorithm
-        let mut (m, n) = (*self, *other);
+        let mut m = *self;
+        let mut n = *other;
         while m != 0 {
             let temp = m;
             m = n % temp;
diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs
index 30a18a0587b..b856c3c65ea 100644
--- a/src/libstd/num/num.rs
+++ b/src/libstd/num/num.rs
@@ -412,7 +412,7 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Div<T,T>+Mul<T,T>>(radix: uint, pow
         if my_pow % 2u == 1u {
             total = total * multiplier;
         }
-        my_pow     = my_pow / 2u;
+        my_pow = my_pow / 2u;
         multiplier = multiplier * multiplier;
     }
     total
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index 52f620f97ce..0dabe7fafa8 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -237,7 +237,8 @@ impl Integer for $T {
     #[inline]
     fn gcd(&self, other: &$T) -> $T {
         // Use Euclid's algorithm
-        let mut (m, n) = (*self, *other);
+        let mut m = *self;
+        let mut n = *other;
         while m != 0 {
             let temp = m;
             m = n % temp;
diff --git a/src/libstd/option.rs b/src/libstd/option.rs
index f3ea81f1ae5..12ae2abd4a1 100644
--- a/src/libstd/option.rs
+++ b/src/libstd/option.rs
@@ -447,7 +447,7 @@ fn test_option_dance() {
 }
 #[test] #[should_fail] #[ignore(cfg(windows))]
 fn test_option_too_much_dance() {
-    let mut y = Some(util::NonCopyable::new());
+    let mut y = Some(util::NonCopyable);
     let _y2 = y.swap_unwrap();
     let _y3 = y.swap_unwrap();
 }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 0f6517f5799..1fbcda12dce 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -29,6 +29,7 @@
 #[allow(missing_doc)];
 
 use cast;
+use container::Container;
 use io;
 use iterator::IteratorUtil;
 use libc;
@@ -134,7 +135,7 @@ pub mod win32 {
                     }
                 }
                 if k != 0 && done {
-                    let sub = vec::slice(buf, 0u, k as uint);
+                    let sub = buf.slice(0, k as uint);
                     res = option::Some(str::from_utf16(sub));
                 }
             }
@@ -145,7 +146,7 @@ pub mod win32 {
     pub fn as_utf16_p<T>(s: &str, f: &fn(*u16) -> T) -> T {
         let mut t = s.to_utf16();
         // Null terminate before passing on.
-        t += [0u16];
+        t.push(0u16);
         vec::as_imm_buf(t, |buf, _len| f(buf))
     }
 }
@@ -594,7 +595,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
     let r = list_dir(p);
     r.iter().advance(|q| {
         let path = &p.push(*q);
-        f(path) && (!path_is_dir(path) || walk_dir(path, f))
+        f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
     })
 }
 
@@ -1140,7 +1141,7 @@ pub fn set_exit_status(code: int) {
 unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
     let mut args = ~[];
     for uint::range(0, argc as uint) |i| {
-        vec::push(&mut args, str::raw::from_c_str(*argv.offset(i)));
+        args.push(str::raw::from_c_str(*argv.offset(i)));
     }
     args
 }
@@ -1186,8 +1187,7 @@ pub fn real_args() -> ~[~str] {
             while *ptr.offset(len) != 0 { len += 1; }
 
             // Push it onto the list.
-            vec::push(&mut args,
-                      vec::raw::buf_as_slice(ptr, len,
+            args.push(vec::raw::buf_as_slice(ptr, len,
                                              str::from_utf16));
         }
     }
@@ -1501,7 +1501,10 @@ mod tests {
     fn test_getenv_big() {
         let mut s = ~"";
         let mut i = 0;
-        while i < 100 { s += "aaaaaaaaaa"; i += 1; }
+        while i < 100 {
+            s = s + "aaaaaaaaaa";
+            i += 1;
+        }
         let n = make_rand_name();
         setenv(n, s);
         debug!(copy s);
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 700bfff3f5d..a5e82c31d79 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -21,8 +21,8 @@ use cmp::Eq;
 use iterator::IteratorUtil;
 use libc;
 use option::{None, Option, Some};
+use str::{OwnedStr, Str, StrSlice, StrVector};
 use str;
-use str::{Str, StrSlice, StrVector};
 use to_str::ToStr;
 use ascii::{AsciiCast, AsciiStr};
 use vec::{OwnedVector, ImmutableVector};
@@ -335,8 +335,8 @@ mod stat {
     }
 }
 
-
-impl Path {
+#[cfg(target_os = "win32")]
+impl WindowsPath {
     pub fn stat(&self) -> Option<libc::stat> {
         unsafe {
              do str::as_c_str(self.to_str()) |buf| {
@@ -349,12 +349,35 @@ impl Path {
         }
     }
 
-    #[cfg(unix)]
-    pub fn lstat(&self) -> Option<libc::stat> {
+    pub fn exists(&self) -> bool {
+        match self.stat() {
+            None => false,
+            Some(_) => true,
+        }
+    }
+
+    pub fn get_size(&self) -> Option<i64> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => Some(st.st_size as i64),
+        }
+    }
+
+    pub fn get_mode(&self) -> Option<uint> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => Some(st.st_mode as uint),
+        }
+    }
+}
+
+#[cfg(not(target_os = "win32"))]
+impl PosixPath {
+    pub fn stat(&self) -> Option<libc::stat> {
         unsafe {
-            do str::as_c_str(self.to_str()) |buf| {
+             do str::as_c_str(self.to_str()) |buf| {
                 let mut st = stat::arch::default_stat();
-                match libc::lstat(buf, &mut st) {
+                match libc::stat(buf, &mut st) {
                     0 => Some(st),
                     _ => None,
                 }
@@ -382,12 +405,21 @@ impl Path {
             Some(ref st) => Some(st.st_mode as uint),
         }
     }
+
+    /// Execute a function on p as well as all of its ancestors
+    pub fn each_parent(&self, f: &fn(&Path)) {
+        if !self.components.is_empty() {
+            f(self);
+            self.pop().each_parent(f);
+        }
+    }
+
 }
 
 #[cfg(target_os = "freebsd")]
 #[cfg(target_os = "linux")]
 #[cfg(target_os = "macos")]
-impl Path {
+impl PosixPath {
     pub fn get_atime(&self) -> Option<(i64, int)> {
         match self.stat() {
             None => None,
@@ -419,9 +451,24 @@ impl Path {
     }
 }
 
+#[cfg(unix)]
+impl PosixPath {
+    pub fn lstat(&self) -> Option<libc::stat> {
+        unsafe {
+            do str::as_c_str(self.to_str()) |buf| {
+                let mut st = stat::arch::default_stat();
+                match libc::lstat(buf, &mut st) {
+                    0 => Some(st),
+                    _ => None,
+                }
+            }
+        }
+    }
+}
+
 #[cfg(target_os = "freebsd")]
 #[cfg(target_os = "macos")]
-impl Path {
+impl PosixPath {
     pub fn get_birthtime(&self) -> Option<(i64, int)> {
         match self.stat() {
             None => None,
@@ -434,7 +481,7 @@ impl Path {
 }
 
 #[cfg(target_os = "win32")]
-impl Path {
+impl WindowsPath {
     pub fn get_atime(&self) -> Option<(i64, int)> {
         match self.stat() {
             None => None,
@@ -461,13 +508,21 @@ impl Path {
             }
         }
     }
+
+    /// Execute a function on p as well as all of its ancestors
+    pub fn each_parent(&self, f: &fn(&Path)) {
+        if !self.components.is_empty() {
+            f(self);
+            self.pop().each_parent(f);
+        }
+    }
 }
 
 impl ToStr for PosixPath {
     fn to_str(&self) -> ~str {
         let mut s = ~"";
         if self.is_absolute {
-            s += "/";
+            s.push_str("/");
         }
         s + self.components.connect("/")
     }
@@ -646,15 +701,21 @@ impl ToStr for WindowsPath {
     fn to_str(&self) -> ~str {
         let mut s = ~"";
         match self.host {
-          Some(ref h) => { s += "\\\\"; s += *h; }
+          Some(ref h) => {
+            s.push_str("\\\\");
+            s.push_str(*h);
+          }
           None => { }
         }
         match self.device {
-          Some(ref d) => { s += *d; s += ":"; }
+          Some(ref d) => {
+            s.push_str(*d);
+            s.push_str(":");
+          }
           None => { }
         }
         if self.is_absolute {
-            s += "\\";
+            s.push_str("\\");
         }
         s + self.components.connect("\\")
     }
diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs
index 661dc2a659f..49713a3a23b 100644
--- a/src/libstd/pipes.rs
+++ b/src/libstd/pipes.rs
@@ -88,7 +88,7 @@ use container::Container;
 use cast::{forget, transmute, transmute_copy, transmute_mut};
 use either::{Either, Left, Right};
 use iterator::IteratorUtil;
-use kinds::Owned;
+use kinds::Send;
 use libc;
 use ops::Drop;
 use option::{None, Option, Some};
@@ -177,7 +177,7 @@ impl PacketHeader {
         transmute_copy(&self.buffer)
     }
 
-    pub fn set_buffer<T:Owned>(&mut self, b: ~Buffer<T>) {
+    pub fn set_buffer<T:Send>(&mut self, b: ~Buffer<T>) {
         unsafe {
             self.buffer = transmute_copy(&b);
         }
@@ -193,13 +193,13 @@ pub trait HasBuffer {
     fn set_buffer(&mut self, b: *libc::c_void);
 }
 
-impl<T:Owned> HasBuffer for Packet<T> {
+impl<T:Send> HasBuffer for Packet<T> {
     fn set_buffer(&mut self, b: *libc::c_void) {
         self.header.buffer = b;
     }
 }
 
-pub fn mk_packet<T:Owned>() -> Packet<T> {
+pub fn mk_packet<T:Send>() -> Packet<T> {
     Packet {
         header: PacketHeader(),
         payload: None,
@@ -230,7 +230,7 @@ pub fn packet<T>() -> *mut Packet<T> {
     p
 }
 
-pub fn entangle_buffer<T:Owned,Tstart:Owned>(
+pub fn entangle_buffer<T:Send,Tstart:Send>(
     mut buffer: ~Buffer<T>,
     init: &fn(*libc::c_void, x: &mut T) -> *mut Packet<Tstart>)
     -> (RecvPacketBuffered<Tstart, T>, SendPacketBuffered<Tstart, T>) {
@@ -396,7 +396,7 @@ pub fn send<T,Tbuffer>(mut p: SendPacketBuffered<T,Tbuffer>,
 Fails if the sender closes the connection.
 
 */
-pub fn recv<T:Owned,Tbuffer:Owned>(
+pub fn recv<T:Send,Tbuffer:Send>(
     p: RecvPacketBuffered<T, Tbuffer>) -> T {
     try_recv(p).expect("connection closed")
 }
@@ -407,7 +407,7 @@ Returns `None` if the sender has closed the connection without sending
 a message, or `Some(T)` if a message was received.
 
 */
-pub fn try_recv<T:Owned,Tbuffer:Owned>(mut p: RecvPacketBuffered<T, Tbuffer>)
+pub fn try_recv<T:Send,Tbuffer:Send>(mut p: RecvPacketBuffered<T, Tbuffer>)
                                        -> Option<T> {
     let p_ = p.unwrap();
     let p = unsafe { &mut *p_ };
@@ -427,7 +427,7 @@ pub fn try_recv<T:Owned,Tbuffer:Owned>(mut p: RecvPacketBuffered<T, Tbuffer>)
     }
 }
 
-fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
+fn try_recv_<T:Send>(p: &mut Packet<T>) -> Option<T> {
     // optimistic path
     match p.header.state {
       Full => {
@@ -511,7 +511,7 @@ fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
 }
 
 /// Returns true if messages are available.
-pub fn peek<T:Owned,Tb:Owned>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
+pub fn peek<T:Send,Tb:Send>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
     unsafe {
         match (*p.header()).state {
             Empty | Terminated => false,
@@ -521,7 +521,7 @@ pub fn peek<T:Owned,Tb:Owned>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
     }
 }
 
-fn sender_terminate<T:Owned>(p: *mut Packet<T>) {
+fn sender_terminate<T:Send>(p: *mut Packet<T>) {
     let p = unsafe {
         &mut *p
     };
@@ -553,7 +553,7 @@ fn sender_terminate<T:Owned>(p: *mut Packet<T>) {
     }
 }
 
-fn receiver_terminate<T:Owned>(p: *mut Packet<T>) {
+fn receiver_terminate<T:Send>(p: *mut Packet<T>) {
     let p = unsafe {
         &mut *p
     };
@@ -671,7 +671,7 @@ pub struct SendPacketBuffered<T, Tbuffer> {
 }
 
 #[unsafe_destructor]
-impl<T:Owned,Tbuffer:Owned> Drop for SendPacketBuffered<T,Tbuffer> {
+impl<T:Send,Tbuffer:Send> Drop for SendPacketBuffered<T,Tbuffer> {
     fn drop(&self) {
         unsafe {
             let this: &mut SendPacketBuffered<T,Tbuffer> = transmute(self);
@@ -729,7 +729,7 @@ pub struct RecvPacketBuffered<T, Tbuffer> {
 }
 
 #[unsafe_destructor]
-impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
+impl<T:Send,Tbuffer:Send> Drop for RecvPacketBuffered<T,Tbuffer> {
     fn drop(&self) {
         unsafe {
             let this: &mut RecvPacketBuffered<T,Tbuffer> = transmute(self);
@@ -741,7 +741,7 @@ impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
     }
 }
 
-impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
+impl<T:Send,Tbuffer:Send> RecvPacketBuffered<T, Tbuffer> {
     pub fn unwrap(&mut self) -> *mut Packet<T> {
         replace(&mut self.p, None).unwrap()
     }
@@ -751,7 +751,7 @@ impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
     }
 }
 
-impl<T:Owned,Tbuffer:Owned> Selectable for RecvPacketBuffered<T, Tbuffer> {
+impl<T:Send,Tbuffer:Send> Selectable for RecvPacketBuffered<T, Tbuffer> {
     fn header(&mut self) -> *mut PacketHeader {
         match self.p {
             Some(packet) => unsafe {
@@ -807,7 +807,7 @@ Sometimes messages will be available on both endpoints at once. In
 this case, `select2` may return either `left` or `right`.
 
 */
-pub fn select2<A:Owned,Ab:Owned,B:Owned,Bb:Owned>(
+pub fn select2<A:Send,Ab:Send,B:Send,Bb:Send>(
     mut a: RecvPacketBuffered<A, Ab>,
     mut b: RecvPacketBuffered<B, Bb>)
     -> Either<(Option<A>, RecvPacketBuffered<B, Bb>),
@@ -847,7 +847,7 @@ pub fn select2i<A:Selectable,B:Selectable>(a: &mut A, b: &mut B)
 
 /// Waits on a set of endpoints. Returns a message, its index, and a
 /// list of the remaining endpoints.
-pub fn select<T:Owned,Tb:Owned>(mut endpoints: ~[RecvPacketBuffered<T, Tb>])
+pub fn select<T:Send,Tb:Send>(mut endpoints: ~[RecvPacketBuffered<T, Tb>])
                                 -> (uint,
                                     Option<T>,
                                     ~[RecvPacketBuffered<T, Tb>]) {
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index 6d7cb2a28a8..13d19b276f5 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -29,7 +29,8 @@ Rust's prelude has three main parts:
 
 // Reexported core operators
 pub use either::{Either, Left, Right};
-pub use kinds::{Const, Copy, Owned, Sized};
+pub use kinds::{Copy, Sized};
+pub use kinds::{Freeze, Send};
 pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
 pub use ops::{BitAnd, BitOr, BitXor};
 pub use ops::{Drop};
diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs
index ea4a9059e72..5baff8aee68 100644
--- a/src/libstd/rand.rs
+++ b/src/libstd/rand.rs
@@ -42,6 +42,7 @@ fn main () {
 
 use cast;
 use cmp;
+use container::Container;
 use int;
 use iterator::IteratorUtil;
 use local_data;
@@ -720,7 +721,8 @@ impl IsaacRng {
     fn isaac(&mut self) {
         self.c += 1;
         // abbreviations
-        let mut (a, b) = (self.a, self.b + self.c);
+        let mut a = self.a;
+        let mut b = self.b + self.c;
 
         static midpoint: uint = RAND_SIZE as uint / 2;
 
diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs
index 6f4f1a34977..e8dad2fc5e8 100644
--- a/src/libstd/rand/distributions.rs
+++ b/src/libstd/rand/distributions.rs
@@ -89,7 +89,8 @@ impl Rand for StandardNormal {
             // do-while, so the condition should be true on the first
             // run, they get overwritten anyway (0 < 1, so these are
             // good).
-            let mut (x, y) = (1.0, 0.0);
+            let mut x = 1.0;
+            let mut y = 0.0;
 
             // XXX infinities?
             while -2.0*y < x * x {
diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs
index 75b1d8f3810..72907f40a07 100644
--- a/src/libstd/rt/comm.rs
+++ b/src/libstd/rt/comm.rs
@@ -19,7 +19,7 @@ use option::*;
 use cast;
 use util;
 use ops::Drop;
-use kinds::Owned;
+use kinds::Send;
 use rt::sched::{Scheduler, Coroutine};
 use rt::local::Local;
 use unstable::intrinsics::{atomic_xchg, atomic_load};
@@ -68,7 +68,7 @@ pub struct PortOneHack<T> {
     suppress_finalize: bool
 }
 
-pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
+pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
     let packet: ~Packet<T> = ~Packet {
         state: STATE_BOTH,
         payload: None
@@ -307,20 +307,20 @@ pub struct Port<T> {
     next: Cell<PortOne<StreamPayload<T>>>
 }
 
-pub fn stream<T: Owned>() -> (Port<T>, Chan<T>) {
+pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
     let (pone, cone) = oneshot();
     let port = Port { next: Cell::new(pone) };
     let chan = Chan { next: Cell::new(cone) };
     return (port, chan);
 }
 
-impl<T: Owned> GenericChan<T> for Chan<T> {
+impl<T: Send> GenericChan<T> for Chan<T> {
     fn send(&self, val: T) {
         self.try_send(val);
     }
 }
 
-impl<T: Owned> GenericSmartChan<T> for Chan<T> {
+impl<T: Send> GenericSmartChan<T> for Chan<T> {
     fn try_send(&self, val: T) -> bool {
         let (next_pone, next_cone) = oneshot();
         let cone = self.next.take();
diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs
index 55861f127bb..c6654e9dabe 100644
--- a/src/libstd/rt/io/extensions.rs
+++ b/src/libstd/rt/io/extensions.rs
@@ -292,13 +292,13 @@ impl<T: Reader> ReaderUtil for T {
             let start_len = buf.len();
             let mut total_read = 0;
 
-            vec::reserve_at_least(buf, start_len + len);
+            buf.reserve_at_least(start_len + len);
             vec::raw::set_len(buf, start_len + len);
 
             do (|| {
                 while total_read < len {
                     let len = buf.len();
-                    let slice = vec::mut_slice(*buf, start_len + total_read, len);
+                    let slice = buf.mut_slice(start_len + total_read, len);
                     match self.read(slice) {
                         Some(nread) => {
                             total_read += nread;
@@ -343,7 +343,9 @@ impl<T: Reader> ReaderByteConversions for T {
     fn read_le_uint_n(&mut self, nbytes: uint) -> u64 {
         assert!(nbytes > 0 && nbytes <= 8);
 
-        let mut (val, pos, i) = (0u64, 0, nbytes);
+        let mut val = 0u64;
+        let mut pos = 0;
+        let mut i = nbytes;
         while i > 0 {
             val += (self.read_u8() as u64) << pos;
             pos += 8;
@@ -359,7 +361,8 @@ impl<T: Reader> ReaderByteConversions for T {
     fn read_be_uint_n(&mut self, nbytes: uint) -> u64 {
         assert!(nbytes > 0 && nbytes <= 8);
 
-        let mut (val, i) = (0u64, nbytes);
+        let mut val = 0u64;
+        let mut i = nbytes;
         while i > 0 {
             i -= 1;
             val += (self.read_u8() as u64) << i * 8;
diff --git a/src/libstd/rt/io/mem.rs b/src/libstd/rt/io/mem.rs
index bd9cff76e57..c93945a6a9a 100644
--- a/src/libstd/rt/io/mem.rs
+++ b/src/libstd/rt/io/mem.rs
@@ -86,7 +86,7 @@ impl Reader for MemReader {
         let write_len = min(buf.len(), self.buf.len() - self.pos);
         {
             let input = self.buf.slice(self.pos, self.pos + write_len);
-            let output = vec::mut_slice(buf, 0, write_len);
+            let output = buf.mut_slice(0, write_len);
             assert_eq!(input.len(), output.len());
             vec::bytes::copy_memory(output, input, write_len);
         }
diff --git a/src/libstd/rt/message_queue.rs b/src/libstd/rt/message_queue.rs
index 5b60543344d..d561e81d032 100644
--- a/src/libstd/rt/message_queue.rs
+++ b/src/libstd/rt/message_queue.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use container::Container;
-use kinds::Owned;
+use kinds::Send;
 use vec::OwnedVector;
 use cell::Cell;
 use option::*;
@@ -21,7 +21,7 @@ pub struct MessageQueue<T> {
     priv queue: ~Exclusive<~[T]>
 }
 
-impl<T: Owned> MessageQueue<T> {
+impl<T: Send> MessageQueue<T> {
     pub fn new() -> MessageQueue<T> {
         MessageQueue {
             queue: ~exclusive(~[])
diff --git a/src/libstd/rt/uv/timer.rs b/src/libstd/rt/uv/timer.rs
index cd6fc5c0a25..14465eb7dfd 100644
--- a/src/libstd/rt/uv/timer.rs
+++ b/src/libstd/rt/uv/timer.rs
@@ -160,14 +160,14 @@ mod test {
                         let mut timer2 = TimerWatcher::new(&mut loop_);
                         do timer2.start(10, 0) |timer2, _| {
 
-                            unsafe { *count_ptr += 1; }
+                            *count_ptr += 1;
 
                             timer2.close(||());
 
                             // Restart the original timer
                             let mut timer = timer;
                             do timer.start(1, 0) |timer, _| {
-                                unsafe { *count_ptr += 1; }
+                                *count_ptr += 1;
                                 timer.close(||());
                             }
                         }
diff --git a/src/libstd/rt/work_queue.rs b/src/libstd/rt/work_queue.rs
index cfffc55a58c..00d27744268 100644
--- a/src/libstd/rt/work_queue.rs
+++ b/src/libstd/rt/work_queue.rs
@@ -13,7 +13,7 @@ use option::*;
 use vec::OwnedVector;
 use unstable::sync::{Exclusive, exclusive};
 use cell::Cell;
-use kinds::Owned;
+use kinds::Send;
 use clone::Clone;
 
 pub struct WorkQueue<T> {
@@ -21,7 +21,7 @@ pub struct WorkQueue<T> {
     priv queue: ~Exclusive<~[T]>
 }
 
-impl<T: Owned> WorkQueue<T> {
+impl<T: Send> WorkQueue<T> {
     pub fn new() -> WorkQueue<T> {
         WorkQueue {
             queue: ~exclusive(~[])
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 801a4af281e..e47800d70c6 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -357,7 +357,8 @@ impl<'self> Iterator<(uint, uint)> for StrMatchesIndexIterator<'self> {
     fn next(&mut self) -> Option<(uint, uint)> {
         // See Issue #1932 for why this is a naive search
         let (h_len, n_len) = (self.haystack.len(), self.needle.len());
-        let mut (match_start, match_i) = (0, 0);
+        let mut match_start = 0;
+        let mut match_i = 0;
 
         while self.position < h_len {
             if self.haystack[self.position] == self.needle[match_i] {
@@ -462,7 +463,7 @@ pub fn each_split_within<'a>(ss: &'a str,
         cont
     };
 
-    ss.iter().enumerate().advance(machine);
+    ss.iter().enumerate().advance(|x| machine(x));
 
     // Let the automaton 'run out' by supplying trailing whitespace
     let mut fake_i = ss.len();
@@ -473,6 +474,31 @@ pub fn each_split_within<'a>(ss: &'a str,
     return cont;
 }
 
+/**
+ * Replace all occurrences of one string with another
+ *
+ * # Arguments
+ *
+ * * s - The string containing substrings to replace
+ * * from - The string to replace
+ * * to - The replacement string
+ *
+ * # Return value
+ *
+ * The original string with all occurances of `from` replaced with `to`
+ */
+pub fn replace(s: &str, from: &str, to: &str) -> ~str {
+    let mut result = ~"";
+    let mut last_end = 0;
+    for s.matches_index_iter(from).advance |(start, end)| {
+        result.push_str(unsafe{raw::slice_bytes(s, last_end, start)});
+        result.push_str(to);
+        last_end = end;
+    }
+    result.push_str(unsafe{raw::slice_bytes(s, last_end, s.len())});
+    result
+}
+
 /*
 Section: Comparing strings
 */
@@ -631,6 +657,48 @@ pub fn with_capacity(capacity: uint) -> ~str {
     buf
 }
 
+/**
+ * As char_len but for a slice of a string
+ *
+ * # Arguments
+ *
+ * * s - A valid string
+ * * start - The position inside `s` where to start counting in bytes
+ * * end - The position where to stop counting
+ *
+ * # Return value
+ *
+ * The number of Unicode characters in `s` between the given indices.
+ */
+pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
+    assert!(s.is_char_boundary(start));
+    assert!(s.is_char_boundary(end));
+    let mut i = start;
+    let mut len = 0u;
+    while i < end {
+        let next = s.char_range_at(i).next;
+        len += 1u;
+        i = next;
+    }
+    return len;
+}
+
+/// Counts the number of bytes taken by the first `n` chars in `s`
+/// starting from `start`.
+pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
+    assert!(s.is_char_boundary(start));
+    let mut end = start;
+    let mut cnt = n;
+    let l = s.len();
+    while cnt > 0u {
+        assert!(end < l);
+        let next = s.char_range_at(end).next;
+        cnt -= 1u;
+        end = next;
+    }
+    end - start
+}
+
 /// Given a first byte, determine how many bytes are in this UTF-8 character
 pub fn utf8_char_width(b: u8) -> uint {
     let byte: uint = b as uint;
@@ -693,7 +761,7 @@ impl<'self> StrUtil for &'self str {
             // NB: len includes the trailing null.
             assert!(len > 0);
             if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
-                to_owned(self).as_c_str(f)
+                to_owned(self).as_c_str(|s| f(s))
             } else {
                 f(buf as *libc::c_char)
             }
@@ -737,7 +805,8 @@ pub mod raw {
 
     /// Create a Rust string from a null-terminated *u8 buffer
     pub unsafe fn from_buf(buf: *u8) -> ~str {
-        let mut (curr, i) = (buf, 0u);
+        let mut curr = buf;
+        let mut i = 0u;
         while *curr != 0u8 {
             i += 1u;
             curr = ptr::offset(buf, i);
@@ -790,7 +859,8 @@ pub mod raw {
     /// invalidated later.
     pub unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
         let s = s as *u8;
-        let mut (curr, len) = (s, 0u);
+        let mut curr = s;
+        let mut len = 0u;
         while *curr != 0u8 {
             len += 1u;
             curr = ptr::offset(s, len);
@@ -1070,6 +1140,17 @@ impl<'self> Str for @str {
     }
 }
 
+impl<'self> Container for &'self str {
+    #[inline]
+    fn len(&self) -> uint {
+        do as_buf(*self) |_p, n| { n - 1u }
+    }
+    #[inline]
+    fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+}
+
 #[allow(missing_doc)]
 pub trait StrSlice<'self> {
     fn contains<'a>(&self, needle: &'a str) -> bool;
@@ -1088,10 +1169,8 @@ pub trait StrSlice<'self> {
     fn any_line_iter(&self) -> AnyLineIterator<'self>;
     fn word_iter(&self) -> WordIterator<'self>;
     fn ends_with(&self, needle: &str) -> bool;
-    fn is_empty(&self) -> bool;
     fn is_whitespace(&self) -> bool;
     fn is_alphanumeric(&self) -> bool;
-    fn len(&self) -> uint;
     fn char_len(&self) -> uint;
 
     fn slice(&self, begin: uint, end: uint) -> &'self str;
@@ -1292,9 +1371,6 @@ impl<'self> StrSlice<'self> for &'self str {
         self.split_iter(char::is_whitespace).filter(|s| !s.is_empty())
     }
 
-    /// Returns true if the string has length 0
-    #[inline]
-    fn is_empty(&self) -> bool { self.len() == 0 }
     /**
      * Returns true if the string contains only whitespace
      *
@@ -1309,11 +1385,6 @@ impl<'self> StrSlice<'self> for &'self str {
      */
     #[inline]
     fn is_alphanumeric(&self) -> bool { self.iter().all(char::is_alphanumeric) }
-    /// Returns the size in bytes not counting the null terminator
-    #[inline]
-    fn len(&self) -> uint {
-        do as_buf(*self) |_p, n| { n - 1u }
-    }
     /// Returns the number of characters that a string holds
     #[inline]
     fn char_len(&self) -> uint { self.iter().len_() }
@@ -1357,7 +1428,8 @@ impl<'self> StrSlice<'self> for &'self str {
     fn slice_chars(&self, begin: uint, end: uint) -> &'self str {
         assert!(begin <= end);
         // not sure how to use the iterators for this nicely.
-        let mut (position, count) = (0, 0);
+        let mut position = 0;
+        let mut count = 0;
         let l = self.len();
         while count < begin && position < l {
             position = self.char_range_at(position).next;
@@ -1505,7 +1577,8 @@ impl<'self> StrSlice<'self> for &'self str {
      * The original string with all occurances of `from` replaced with `to`
      */
     pub fn replace(&self, from: &str, to: &str) -> ~str {
-        let mut (result, last_end) = (~"", 0);
+        let mut result = ~"";
+        let mut last_end = 0;
         for self.matches_index_iter(from).advance |(start, end)| {
             result.push_str(unsafe{raw::slice_bytes(*self, last_end, start)});
             result.push_str(to);
@@ -2081,7 +2154,7 @@ impl OwnedStr for ~str {
     pub fn reserve(&mut self, n: uint) {
         unsafe {
             let v: *mut ~[u8] = cast::transmute(self);
-            vec::reserve(&mut *v, n + 1);
+            (*v).reserve(n + 1);
         }
     }
 
@@ -2115,8 +2188,8 @@ impl OwnedStr for ~str {
      * reallocating
      */
     fn capacity(&self) -> uint {
-        let buf: &const ~[u8] = unsafe { cast::transmute(self) };
-        let vcap = vec::capacity(buf);
+        let buf: &~[u8] = unsafe { cast::transmute(self) };
+        let vcap = buf.capacity();
         assert!(vcap > 0u);
         vcap - 1u
     }
@@ -2249,7 +2322,7 @@ mod tests {
         assert!("" <= "");
         assert!("" <= "foo");
         assert!("foo" <= "foo");
-        assert!("foo" != ~"bar");
+        assert!("foo" != "bar");
     }
 
     #[test]
@@ -3156,6 +3229,7 @@ mod tests {
 
     #[test]
     fn test_add() {
+        #[allow(unnecessary_allocation)];
         macro_rules! t (
             ($s1:expr, $s2:expr, $e:expr) => {
                 assert_eq!($s1 + $s2, $e);
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index 223afbce091..a8e8cfd163a 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -353,7 +353,7 @@ impl TaskBuilder {
     }
 
     /// Runs a task, while transfering ownership of one argument to the child.
-    pub fn spawn_with<A:Owned>(&mut self, arg: A, f: ~fn(v: A)) {
+    pub fn spawn_with<A:Send>(&mut self, arg: A, f: ~fn(v: A)) {
         let arg = Cell::new(arg);
         do self.spawn {
             f(arg.take());
@@ -373,7 +373,7 @@ impl TaskBuilder {
      * # Failure
      * Fails if a future_result was already set for this task.
      */
-    pub fn try<T:Owned>(&mut self, f: ~fn() -> T) -> Result<T,()> {
+    pub fn try<T:Send>(&mut self, f: ~fn() -> T) -> Result<T,()> {
         let (po, ch) = stream::<T>();
         let mut result = None;
 
@@ -445,7 +445,7 @@ pub fn spawn_supervised(f: ~fn()) {
     task.spawn(f)
 }
 
-pub fn spawn_with<A:Owned>(arg: A, f: ~fn(v: A)) {
+pub fn spawn_with<A:Send>(arg: A, f: ~fn(v: A)) {
     /*!
      * Runs a task, while transfering ownership of one argument to the
      * child.
@@ -478,7 +478,7 @@ pub fn spawn_sched(mode: SchedMode, f: ~fn()) {
     task.spawn(f)
 }
 
-pub fn try<T:Owned>(f: ~fn() -> T) -> Result<T,()> {
+pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
     /*!
      * Execute a function in another task and return either the return value
      * of the function or result::err.
@@ -934,17 +934,15 @@ fn test_spawn_sched_blocking() {
             let lock = testrt::rust_dbg_lock_create();
 
             do spawn_sched(SingleThreaded) {
-                unsafe {
-                    testrt::rust_dbg_lock_lock(lock);
+                testrt::rust_dbg_lock_lock(lock);
 
-                    start_ch.send(());
+                start_ch.send(());
 
-                    // Block the scheduler thread
-                    testrt::rust_dbg_lock_wait(lock);
-                    testrt::rust_dbg_lock_unlock(lock);
+                // Block the scheduler thread
+                testrt::rust_dbg_lock_wait(lock);
+                testrt::rust_dbg_lock_unlock(lock);
 
-                    fin_ch.send(());
-                }
+                fin_ch.send(());
             };
 
             // Wait until the other task has its lock
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index 95fc53c1b55..c932a9660c2 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -230,11 +230,15 @@ fn each_ancestor(list:        &mut AncestorList,
         // 'do_continue'  - Did the forward_blk succeed at this point? (i.e.,
         //                  should we recurse? or should our callers unwind?)
 
+        let forward_blk = Cell::new(forward_blk);
+
         // The map defaults to None, because if ancestors is None, we're at
         // the end of the list, which doesn't make sense to coalesce.
         return do (**ancestors).map_default((None,false)) |ancestor_arc| {
             // NB: Takes a lock! (this ancestor node)
             do access_ancestors(ancestor_arc) |nobe| {
+                // Argh, but we couldn't give it to coalesce() otherwise.
+                let forward_blk = forward_blk.take();
                 // Check monotonicity
                 assert!(last_generation > nobe.generation);
                 /*##########################################################*
@@ -636,7 +640,8 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
         let child_data = Cell::new((notify_chan, child_arc, ancestors));
         let result: ~fn() = || {
             // Agh. Get move-mode items into the closure. FIXME (#2829)
-            let mut (notify_chan, child_arc, ancestors) = child_data.take();
+            let (notify_chan, child_arc, ancestors) = child_data.take();
+            let mut ancestors = ancestors;
             // Child task runs this code.
 
             // Even if the below code fails to kick the child off, we must
diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs
index 6f0c615d007..d6e92dd679e 100644
--- a/src/libstd/to_bytes.rs
+++ b/src/libstd/to_bytes.rs
@@ -232,7 +232,8 @@ impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) {
   #[inline]
   fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
     match *self {
-      (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) }
+      (ref a, ref b) => { a.iter_bytes(lsb0, |b| f(b)) &&
+                          b.iter_bytes(lsb0, |b| f(b)) }
     }
   }
 }
@@ -242,7 +243,9 @@ impl<A:IterBytes,B:IterBytes,C:IterBytes> IterBytes for (A,B,C) {
   fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
     match *self {
       (ref a, ref b, ref c) => {
-        a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f)
+        a.iter_bytes(lsb0, |b| f(b)) &&
+        b.iter_bytes(lsb0, |b| f(b)) &&
+        c.iter_bytes(lsb0, |b| f(b))
       }
     }
   }
@@ -296,7 +299,7 @@ impl<A:IterBytes> IterBytes for Option<A> {
     #[inline]
     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
         match *self {
-          Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f),
+          Some(ref a) => 0u8.iter_bytes(lsb0, |b| f(b)) && a.iter_bytes(lsb0, |b| f(b)),
           None => 1u8.iter_bytes(lsb0, f)
         }
     }
diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs
index ea0e212b14f..77701acd33e 100644
--- a/src/libstd/to_str.rs
+++ b/src/libstd/to_str.rs
@@ -53,7 +53,8 @@ impl<A:ToStr> ToStr for (A,) {
 impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
     #[inline]
     fn to_str(&self) -> ~str {
-        let mut (acc, first) = (~"{", true);
+        let mut acc = ~"{";
+        let mut first = true;
         for self.iter().advance |(key, value)| {
             if first {
                 first = false;
@@ -73,7 +74,8 @@ impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
 impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
     #[inline]
     fn to_str(&self) -> ~str {
-        let mut (acc, first) = (~"{", true);
+        let mut acc = ~"{";
+        let mut first = true;
         for self.iter().advance |element| {
             if first {
                 first = false;
@@ -121,7 +123,8 @@ impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
 impl<'self,A:ToStr> ToStr for &'self [A] {
     #[inline]
     fn to_str(&self) -> ~str {
-        let mut (acc, first) = (~"[", true);
+        let mut acc = ~"[";
+        let mut first = true;
         for self.iter().advance |elt| {
             if first {
                 first = false;
@@ -139,7 +142,8 @@ impl<'self,A:ToStr> ToStr for &'self [A] {
 impl<A:ToStr> ToStr for ~[A] {
     #[inline]
     fn to_str(&self) -> ~str {
-        let mut (acc, first) = (~"[", true);
+        let mut acc = ~"[";
+        let mut first = true;
         for self.iter().advance |elt| {
             if first {
                 first = false;
@@ -157,7 +161,8 @@ impl<A:ToStr> ToStr for ~[A] {
 impl<A:ToStr> ToStr for @[A] {
     #[inline]
     fn to_str(&self) -> ~str {
-        let mut (acc, first) = (~"[", true);
+        let mut acc = ~"[";
+        let mut first = true;
         for self.iter().advance |elt| {
             if first {
                 first = false;
diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs
index 8f70c75439a..b9b03ea5661 100644
--- a/src/libstd/trie.rs
+++ b/src/libstd/trie.rs
@@ -251,7 +251,7 @@ impl<T> TrieNode<T> {
     fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
         for uint::range(0, self.children.len()) |idx| {
             match self.children[idx] {
-                Internal(ref x) => if !x.each(f) { return false },
+                Internal(ref x) => if !x.each(|i,t| f(i,t)) { return false },
                 External(k, ref v) => if !f(&k, v) { return false },
                 Nothing => ()
             }
@@ -262,7 +262,7 @@ impl<T> TrieNode<T> {
     fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
         for uint::range_rev(self.children.len(), 0) |idx| {
             match self.children[idx - 1] {
-                Internal(ref x) => if !x.each_reverse(f) { return false },
+                Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false },
                 External(k, ref v) => if !f(&k, v) { return false },
                 Nothing => ()
             }
@@ -273,7 +273,7 @@ impl<T> TrieNode<T> {
     fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
         for self.children.mut_iter().advance |child| {
             match *child {
-                Internal(ref mut x) => if !x.mutate_values(f) {
+                Internal(ref mut x) => if !x.mutate_values(|i,t| f(i,t)) {
                     return false
                 },
                 External(k, ref mut v) => if !f(&k, v) { return false },
diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs
index 45eced9846c..1e5ac305df3 100644
--- a/src/libstd/unstable/atomics.rs
+++ b/src/libstd/unstable/atomics.rs
@@ -62,7 +62,7 @@ pub struct AtomicPtr<T> {
 /**
  * An owned atomic pointer. Ensures that only a single reference to the data is held at any time.
  */
-#[no_drop_flag]
+#[unsafe_no_drop_flag]
 pub struct AtomicOption<T> {
     priv p: *mut c_void
 }
diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs
index 87bd25bdad3..624062a7ec4 100644
--- a/src/libstd/unstable/extfmt.rs
+++ b/src/libstd/unstable/extfmt.rs
@@ -94,6 +94,7 @@ use iterator::IteratorUtil;
 #[doc(hidden)]
 pub mod ct {
     use char;
+    use container::Container;
     use prelude::*;
     use str;
 
diff --git a/src/libstd/unstable/global.rs b/src/libstd/unstable/global.rs
index 4fde8f704b9..285a8114cc2 100644
--- a/src/libstd/unstable/global.rs
+++ b/src/libstd/unstable/global.rs
@@ -27,7 +27,7 @@ avoid hitting the mutex.
 
 use cast::{transmute};
 use clone::Clone;
-use kinds::Owned;
+use kinds::Send;
 use libc::{c_void};
 use option::{Option, Some, None};
 use ops::Drop;
@@ -43,7 +43,7 @@ use sys::Closure;
 
 pub type GlobalDataKey<'self,T> = &'self fn(v: T);
 
-pub unsafe fn global_data_clone_create<T:Owned + Clone>(
+pub unsafe fn global_data_clone_create<T:Send + Clone>(
     key: GlobalDataKey<T>, create: &fn() -> ~T) -> T {
     /*!
      * Clone a global value or, if it has not been created,
@@ -59,7 +59,7 @@ pub unsafe fn global_data_clone_create<T:Owned + Clone>(
     global_data_clone_create_(key_ptr(key), create)
 }
 
-unsafe fn global_data_clone_create_<T:Owned + Clone>(
+unsafe fn global_data_clone_create_<T:Send + Clone>(
     key: uint, create: &fn() -> ~T) -> T {
 
     let mut clone_value: Option<T> = None;
@@ -79,13 +79,13 @@ unsafe fn global_data_clone_create_<T:Owned + Clone>(
     return clone_value.unwrap();
 }
 
-unsafe fn global_data_modify<T:Owned>(
+unsafe fn global_data_modify<T:Send>(
     key: GlobalDataKey<T>, op: &fn(Option<~T>) -> Option<~T>) {
 
     global_data_modify_(key_ptr(key), op)
 }
 
-unsafe fn global_data_modify_<T:Owned>(
+unsafe fn global_data_modify_<T:Send>(
     key: uint, op: &fn(Option<~T>) -> Option<~T>) {
 
     let mut old_dtor = None;
@@ -124,7 +124,7 @@ unsafe fn global_data_modify_<T:Owned>(
     }
 }
 
-pub unsafe fn global_data_clone<T:Owned + Clone>(
+pub unsafe fn global_data_clone<T:Send + Clone>(
     key: GlobalDataKey<T>) -> Option<T> {
     let mut maybe_clone: Option<T> = None;
     do global_data_modify(key) |current| {
@@ -220,7 +220,7 @@ fn get_global_state() -> Exclusive<GlobalState> {
     }
 }
 
-fn key_ptr<T:Owned>(key: GlobalDataKey<T>) -> uint {
+fn key_ptr<T:Send>(key: GlobalDataKey<T>) -> uint {
     unsafe {
         let closure: Closure = transmute(key);
         return transmute(closure.code);
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
index 0f9298595ee..06c3ecb8147 100644
--- a/src/libstd/unstable/sync.rs
+++ b/src/libstd/unstable/sync.rs
@@ -17,7 +17,7 @@ use unstable::finally::Finally;
 use unstable::intrinsics;
 use ops::Drop;
 use clone::Clone;
-use kinds::Owned;
+use kinds::Send;
 
 /// An atomically reference counted pointer.
 ///
@@ -31,7 +31,7 @@ struct AtomicRcBoxData<T> {
     data: Option<T>,
 }
 
-impl<T: Owned> UnsafeAtomicRcBox<T> {
+impl<T: Send> UnsafeAtomicRcBox<T> {
     pub fn new(data: T) -> UnsafeAtomicRcBox<T> {
         unsafe {
             let data = ~AtomicRcBoxData { count: 1, data: Some(data) };
@@ -61,7 +61,7 @@ impl<T: Owned> UnsafeAtomicRcBox<T> {
     }
 }
 
-impl<T: Owned> Clone for UnsafeAtomicRcBox<T> {
+impl<T: Send> Clone for UnsafeAtomicRcBox<T> {
     fn clone(&self) -> UnsafeAtomicRcBox<T> {
         unsafe {
             let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
@@ -144,7 +144,7 @@ pub struct Exclusive<T> {
     x: UnsafeAtomicRcBox<ExData<T>>
 }
 
-pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
+pub fn exclusive<T:Send>(user_data: T) -> Exclusive<T> {
     let data = ExData {
         lock: LittleLock(),
         failed: false,
@@ -155,14 +155,14 @@ pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
     }
 }
 
-impl<T:Owned> Clone for Exclusive<T> {
+impl<T:Send> Clone for Exclusive<T> {
     // Duplicate an exclusive ARC, as std::arc::clone.
     fn clone(&self) -> Exclusive<T> {
         Exclusive { x: self.x.clone() }
     }
 }
 
-impl<T:Owned> Exclusive<T> {
+impl<T:Send> Exclusive<T> {
     // Exactly like std::arc::mutex_arc,access(), but with the little_lock
     // instead of a proper mutex. Same reason for being unsafe.
     //
diff --git a/src/libstd/util.rs b/src/libstd/util.rs
index 6eddae17ce6..fd29d7dc14b 100644
--- a/src/libstd/util.rs
+++ b/src/libstd/util.rs
@@ -75,18 +75,14 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 }
 
 /// A non-copyable dummy type.
+#[deriving(Eq, TotalEq, Ord, TotalOrd)]
+#[unsafe_no_drop_flag]
 pub struct NonCopyable;
 
-impl NonCopyable {
-    /// Creates a dummy non-copyable structure and returns it for use.
-    pub fn new() -> NonCopyable { NonCopyable }
-}
-
 impl Drop for NonCopyable {
     fn drop(&self) { }
 }
 
-
 /// A type with no inhabitants
 pub enum Void { }
 
@@ -130,39 +126,73 @@ pub fn unreachable() -> ! {
 
 #[cfg(test)]
 mod tests {
+    use super::*;
     use option::{None, Some};
-    use util::{Void, NonCopyable, id, replace, swap};
     use either::{Either, Left, Right};
+    use sys::size_of;
+    use kinds::Drop;
 
     #[test]
-    pub fn identity_crisis() {
+    fn identity_crisis() {
         // Writing a test for the identity function. How did it come to this?
         let x = ~[(5, false)];
         //FIXME #3387 assert!(x.eq(id(copy x)));
         let y = copy x;
         assert!(x.eq(&id(y)));
     }
+
     #[test]
-    pub fn test_swap() {
+    fn test_swap() {
         let mut x = 31337;
         let mut y = 42;
         swap(&mut x, &mut y);
         assert_eq!(x, 42);
         assert_eq!(y, 31337);
     }
+
     #[test]
-    pub fn test_replace() {
-        let mut x = Some(NonCopyable::new());
+    fn test_replace() {
+        let mut x = Some(NonCopyable);
         let y = replace(&mut x, None);
         assert!(x.is_none());
         assert!(y.is_some());
     }
+
     #[test]
-    pub fn test_uninhabited() {
+    fn test_uninhabited() {
         let could_only_be_coin : Either <Void, ()> = Right (());
         match could_only_be_coin {
             Right (coin) => coin,
             Left (is_void) => is_void.uninhabited ()
         }
     }
+
+    #[test]
+    fn test_noncopyable() {
+        assert_eq!(size_of::<NonCopyable>(), 0);
+
+        // verify that `#[unsafe_no_drop_flag]` works as intended on a zero-size struct
+
+        // NOTE: uncomment after snapshot, will not parse yet
+        //static mut did_run: bool = false;
+
+        struct Foo { five: int }
+
+        impl Drop for Foo {
+            fn drop(&self) {
+                assert_eq!(self.five, 5);
+                // NOTE: uncomment after snapshot, will not parse yet
+                //unsafe {
+                    //did_run = true;
+                //}
+            }
+        }
+
+        {
+            let _a = (NonCopyable, Foo { five: 5 }, NonCopyable);
+        }
+
+        // NOTE: uncomment after snapshot, will not parse yet
+        //unsafe { assert_eq!(did_run, true); }
+    }
 }
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 56e6bacf93e..4e7943f7cfd 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -69,63 +69,6 @@ pub fn same_length<T, U>(xs: &const [T], ys: &const [U]) -> bool {
 }
 
 /**
- * Reserves capacity for exactly `n` elements in the given vector.
- *
- * If the capacity for `v` is already equal to or greater than the requested
- * capacity, then no action is taken.
- *
- * # Arguments
- *
- * * v - A vector
- * * n - The number of elements to reserve space for
- */
-#[inline]
-pub fn reserve<T>(v: &mut ~[T], n: uint) {
-    // Only make the (slow) call into the runtime if we have to
-    use managed;
-    if capacity(v) < n {
-        unsafe {
-            let ptr: **raw::VecRepr = cast::transmute(v);
-            let td = get_tydesc::<T>();
-            if ((**ptr).box_header.ref_count ==
-                managed::raw::RC_MANAGED_UNIQUE) {
-                rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t);
-            } else {
-                rustrt::vec_reserve_shared(td, ptr, n as libc::size_t);
-            }
-        }
-    }
-}
-
-/**
- * Reserves capacity for at least `n` elements in the given vector.
- *
- * This function will over-allocate in order to amortize the allocation costs
- * in scenarios where the caller may need to repeatedly reserve additional
- * space.
- *
- * If the capacity for `v` is already equal to or greater than the requested
- * capacity, then no action is taken.
- *
- * # Arguments
- *
- * * v - A vector
- * * n - The number of elements to reserve space for
- */
-pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) {
-    reserve(v, uint::next_power_of_two(n));
-}
-
-/// Returns the number of elements the vector can hold without reallocating
-#[inline]
-pub fn capacity<T>(v: &const ~[T]) -> uint {
-    unsafe {
-        let repr: **raw::VecRepr = transmute(v);
-        (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
-    }
-}
-
-/**
  * Creates and initializes an owned vector.
  *
  * Creates an owned vector of size `n_elts` and initializes the elements
@@ -179,7 +122,7 @@ pub fn to_owned<T:Copy>(t: &[T]) -> ~[T] {
 /// Creates a new vector with a capacity of `capacity`
 pub fn with_capacity<T>(capacity: uint) -> ~[T] {
     let mut vec = ~[];
-    reserve(&mut vec, capacity);
+    vec.reserve(capacity);
     vec
 }
 
@@ -238,85 +181,6 @@ pub fn build_sized_opt<A>(size: Option<uint>,
 
 // Accessors
 
-/// 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") }
-    &v[0]
-}
-
-/// Returns `Some(x)` where `x` is the first element of the slice `v`,
-/// or `None` if the vector is empty.
-pub fn head_opt<'r,T>(v: &'r [T]) -> Option<&'r T> {
-    if v.len() == 0 { None } else { Some(&v[0]) }
-}
-
-/// Returns a vector containing all but the first element of a slice
-pub fn tail<'r,T>(v: &'r [T]) -> &'r [T] { slice(v, 1, v.len()) }
-
-/// Returns a vector containing all but the first `n` elements of a slice
-pub fn tailn<'r,T>(v: &'r [T], n: uint) -> &'r [T] { slice(v, n, v.len()) }
-
-/// Returns a vector containing all but the last element of a slice
-pub fn init<'r,T>(v: &'r [T]) -> &'r [T] { slice(v, 0, v.len() - 1) }
-
-/// Returns a vector containing all but the last `n' elements of a slice
-pub fn initn<'r,T>(v: &'r [T], n: uint) -> &'r [T] {
-    slice(v, 0, v.len() - n)
-}
-
-/// 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") }
-    &v[v.len() - 1]
-}
-
-/// Returns `Some(x)` where `x` is the last element of the slice `v`, or
-/// `None` if the vector is empty.
-pub fn last_opt<'r,T>(v: &'r [T]) -> Option<&'r T> {
-    if v.len() == 0 { None } else { Some(&v[v.len() - 1]) }
-}
-
-/// Return a slice that points into another slice.
-#[inline]
-pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] {
-    assert!(start <= end);
-    assert!(end <= v.len());
-    do as_imm_buf(v) |p, _len| {
-        unsafe {
-            transmute((ptr::offset(p, start),
-                       (end - start) * sys::nonzero_size_of::<T>()))
-        }
-    }
-}
-
-/// Return a slice that points into another slice.
-#[inline]
-pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint)
-                    -> &'r mut [T] {
-    assert!(start <= end);
-    assert!(end <= v.len());
-    do as_mut_buf(v) |p, _len| {
-        unsafe {
-            transmute((ptr::mut_offset(p, start),
-                       (end - start) * sys::nonzero_size_of::<T>()))
-        }
-    }
-}
-
-/// Return a slice that points into another slice.
-#[inline]
-pub fn const_slice<'r,T>(v: &'r const [T], start: uint, end: uint)
-                      -> &'r const [T] {
-    assert!(start <= end);
-    assert!(end <= v.len());
-    do as_const_buf(v) |p, _len| {
-        unsafe {
-            transmute((ptr::const_offset(p, start),
-                       (end - start) * sys::nonzero_size_of::<T>()))
-        }
-    }
-}
-
 /// Copies
 
 /// Split the vector `v` by applying each element against the predicate `f`.
@@ -327,15 +191,15 @@ pub fn split<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut start = 0u;
     let mut result = ~[];
     while start < ln {
-        match position_between(v, start, ln, f) {
+        match position_between(v, start, ln, |t| f(t)) {
             None => break,
             Some(i) => {
-                result.push(slice(v, start, i).to_owned());
+                result.push(v.slice(start, i).to_owned());
                 start = i + 1u;
             }
         }
     }
-    result.push(slice(v, start, ln).to_owned());
+    result.push(v.slice(start, ln).to_owned());
     result
 }
 
@@ -351,17 +215,17 @@ pub fn splitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut count = n;
     let mut result = ~[];
     while start < ln && count > 0u {
-        match position_between(v, start, ln, f) {
+        match position_between(v, start, ln, |t| f(t)) {
             None => break,
             Some(i) => {
-                result.push(slice(v, start, i).to_owned());
+                result.push(v.slice(start, i).to_owned());
                 // Make sure to skip the separator.
                 start = i + 1u;
                 count -= 1u;
             }
         }
     }
-    result.push(slice(v, start, ln).to_owned());
+    result.push(v.slice(start, ln).to_owned());
     result
 }
 
@@ -376,15 +240,15 @@ pub fn rsplit<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut end = ln;
     let mut result = ~[];
     while end > 0 {
-        match rposition_between(v, 0, end, f) {
+        match rposition_between(v, 0, end, |t| f(t)) {
             None => break,
             Some(i) => {
-                result.push(slice(v, i + 1, end).to_owned());
+                result.push(v.slice(i + 1, end).to_owned());
                 end = i;
             }
         }
     }
-    result.push(slice(v, 0u, end).to_owned());
+    result.push(v.slice(0u, end).to_owned());
     reverse(result);
     result
 }
@@ -401,151 +265,21 @@ pub fn rsplitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut count = n;
     let mut result = ~[];
     while end > 0u && count > 0u {
-        match rposition_between(v, 0u, end, f) {
+        match rposition_between(v, 0u, end, |t| f(t)) {
             None => break,
             Some(i) => {
-                result.push(slice(v, i + 1u, end).to_owned());
+                result.push(v.slice(i + 1u, end).to_owned());
                 // Make sure to skip the separator.
                 end = i;
                 count -= 1u;
             }
         }
     }
-    result.push(slice(v, 0u, end).to_owned());
+    result.push(v.slice(0u, end).to_owned());
     reverse(result);
     result
 }
 
-/**
- * Partitions a vector into two new vectors: those that satisfies the
- * predicate, and those that do not.
- */
-pub fn partition<T>(v: ~[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) {
-    let mut lefts  = ~[];
-    let mut rights = ~[];
-
-    // FIXME (#4355 maybe): using v.consume here crashes
-    // do v.consume |_, elt| {
-    do consume(v) |_, elt| {
-        if f(&elt) {
-            lefts.push(elt);
-        } else {
-            rights.push(elt);
-        }
-    }
-
-    (lefts, rights)
-}
-
-/**
- * Partitions a vector into two new vectors: those that satisfies the
- * predicate, and those that do not.
- */
-pub fn partitioned<T:Copy>(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) {
-    let mut lefts  = ~[];
-    let mut rights = ~[];
-
-    for v.iter().advance |elt| {
-        if f(elt) {
-            lefts.push(copy *elt);
-        } else {
-            rights.push(copy *elt);
-        }
-    }
-
-    (lefts, rights)
-}
-
-// Mutators
-
-/// Removes the first element from a vector and return it
-pub fn shift<T>(v: &mut ~[T]) -> T {
-    unsafe {
-        assert!(!v.is_empty());
-
-        if v.len() == 1 { return v.pop() }
-
-        if v.len() == 2 {
-            let last = v.pop();
-            let first = v.pop();
-            v.push(last);
-            return first;
-        }
-
-        let ln = v.len();
-        let next_ln = v.len() - 1;
-
-        // Save the last element. We're going to overwrite its position
-        let work_elt = v.pop();
-        // We still should have room to work where what last element was
-        assert!(capacity(v) >= ln);
-        // Pretend like we have the original length so we can use
-        // the vector copy_memory to overwrite the hole we just made
-        raw::set_len(&mut *v, ln);
-
-        // Memcopy the head element (the one we want) to the location we just
-        // popped. For the moment it unsafely exists at both the head and last
-        // positions
-        {
-            let first_slice = slice(*v, 0, 1);
-            let last_slice = slice(*v, next_ln, ln);
-            raw::copy_memory(transmute(last_slice), first_slice, 1);
-        }
-
-        // Memcopy everything to the left one element
-        {
-            let init_slice = slice(*v, 0, next_ln);
-            let tail_slice = slice(*v, 1, ln);
-            raw::copy_memory(transmute(init_slice),
-                             tail_slice,
-                             next_ln);
-        }
-
-        // Set the new length. Now the vector is back to normal
-        raw::set_len(&mut *v, next_ln);
-
-        // Swap out the element we want from the end
-        let vp = raw::to_mut_ptr(*v);
-        let vp = ptr::mut_offset(vp, next_ln - 1);
-
-        ptr::replace_ptr(vp, work_elt)
-    }
-}
-
-/// Prepend an element to the vector
-pub fn unshift<T>(v: &mut ~[T], x: T) {
-    let vv = util::replace(v, ~[x]);
-    v.push_all_move(vv);
-}
-
-/// Insert an element at position i within v, shifting all
-/// elements after position i one position to the right.
-pub fn insert<T>(v: &mut ~[T], i: uint, x: T) {
-    let len = v.len();
-    assert!(i <= len);
-
-    v.push(x);
-    let mut j = len;
-    while j > i {
-        swap(*v, j, j - 1);
-        j -= 1;
-    }
-}
-
-/// Remove and return the element at position i within v, shifting
-/// all elements after position i one position to the left.
-pub fn remove<T>(v: &mut ~[T], i: uint) -> T {
-    let len = v.len();
-    assert!(i < len);
-
-    let mut j = i;
-    while j < len - 1 {
-        swap(*v, j, j + 1);
-        j += 1;
-    }
-    v.pop()
-}
-
 /// Consumes all elements, in a vector, moving them out into the / closure
 /// provided. The vector is traversed from the start to the end.
 ///
@@ -607,131 +341,6 @@ pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) {
     }
 }
 
-/// Remove the last element from a vector and return it
-pub fn pop<T>(v: &mut ~[T]) -> T {
-    let ln = v.len();
-    if ln == 0 {
-        fail!("sorry, cannot vec::pop an empty vector")
-    }
-    let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
-    unsafe {
-        let val = ptr::replace_ptr(valptr, intrinsics::init());
-        raw::set_len(v, ln - 1u);
-        val
-    }
-}
-
-/**
- * Remove an element from anywhere in the vector and return it, replacing it
- * with the last element. This does not preserve ordering, but is O(1).
- *
- * Fails if index >= length.
- */
-pub fn swap_remove<T>(v: &mut ~[T], index: uint) -> T {
-    let ln = v.len();
-    if index >= ln {
-        fail!("vec::swap_remove - index %u >= length %u", index, ln);
-    }
-    if index < ln - 1 {
-        swap(*v, index, ln - 1);
-    }
-    v.pop()
-}
-
-/// Append an element to a vector
-#[inline]
-pub fn push<T>(v: &mut ~[T], initval: T) {
-    unsafe {
-        let repr: **raw::VecRepr = transmute(&mut *v);
-        let fill = (**repr).unboxed.fill;
-        if (**repr).unboxed.alloc > fill {
-            push_fast(v, initval);
-        }
-        else {
-            push_slow(v, initval);
-        }
-    }
-}
-
-// This doesn't bother to make sure we have space.
-#[inline] // really pretty please
-unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
-    let repr: **mut raw::VecRepr = transmute(v);
-    let fill = (**repr).unboxed.fill;
-    (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
-    let p = to_unsafe_ptr(&((**repr).unboxed.data));
-    let p = ptr::offset(p, fill) as *mut T;
-    intrinsics::move_val_init(&mut(*p), initval);
-}
-
-#[inline(never)]
-fn push_slow<T>(v: &mut ~[T], initval: T) {
-    let new_len = v.len() + 1;
-    reserve_at_least(&mut *v, new_len);
-    unsafe { push_fast(v, initval) }
-}
-
-/// Iterates over the slice `rhs`, copies each element, and then appends it to
-/// the vector provided `v`. The `rhs` vector is traversed in-order.
-///
-/// # Example
-///
-/// ~~~ {.rust}
-/// let mut a = ~[1];
-/// vec::push_all(&mut a, [2, 3, 4]);
-/// assert!(a == ~[1, 2, 3, 4]);
-/// ~~~
-#[inline]
-pub fn push_all<T:Copy>(v: &mut ~[T], rhs: &const [T]) {
-    let new_len = v.len() + rhs.len();
-    reserve(&mut *v, new_len);
-
-    for uint::range(0u, rhs.len()) |i| {
-        push(&mut *v, unsafe { raw::get(rhs, i) })
-    }
-}
-
-/// Takes ownership of the vector `rhs`, moving all elements into the specified
-/// vector `v`. This does not copy any elements, and it is illegal to use the
-/// `rhs` vector after calling this method (because it is moved here).
-///
-/// # Example
-///
-/// ~~~ {.rust}
-/// let mut a = ~[~1];
-/// vec::push_all_move(&mut a, ~[~2, ~3, ~4]);
-/// assert!(a == ~[~1, ~2, ~3, ~4]);
-/// ~~~
-#[inline]
-pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
-    let new_len = v.len() + rhs.len();
-    reserve(&mut *v, new_len);
-    unsafe {
-        do as_mut_buf(rhs) |p, len| {
-            for uint::range(0, len) |i| {
-                let x = ptr::replace_ptr(ptr::mut_offset(p, i),
-                                         intrinsics::uninit());
-                push(&mut *v, x);
-            }
-        }
-        raw::set_len(&mut rhs, 0);
-    }
-}
-
-/// Shorten a vector, dropping excess elements.
-pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
-    do as_mut_buf(*v) |p, oldlen| {
-        assert!(newlen <= oldlen);
-        unsafe {
-            // This loop is optimized out for non-drop types.
-            for uint::range(newlen, oldlen) |i| {
-                ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit());
-            }
-        }
-    }
-    unsafe { raw::set_len(&mut *v, newlen); }
-}
-
 /**
  * Remove consecutive repeated elements from a vector; if the vector is
  * sorted, this removes all duplicates.
@@ -739,7 +348,8 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
 pub fn dedup<T:Eq>(v: &mut ~[T]) {
     unsafe {
         if v.len() < 1 { return; }
-        let mut (last_written, next_to_read) = (0, 1);
+        let mut last_written = 0;
+        let mut next_to_read = 1;
         do as_const_buf(*v) |p, ln| {
             // We have a mutable reference to v, so we can make arbitrary
             // changes. (cf. push and pop)
@@ -800,7 +410,7 @@ pub fn append_one<T>(lhs: ~[T], x: T) -> ~[T] {
  */
 pub fn grow<T:Copy>(v: &mut ~[T], n: uint, initval: &T) {
     let new_len = v.len() + n;
-    reserve_at_least(&mut *v, new_len);
+    v.reserve_at_least(new_len);
     let mut i: uint = 0u;
 
     while i < n {
@@ -824,7 +434,7 @@ pub fn grow<T:Copy>(v: &mut ~[T], n: uint, initval: &T) {
  */
 pub fn grow_fn<T>(v: &mut ~[T], n: uint, op: &fn(uint) -> T) {
     let new_len = v.len() + n;
-    reserve_at_least(&mut *v, new_len);
+    v.reserve_at_least(new_len);
     let mut i: uint = 0u;
     while i < n {
         v.push(op(i));
@@ -981,26 +591,6 @@ pub fn filtered<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] {
     result
 }
 
-/**
- * Like `filter()`, but in place.  Preserves order of `v`.  Linear time.
- */
-pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) {
-    let len = v.len();
-    let mut deleted: uint = 0;
-
-    for uint::range(0, len) |i| {
-        if !f(&v[i]) {
-            deleted += 1;
-        } else if deleted > 0 {
-            swap(*v, i - deleted, i);
-        }
-    }
-
-    if deleted > 0 {
-        v.truncate(len - deleted);
-    }
-}
-
 /// Flattens a vector of vectors of T into a single vector of T.
 pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] { v.concat_vec() }
 
@@ -1209,7 +799,8 @@ pub fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> {
  * Convert a vector of pairs into a pair of vectors, by reference. As unzip().
  */
 pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
-    let mut (ts, us) = (~[], ~[]);
+    let mut ts = ~[];
+    let mut us = ~[];
     for v.iter().advance |p| {
         let (t, u) = copy *p;
         ts.push(t);
@@ -1227,7 +818,8 @@ pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
  * of the i-th tuple of the input vector.
  */
 pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
-    let mut (ts, us) = (~[], ~[]);
+    let mut ts = ~[];
+    let mut us = ~[];
     do consume(v) |_i, p| {
         let (t, u) = p;
         ts.push(t);
@@ -1652,13 +1244,11 @@ impl<'self,T:Copy> CopyableVector<T> for &'self [T] {
     /// Returns a copy of `v`.
     #[inline]
     fn to_owned(&self) -> ~[T] {
-        let mut result = ~[];
-        reserve(&mut result, self.len());
+        let mut result = with_capacity(self.len());
         for self.iter().advance |e| {
             result.push(copy *e);
         }
         result
-
     }
 }
 
@@ -1689,7 +1279,14 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
     /// Return a slice that points into another slice.
     #[inline]
     fn slice(&self, start: uint, end: uint) -> &'self [T] {
-        slice(*self, start, end)
+    assert!(start <= end);
+    assert!(end <= self.len());
+        do as_imm_buf(*self) |p, _len| {
+            unsafe {
+                transmute((ptr::offset(p, start),
+                           (end - start) * sys::nonzero_size_of::<T>()))
+            }
+        }
     }
 
     #[inline]
@@ -1712,35 +1309,49 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
 
     /// Returns the first element of a vector, failing if the vector is empty.
     #[inline]
-    fn head(&self) -> &'self T { head(*self) }
+    fn head(&self) -> &'self T {
+        if self.len() == 0 { fail!("head: empty vector") }
+        &self[0]
+    }
 
-    /// Returns the first element of a vector
+    /// Returns the first element of a vector, or `None` if it is empty
     #[inline]
-    fn head_opt(&self) -> Option<&'self T> { head_opt(*self) }
+    fn head_opt(&self) -> Option<&'self T> {
+        if self.len() == 0 { None } else { Some(&self[0]) }
+    }
 
     /// Returns all but the first element of a vector
     #[inline]
-    fn tail(&self) -> &'self [T] { tail(*self) }
+    fn tail(&self) -> &'self [T] { self.slice(1, self.len()) }
 
     /// Returns all but the first `n' elements of a vector
     #[inline]
-    fn tailn(&self, n: uint) -> &'self [T] { tailn(*self, n) }
+    fn tailn(&self, n: uint) -> &'self [T] { self.slice(n, self.len()) }
 
-    /// Returns all but the last elemnt of a vector
+    /// Returns all but the last element of a vector
     #[inline]
-    fn init(&self) -> &'self [T] { init(*self) }
+    fn init(&self) -> &'self [T] {
+        self.slice(0, self.len() - 1)
+    }
 
     /// Returns all but the last `n' elemnts of a vector
     #[inline]
-    fn initn(&self, n: uint) -> &'self [T] { initn(*self, n) }
+    fn initn(&self, n: uint) -> &'self [T] {
+        self.slice(0, self.len() - n)
+    }
 
-    /// Returns the last element of a `v`, failing if the vector is empty.
+    /// Returns the last element of a vector, failing if the vector is empty.
     #[inline]
-    fn last(&self) -> &'self T { last(*self) }
+    fn last(&self) -> &'self T {
+        if self.len() == 0 { fail!("last: empty vector") }
+        &self[self.len() - 1]
+    }
 
-    /// Returns the last element of a `v`, failing if the vector is empty.
+    /// Returns the last element of a vector, or `None` if it is empty.
     #[inline]
-    fn last_opt(&self) -> Option<&'self T> { last_opt(*self) }
+    fn last_opt(&self) -> Option<&'self T> {
+            if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
+    }
 
     /**
      * Find the last index matching some predicate
@@ -1865,7 +1476,18 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
      */
     #[inline]
     fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]) {
-        partitioned(*self, f)
+        let mut lefts  = ~[];
+        let mut rights = ~[];
+
+        for self.iter().advance |elt| {
+            if f(elt) {
+                lefts.push(copy *elt);
+            } else {
+                rights.push(copy *elt);
+            }
+        }
+
+        (lefts, rights)
     }
 
     /// Returns the element at the given index, without doing bounds checking.
@@ -1877,7 +1499,13 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
 
 #[allow(missing_doc)]
 pub trait OwnedVector<T> {
+    fn reserve(&mut self, n: uint);
+    fn reserve_at_least(&mut self, n: uint);
+    fn capacity(&self) -> uint;
+
     fn push(&mut self, t: T);
+    unsafe fn push_fast(&mut self, t: T);
+
     fn push_all_move(&mut self, rhs: ~[T]);
     fn pop(&mut self) -> T;
     fn shift(&mut self) -> T;
@@ -1895,54 +1523,276 @@ pub trait OwnedVector<T> {
 }
 
 impl<T> OwnedVector<T> for ~[T] {
+    /**
+     * Reserves capacity for exactly `n` elements in the given vector.
+     *
+     * If the capacity for `self` is already equal to or greater than the requested
+     * capacity, then no action is taken.
+     *
+     * # Arguments
+     *
+     * * n - The number of elements to reserve space for
+     */
     #[inline]
-    fn push(&mut self, t: T) {
-        push(self, t);
+    fn reserve(&mut self, n: uint) {
+        // Only make the (slow) call into the runtime if we have to
+        use managed;
+        if self.capacity() < n {
+            unsafe {
+                let ptr: **raw::VecRepr = cast::transmute(self);
+                let td = get_tydesc::<T>();
+                if ((**ptr).box_header.ref_count ==
+                    managed::raw::RC_MANAGED_UNIQUE) {
+                    rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t);
+                } else {
+                    rustrt::vec_reserve_shared(td, ptr, n as libc::size_t);
+                }
+            }
+        }
     }
 
+    /**
+     * Reserves capacity for at least `n` elements in the given vector.
+     *
+     * This function will over-allocate in order to amortize the allocation costs
+     * in scenarios where the caller may need to repeatedly reserve additional
+     * space.
+     *
+     * If the capacity for `self` is already equal to or greater than the requested
+     * capacity, then no action is taken.
+     *
+     * # Arguments
+     *
+     * * n - The number of elements to reserve space for
+     */
+    fn reserve_at_least(&mut self, n: uint) {
+        self.reserve(uint::next_power_of_two(n));
+    }
+
+    /// Returns the number of elements the vector can hold without reallocating.
     #[inline]
-    fn push_all_move(&mut self, rhs: ~[T]) {
-        push_all_move(self, rhs);
+    fn capacity(&self) -> uint {
+        unsafe {
+            let repr: **raw::VecRepr = transmute(self);
+            (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
+        }
     }
 
+    /// Append an element to a vector
     #[inline]
+    fn push(&mut self, t: T) {
+        unsafe {
+            let repr: **raw::VecRepr = transmute(&mut *self);
+            let fill = (**repr).unboxed.fill;
+            if (**repr).unboxed.alloc <= fill {
+                // need more space
+                reserve_no_inline(self);
+            }
+
+            self.push_fast(t);
+        }
+
+        // this peculiar function is because reserve_at_least is very
+        // large (because of reserve), and will be inlined, which
+        // makes push too large.
+        #[inline(never)]
+        fn reserve_no_inline<T>(v: &mut ~[T]) {
+            let new_len = v.len() + 1;
+            v.reserve_at_least(new_len);
+        }
+    }
+
+    // This doesn't bother to make sure we have space.
+    #[inline] // really pretty please
+    unsafe fn push_fast(&mut self, t: T) {
+        let repr: **mut raw::VecRepr = transmute(self);
+        let fill = (**repr).unboxed.fill;
+        (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
+        let p = to_unsafe_ptr(&((**repr).unboxed.data));
+        let p = ptr::offset(p, fill) as *mut T;
+        intrinsics::move_val_init(&mut(*p), t);
+    }
+
+    /// Takes ownership of the vector `rhs`, moving all elements into
+    /// the current vector. This does not copy any elements, and it is
+    /// illegal to use the `rhs` vector after calling this method
+    /// (because it is moved here).
+    ///
+    /// # Example
+    ///
+    /// ~~~ {.rust}
+    /// let mut a = ~[~1];
+    /// a.push_all_move(~[~2, ~3, ~4]);
+    /// assert!(a == ~[~1, ~2, ~3, ~4]);
+    /// ~~~
+    #[inline]
+    fn push_all_move(&mut self, mut rhs: ~[T]) {
+        let new_len = self.len() + rhs.len();
+        self.reserve(new_len);
+        unsafe {
+            do as_mut_buf(rhs) |p, len| {
+                for uint::range(0, len) |i| {
+                    let x = ptr::replace_ptr(ptr::mut_offset(p, i),
+                                             intrinsics::uninit());
+                    self.push(x);
+                }
+            }
+            raw::set_len(&mut rhs, 0);
+        }
+    }
+
+    /// Remove the last element from a vector and return it
     fn pop(&mut self) -> T {
-        pop(self)
+        let ln = self.len();
+        if ln == 0 {
+            fail!("sorry, cannot pop an empty vector")
+        }
+        let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]);
+        unsafe {
+            let val = ptr::replace_ptr(valptr, intrinsics::init());
+            raw::set_len(self, ln - 1u);
+            val
+        }
     }
 
-    #[inline]
+    /// Removes the first element from a vector and return it
     fn shift(&mut self) -> T {
-        shift(self)
+        unsafe {
+            assert!(!self.is_empty());
+
+            if self.len() == 1 { return self.pop() }
+
+            if self.len() == 2 {
+                let last = self.pop();
+                let first = self.pop();
+                self.push(last);
+                return first;
+            }
+
+            let ln = self.len();
+            let next_ln = self.len() - 1;
+
+            // Save the last element. We're going to overwrite its position
+            let work_elt = self.pop();
+            // We still should have room to work where what last element was
+            assert!(self.capacity() >= ln);
+            // Pretend like we have the original length so we can use
+            // the vector copy_memory to overwrite the hole we just made
+            raw::set_len(self, ln);
+
+            // Memcopy the head element (the one we want) to the location we just
+            // popped. For the moment it unsafely exists at both the head and last
+            // positions
+            {
+                let first_slice = self.slice(0, 1);
+                let last_slice = self.slice(next_ln, ln);
+                raw::copy_memory(transmute(last_slice), first_slice, 1);
+            }
+
+            // Memcopy everything to the left one element
+            {
+                let init_slice = self.slice(0, next_ln);
+                let tail_slice = self.slice(1, ln);
+                raw::copy_memory(transmute(init_slice),
+                                 tail_slice,
+                                 next_ln);
+            }
+
+            // Set the new length. Now the vector is back to normal
+            raw::set_len(self, next_ln);
+
+            // Swap out the element we want from the end
+            let vp = raw::to_mut_ptr(*self);
+            let vp = ptr::mut_offset(vp, next_ln - 1);
+
+            ptr::replace_ptr(vp, work_elt)
+        }
     }
 
-    #[inline]
+    /// Prepend an element to the vector
     fn unshift(&mut self, x: T) {
-        unshift(self, x)
+        let v = util::replace(self, ~[x]);
+        self.push_all_move(v);
     }
 
-    #[inline]
+    /// Insert an element at position i within v, shifting all
+    /// elements after position i one position to the right.
     fn insert(&mut self, i: uint, x:T) {
-        insert(self, i, x)
+        let len = self.len();
+        assert!(i <= len);
+
+        self.push(x);
+        let mut j = len;
+        while j > i {
+            swap(*self, j, j - 1);
+            j -= 1;
+        }
     }
 
-    #[inline]
+    /// Remove and return the element at position i within v, shifting
+    /// all elements after position i one position to the left.
     fn remove(&mut self, i: uint) -> T {
-        remove(self, i)
+        let len = self.len();
+        assert!(i < len);
+
+        let mut j = i;
+        while j < len - 1 {
+            swap(*self, j, j + 1);
+            j += 1;
+        }
+        self.pop()
     }
 
-    #[inline]
+    /**
+     * Remove an element from anywhere in the vector and return it, replacing it
+     * with the last element. This does not preserve ordering, but is O(1).
+     *
+     * Fails if index >= length.
+     */
     fn swap_remove(&mut self, index: uint) -> T {
-        swap_remove(self, index)
+        let ln = self.len();
+        if index >= ln {
+            fail!("vec::swap_remove - index %u >= length %u", index, ln);
+        }
+        if index < ln - 1 {
+            swap(*self, index, ln - 1);
+        }
+        self.pop()
     }
 
-    #[inline]
+    /// Shorten a vector, dropping excess elements.
     fn truncate(&mut self, newlen: uint) {
-        truncate(self, newlen);
+        do as_mut_buf(*self) |p, oldlen| {
+            assert!(newlen <= oldlen);
+            unsafe {
+                // This loop is optimized out for non-drop types.
+                for uint::range(newlen, oldlen) |i| {
+                    ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit());
+                }
+            }
+        }
+        unsafe { raw::set_len(self, newlen); }
     }
 
-    #[inline]
+
+    /**
+     * Like `filter()`, but in place.  Preserves order of `v`.  Linear time.
+     */
     fn retain(&mut self, f: &fn(t: &T) -> bool) {
-        retain(self, f);
+        let len = self.len();
+        let mut deleted: uint = 0;
+
+        for uint::range(0, len) |i| {
+            if !f(&self[i]) {
+                deleted += 1;
+            } else if deleted > 0 {
+                swap(*self, i - deleted, i);
+            }
+        }
+
+        if deleted > 0 {
+            self.truncate(len - deleted);
+        }
     }
 
     #[inline]
@@ -1966,7 +1816,18 @@ impl<T> OwnedVector<T> for ~[T] {
      */
     #[inline]
     fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]) {
-        partition(self, f)
+        let mut lefts  = ~[];
+        let mut rights = ~[];
+
+        do self.consume |_, elt| {
+            if f(&elt) {
+                lefts.push(elt);
+            } else {
+                rights.push(elt);
+            }
+        }
+
+        (lefts, rights)
     }
 
     #[inline]
@@ -1988,9 +1849,24 @@ pub trait OwnedCopyableVector<T:Copy> {
 }
 
 impl<T:Copy> OwnedCopyableVector<T> for ~[T] {
+    /// Iterates over the slice `rhs`, copies each element, and then appends it to
+    /// the vector provided `v`. The `rhs` vector is traversed in-order.
+    ///
+    /// # Example
+    ///
+    /// ~~~ {.rust}
+    /// let mut a = ~[1];
+    /// a.push_all([2, 3, 4]);
+    /// assert!(a == ~[1, 2, 3, 4]);
+    /// ~~~
     #[inline]
     fn push_all(&mut self, rhs: &const [T]) {
-        push_all(self, rhs);
+        let new_len = self.len() + rhs.len();
+        self.reserve(new_len);
+
+        for uint::range(0u, rhs.len()) |i| {
+            self.push(unsafe { raw::get(rhs, i) })
+        }
     }
 
     #[inline]
@@ -2042,9 +1918,17 @@ pub trait MutableVector<'self, T> {
 }
 
 impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
+    /// Return a slice that points into another slice.
     #[inline]
     fn mut_slice(self, start: uint, end: uint) -> &'self mut [T] {
-        mut_slice(self, start, end)
+        assert!(start <= end);
+        assert!(end <= self.len());
+        do as_mut_buf(self) |p, _len| {
+            unsafe {
+                transmute((ptr::mut_offset(p, start),
+                           (end - start) * sys::nonzero_size_of::<T>()))
+            }
+        }
     }
 
     #[inline]
@@ -2462,6 +2346,7 @@ impl<T> FromIter<T> for ~[T]{
     }
 }
 
+#[cfg(stage0)]
 impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
     pub fn from_iterator(iterator: &mut T) -> ~[A] {
         let mut xs = ~[];
@@ -2472,7 +2357,8 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
     }
 }
 
-/* FIXME: #7341 - ICE
+
+#[cfg(not(stage0))]
 impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
     pub fn from_iterator(iterator: &mut T) -> ~[A] {
         let (lower, _) = iterator.size_hint();
@@ -2483,7 +2369,7 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
         xs
     }
 }
-*/
+
 
 #[cfg(test)]
 mod tests {
@@ -2713,7 +2599,7 @@ mod tests {
     fn test_slice() {
         // Test fixed length vector.
         let vec_fixed = [1, 2, 3, 4];
-        let v_a = slice(vec_fixed, 1u, vec_fixed.len()).to_owned();
+        let v_a = vec_fixed.slice(1u, vec_fixed.len()).to_owned();
         assert_eq!(v_a.len(), 3u);
         assert_eq!(v_a[0], 2);
         assert_eq!(v_a[1], 3);
@@ -2721,14 +2607,14 @@ mod tests {
 
         // Test on stack.
         let vec_stack = &[1, 2, 3];
-        let v_b = slice(vec_stack, 1u, 3u).to_owned();
+        let v_b = vec_stack.slice(1u, 3u).to_owned();
         assert_eq!(v_b.len(), 2u);
         assert_eq!(v_b[0], 2);
         assert_eq!(v_b[1], 3);
 
         // Test on managed heap.
         let vec_managed = @[1, 2, 3, 4, 5];
-        let v_c = slice(vec_managed, 0u, 3u).to_owned();
+        let v_c = vec_managed.slice(0u, 3u).to_owned();
         assert_eq!(v_c.len(), 3u);
         assert_eq!(v_c[0], 1);
         assert_eq!(v_c[1], 2);
@@ -2736,7 +2622,7 @@ mod tests {
 
         // Test on exchange heap.
         let vec_unique = ~[1, 2, 3, 4, 5, 6];
-        let v_d = slice(vec_unique, 1u, 6u).to_owned();
+        let v_d = vec_unique.slice(1u, 6u).to_owned();
         assert_eq!(v_d.len(), 5u);
         assert_eq!(v_d[0], 2);
         assert_eq!(v_d[1], 3);
@@ -3329,11 +3215,10 @@ mod tests {
 
     #[test]
     fn test_partition() {
-        // FIXME (#4355 maybe): using v.partition here crashes
-        assert_eq!(partition(~[], |x: &int| *x < 3), (~[], ~[]));
-        assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 4), (~[1, 2, 3], ~[]));
-        assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 2), (~[1], ~[2, 3]));
-        assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 0), (~[], ~[1, 2, 3]));
+        assert_eq!((~[]).partition(|x: &int| *x < 3), (~[], ~[]));
+        assert_eq!((~[1, 2, 3]).partition(|x: &int| *x < 4), (~[1, 2, 3], ~[]));
+        assert_eq!((~[1, 2, 3]).partition(|x: &int| *x < 2), (~[1], ~[2, 3]));
+        assert_eq!((~[1, 2, 3]).partition(|x: &int| *x < 0), (~[], ~[1, 2, 3]));
     }
 
     #[test]
@@ -3453,11 +3338,11 @@ mod tests {
     #[test]
     fn test_capacity() {
         let mut v = ~[0u64];
-        reserve(&mut v, 10u);
-        assert_eq!(capacity(&v), 10u);
+        v.reserve(10u);
+        assert_eq!(v.capacity(), 10u);
         let mut v = ~[0u32];
-        reserve(&mut v, 10u);
-        assert_eq!(capacity(&v), 10u);
+        v.reserve(10u);
+        assert_eq!(v.capacity(), 10u);
     }
 
     #[test]
@@ -3981,11 +3866,11 @@ mod tests {
     fn test_vec_zero() {
         use num::Zero;
         macro_rules! t (
-            ($ty:ty) => {
+            ($ty:ty) => {{
                 let v: $ty = Zero::zero();
                 assert!(v.is_empty());
                 assert!(v.is_zero());
-            }
+            }}
         );
 
         t!(&[int]);
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index feb03896558..bc432c4c7b0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -17,17 +17,14 @@ use parse::token::{interner_get, str_to_ident};
 
 use std::hashmap::HashMap;
 use std::option::Option;
-use std::to_bytes::IterBytes;
-use std::to_bytes;
 use std::to_str::ToStr;
 use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
 
-
 // an identifier contains a Name (index into the interner
 // table) and a SyntaxContext to track renaming and
 // macro expansion per Flatt et al., "Macros
 // That Work Together"
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct ident { name: Name, ctxt: SyntaxContext }
 
 /// Construct an identifier with the given name and an empty context:
@@ -57,7 +54,7 @@ pub struct SCTable {
 pub static empty_ctxt : uint = 0;
 pub static illegal_ctxt : uint = 1;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum SyntaxContext_ {
     EmptyCtxt,
     Mark (Mrk,SyntaxContext),
@@ -86,42 +83,28 @@ impl<S:Encoder> Encodable<S> for ident {
     }
 }
 
+#[deriving(IterBytes)]
 impl<D:Decoder> Decodable<D> for ident {
     fn decode(d: &mut D) -> ident {
         str_to_ident(d.read_str())
     }
 }
 
-impl to_bytes::IterBytes for ident {
-    #[inline]
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.name.iter_bytes(lsb0, f)
-    }
-}
-
 // Functions may or may not have names.
 pub type fn_ident = Option<ident>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Lifetime {
     id: node_id,
     span: span,
     ident: ident
 }
 
-impl to_bytes::IterBytes for Lifetime {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.id.iter_bytes(lsb0, f) &&
-        self.span.iter_bytes(lsb0, f) &&
-        self.ident.iter_bytes(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.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Path {
     span: span,
     global: bool,
@@ -134,7 +117,7 @@ pub type crate_num = int;
 
 pub type node_id = int;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct def_id {
     crate: crate_num,
     node: node_id,
@@ -143,24 +126,24 @@ pub struct def_id {
 pub static local_crate: crate_num = 0;
 pub static crate_node_id: node_id = 0;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 // 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
-// detects Copy, Send, Owned, and Const.
+// detects Copy, Send, Send, and Freeze.
 pub enum TyParamBound {
     TraitTyParamBound(@trait_ref),
     RegionTyParamBound
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct TyParam {
     ident: ident,
     id: node_id,
     bounds: @OptVec<TyParamBound>
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Generics {
     lifetimes: OptVec<Lifetime>,
     ty_params: OptVec<TyParam>
@@ -178,7 +161,7 @@ impl Generics {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum def {
     def_fn(def_id, purity),
     def_static_method(/* method */ def_id,
@@ -205,7 +188,8 @@ pub enum def {
     def_struct(def_id),
     def_typaram_binder(node_id), /* struct, impl or trait with ty params */
     def_region(node_id),
-    def_label(node_id)
+    def_label(node_id),
+    def_method(def_id /* method */, Option<def_id> /* trait */),
 }
 
 
@@ -215,7 +199,7 @@ pub type crate_cfg = ~[@meta_item];
 
 pub type crate = spanned<crate_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct crate_ {
     module: _mod,
     attrs: ~[attribute],
@@ -224,7 +208,7 @@ pub struct crate_ {
 
 pub type meta_item = spanned<meta_item_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum meta_item_ {
     meta_word(@str),
     meta_list(@str, ~[@meta_item]),
@@ -233,7 +217,7 @@ pub enum meta_item_ {
 
 pub type blk = spanned<blk_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct blk_ {
     view_items: ~[@view_item],
     stmts: ~[@stmt],
@@ -242,40 +226,26 @@ pub struct blk_ {
     rules: blk_check_mode,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct pat {
     id: node_id,
     node: pat_,
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct field_pat {
     ident: ident,
     pat: @pat,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum binding_mode {
     bind_by_ref(mutability),
     bind_infer
 }
 
-impl to_bytes::IterBytes for binding_mode {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-          bind_by_ref(ref m) => {
-              0u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f)
-          }
-
-          bind_infer => {
-              1u8.iter_bytes(lsb0, f)
-          }
-        }
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -300,28 +270,16 @@ pub enum pat_ {
     pat_vec(~[@pat], Option<@pat>, ~[@pat])
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum mutability { m_mutbl, m_imm, m_const, }
 
-impl to_bytes::IterBytes for mutability {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum Sigil {
     BorrowedSigil,
     OwnedSigil,
     ManagedSigil
 }
 
-impl to_bytes::IterBytes for Sigil {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as uint).iter_bytes(lsb0, f)
-    }
-}
-
 impl ToStr for Sigil {
     fn to_str(&self) -> ~str {
         match *self {
@@ -332,7 +290,7 @@ impl ToStr for Sigil {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum vstore {
     // FIXME (#3469): Change uint to @expr (actually only constant exprs)
     vstore_fixed(Option<uint>),     // [1,2,3,4]
@@ -341,7 +299,7 @@ pub enum vstore {
     vstore_slice(Option<@Lifetime>) // &'foo? [1,2,3,4]
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum expr_vstore {
     expr_vstore_uniq,                  // ~[1,2,3,4]
     expr_vstore_box,                   // @[1,2,3,4]
@@ -350,7 +308,7 @@ pub enum expr_vstore {
     expr_vstore_mut_slice,             // &mut [1,2,3,4]
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum binop {
     add,
     subtract,
@@ -372,7 +330,7 @@ pub enum binop {
     gt,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum unop {
     box(mutability),
     uniq(mutability),
@@ -383,7 +341,7 @@ pub enum unop {
 
 pub type stmt = spanned<stmt_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum stmt_ {
     // could be an item or a local (let) binding:
     stmt_decl(@decl, node_id),
@@ -400,7 +358,7 @@ pub enum stmt_ {
 
 // FIXME (pending discussion of #1697, #2178...): local should really be
 // a refinement on pat.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct local_ {
     is_mutbl: bool,
     ty: @Ty,
@@ -413,7 +371,7 @@ pub type local = spanned<local_>;
 
 pub type decl = spanned<decl_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum decl_ {
     // a local (let) binding:
     decl_local(@local),
@@ -421,14 +379,14 @@ pub enum decl_ {
     decl_item(@item),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct arm {
     pats: ~[@pat],
     guard: Option<@expr>,
     body: blk,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct field_ {
     ident: ident,
     expr: @expr,
@@ -436,10 +394,10 @@ pub struct field_ {
 
 pub type field = spanned<field_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum blk_check_mode { default_blk, unsafe_blk, }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct expr {
     id: node_id,
     node: expr_,
@@ -459,14 +417,14 @@ impl expr {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum CallSugar {
     NoSugar,
     DoSugar,
     ForSugar
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
@@ -537,7 +495,7 @@ pub enum expr_ {
 // else knows what to do with them, so you'll probably get a syntax
 // error.
 //
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 pub enum token_tree {
     // a single token
@@ -610,7 +568,7 @@ pub enum token_tree {
 //
 pub type matcher = spanned<matcher_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum matcher_ {
     // match one token
     match_tok(::parse::token::Token),
@@ -623,14 +581,14 @@ pub enum matcher_ {
 
 pub type mac = spanned<mac_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum mac_ {
     mac_invoc_tt(@Path,~[token_tree]),   // new macro-invocation
 }
 
 pub type lit = spanned<lit_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum lit_ {
     lit_str(@str),
     lit_int(i64, int_ty),
@@ -644,13 +602,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.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct mt {
     ty: @Ty,
     mutbl: mutability,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct ty_field_ {
     ident: ident,
     mt: mt,
@@ -658,7 +616,7 @@ pub struct ty_field_ {
 
 pub type ty_field = spanned<ty_field_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct ty_method {
     ident: ident,
     attrs: ~[attribute],
@@ -670,7 +628,7 @@ pub struct ty_method {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 // A trait method is either required (meaning it doesn't have an
 // implementation, just a signature) or provided (meaning it has a default
 // implementation).
@@ -679,7 +637,7 @@ pub enum trait_method {
     provided(@method),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 impl ToStr for int_ty {
@@ -688,13 +646,7 @@ impl ToStr for int_ty {
     }
 }
 
-impl to_bytes::IterBytes for int_ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
 
 impl ToStr for uint_ty {
@@ -703,13 +655,7 @@ impl ToStr for uint_ty {
     }
 }
 
-impl to_bytes::IterBytes for uint_ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum float_ty { ty_f, ty_f32, ty_f64, }
 
 impl ToStr for float_ty {
@@ -718,14 +664,8 @@ impl ToStr for float_ty {
     }
 }
 
-impl to_bytes::IterBytes for float_ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
 // NB Eq method appears below.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Ty {
     id: node_id,
     node: ty_,
@@ -733,7 +673,7 @@ pub struct Ty {
 }
 
 // Not represented directly in the AST, referred to by name through a ty_path.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum prim_ty {
     ty_int(int_ty),
     ty_uint(uint_ty),
@@ -742,12 +682,13 @@ pub enum prim_ty {
     ty_bool,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum Onceness {
     Once,
     Many
 }
 
+#[deriving(IterBytes)]
 impl ToStr for Onceness {
     fn to_str(&self) -> ~str {
         match *self {
@@ -757,13 +698,7 @@ impl ToStr for Onceness {
     }
 }
 
-impl to_bytes::IterBytes for Onceness {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as uint).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct TyClosure {
     sigil: Sigil,
     region: Option<@Lifetime>,
@@ -778,7 +713,7 @@ pub struct TyClosure {
     bounds: Option<OptVec<TyParamBound>>,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct TyBareFn {
     purity: purity,
     abis: AbiSet,
@@ -786,7 +721,7 @@ pub struct TyBareFn {
     decl: fn_decl
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
@@ -807,19 +742,13 @@ pub enum ty_ {
     ty_infer,
 }
 
-impl to_bytes::IterBytes for Ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.span.lo.iter_bytes(lsb0, f) && self.span.hi.iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum asm_dialect {
     asm_att,
     asm_intel
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct inline_asm {
     asm: @str,
     clobbers: @str,
@@ -830,7 +759,7 @@ pub struct inline_asm {
     dialect: asm_dialect
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct arg {
     is_mutbl: bool,
     ty: @Ty,
@@ -838,20 +767,21 @@ pub struct arg {
     id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct fn_decl {
     inputs: ~[arg],
     output: @Ty,
     cf: ret_style,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum purity {
     unsafe_fn, // declared with "unsafe fn"
     impure_fn, // declared with "fn"
     extern_fn, // declared with "extern fn"
 }
 
+#[deriving(IterBytes)]
 impl ToStr for purity {
     fn to_str(&self) -> ~str {
         match *self {
@@ -862,26 +792,14 @@ impl ToStr for purity {
     }
 }
 
-impl to_bytes::IterBytes for purity {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum ret_style {
     noreturn, // functions with return type _|_ that always
               // raise an error or exit (i.e. never return to the caller)
     return_val, // everything else
 }
 
-impl to_bytes::IterBytes for ret_style {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum explicit_self_ {
     sty_static,                                // no self
     sty_value,                                 // `self`
@@ -890,27 +808,9 @@ pub enum explicit_self_ {
     sty_uniq(mutability)                       // `~self`
 }
 
-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) => {
-                2u8.iter_bytes(lsb0, f) && lft.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f)
-            }
-            sty_box(ref mutbl) => {
-                3u8.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f)
-            }
-            sty_uniq(ref mutbl) => {
-                4u8.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 pub type explicit_self = spanned<explicit_self_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct method {
     ident: ident,
     attrs: ~[attribute],
@@ -925,17 +825,17 @@ pub struct method {
     vis: visibility,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct _mod {
     view_items: ~[@view_item],
     items: ~[@item],
 }
 
 // Foreign mods can be named or anonymous
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum foreign_mod_sort { named, anonymous }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct foreign_mod {
     sort: foreign_mod_sort,
     abis: AbiSet,
@@ -943,24 +843,24 @@ pub struct foreign_mod {
     items: ~[@foreign_item],
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct variant_arg {
     ty: @Ty,
     id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum variant_kind {
     tuple_variant_kind(~[variant_arg]),
     struct_variant_kind(@struct_def),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct enum_def {
     variants: ~[variant],
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct variant_ {
     name: ident,
     attrs: ~[attribute],
@@ -972,7 +872,7 @@ pub struct variant_ {
 
 pub type variant = spanned<variant_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct path_list_ident_ {
     name: ident,
     id: node_id,
@@ -982,7 +882,7 @@ pub type path_list_ident = spanned<path_list_ident_>;
 
 pub type view_path = spanned<view_path_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum view_path_ {
 
     // quux = foo::bar::baz
@@ -999,7 +899,7 @@ pub enum view_path_ {
     view_path_list(@Path, ~[path_list_ident], node_id)
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct view_item {
     node: view_item_,
     attrs: ~[attribute],
@@ -1007,7 +907,7 @@ pub struct view_item {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum view_item_ {
     view_item_extern_mod(ident, ~[@meta_item], node_id),
     view_item_use(~[@view_path]),
@@ -1019,11 +919,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.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum attr_style { attr_outer, attr_inner, }
 
 // doc-comments are promoted to attributes that have is_sugared_doc = true
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct attribute_ {
     style: attr_style,
     value: @meta_item,
@@ -1037,17 +937,17 @@ 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).
  */
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct trait_ref {
     path: @Path,
     ref_id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum visibility { public, private, inherited }
 
 impl visibility {
-    fn inherit_from(&self, parent_visibility: visibility) -> visibility {
+    pub fn inherit_from(&self, parent_visibility: visibility) -> visibility {
         match self {
             &inherited => parent_visibility,
             &public | &private => *self
@@ -1055,7 +955,7 @@ impl visibility {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct struct_field_ {
     kind: struct_field_kind,
     id: node_id,
@@ -1065,13 +965,13 @@ pub struct struct_field_ {
 
 pub type struct_field = spanned<struct_field_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum struct_field_kind {
     named_field(ident, visibility),
     unnamed_field   // element of a tuple-like struct
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct struct_def {
     fields: ~[@struct_field], /* fields, not including ctor */
     /* ID of the constructor. This is only used for tuple- or enum-like
@@ -1083,7 +983,7 @@ pub struct struct_def {
   FIXME (#3300): Should allow items to be anonymous. Right now
   we just use dummy names for anon items.
  */
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct item {
     ident: ident,
     attrs: ~[attribute],
@@ -1093,7 +993,7 @@ pub struct item {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum item_ {
     item_static(@Ty, mutability, @expr),
     item_fn(fn_decl, purity, AbiSet, Generics, blk),
@@ -1111,7 +1011,7 @@ pub enum item_ {
     item_mac(mac),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct foreign_item {
     ident: ident,
     attrs: ~[attribute],
@@ -1121,7 +1021,7 @@ pub struct foreign_item {
     vis: visibility,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum foreign_item_ {
     foreign_item_fn(fn_decl, purity, Generics),
     foreign_item_static(@Ty, /* is_mutbl */ bool),
@@ -1130,7 +1030,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.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 9ba7cb3c818..9439f45be21 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -19,7 +19,6 @@ use visit;
 use std::hashmap::HashMap;
 use std::int;
 use std::option;
-use std::to_bytes;
 use std::cast;
 use std::local_data;
 
@@ -59,7 +58,7 @@ pub fn def_id_of_def(d: def) -> def_id {
       def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
       def_foreign_mod(id) | def_static(id, _) |
       def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
-      def_use(id) | def_struct(id) | def_trait(id) => {
+      def_use(id) | def_struct(id) | def_trait(id) | def_method(id, _) => {
         id
       }
       def_arg(id, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
@@ -194,14 +193,6 @@ pub fn is_call_expr(e: @expr) -> bool {
     match e.node { expr_call(*) => true, _ => false }
 }
 
-// This makes def_id hashable
-impl to_bytes::IterBytes for def_id {
-    #[inline]
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.crate.iter_bytes(lsb0, f) && self.node.iter_bytes(lsb0, f)
-    }
-}
-
 pub fn block_from_expr(e: @expr) -> blk {
     let blk_ = default_block(~[], option::Some::<@expr>(e), e.id);
     return spanned {node: blk_, span: e.span};
@@ -544,18 +535,18 @@ pub fn walk_pat(pat: @pat, it: &fn(@pat) -> bool) -> bool {
     match pat.node {
         pat_ident(_, _, Some(p)) => walk_pat(p, it),
         pat_struct(_, ref fields, _) => {
-            fields.iter().advance(|f| walk_pat(f.pat, it))
+            fields.iter().advance(|f| walk_pat(f.pat, |p| it(p)))
         }
         pat_enum(_, Some(ref s)) | pat_tup(ref s) => {
-            s.iter().advance(|&p| walk_pat(p, it))
+            s.iter().advance(|&p| walk_pat(p, |p| it(p)))
         }
         pat_box(s) | pat_uniq(s) | pat_region(s) => {
             walk_pat(s, it)
         }
         pat_vec(ref before, ref slice, ref after) => {
-            before.iter().advance(|&p| walk_pat(p, it)) &&
-                slice.iter().advance(|&p| walk_pat(p, it)) &&
-                after.iter().advance(|&p| walk_pat(p, it))
+            before.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
+                slice.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
+                after.iter().advance(|&p| walk_pat(p, |p| it(p)))
         }
         pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) |
         pat_enum(_, _) => {
@@ -619,6 +610,15 @@ pub enum Privacy {
     Public
 }
 
+/// Returns true if the given pattern consists solely of an identifier
+/// and false otherwise.
+pub fn pat_is_ident(pat: @ast::pat) -> bool {
+    match pat.node {
+        ast::pat_ident(*) => true,
+        _ => false,
+    }
+}
+
 // HYGIENE FUNCTIONS
 
 /// Construct an identifier with the given name and an empty context:
@@ -695,7 +695,7 @@ pub fn new_sctable_internal() -> SCTable {
 pub fn get_sctable() -> @mut SCTable {
     unsafe {
         let sctable_key = (cast::transmute::<(uint, uint),
-                           &fn(v: @@mut SCTable)>(
+                           &fn:Copy(v: @@mut SCTable)>(
                                (-4 as uint, 0u)));
         match local_data::local_data_get(sctable_key) {
             None => {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 5efc96e16b5..bcf617c56ae 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -22,7 +22,6 @@ source code snippets, etc.
 */
 
 use std::cmp;
-use std::to_bytes;
 use std::uint;
 use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -32,12 +31,12 @@ pub trait Pos {
 }
 
 /// A byte offset
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct BytePos(uint);
 /// A character offset. Because of multibyte utf8 characters, a byte offset
 /// is not equivalent to a character offset. The CodeMap will convert BytePos
 /// values to CharPos values as necessary.
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct CharPos(uint);
 
 // XXX: Lots of boilerplate in these impls, but so far my attempts to fix
@@ -67,12 +66,6 @@ impl Sub<BytePos, BytePos> for BytePos {
     }
 }
 
-impl to_bytes::IterBytes for BytePos {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (**self).iter_bytes(lsb0, f)
-    }
-}
-
 impl Pos for CharPos {
     fn from_uint(n: uint) -> CharPos { CharPos(n) }
     fn to_uint(&self) -> uint { **self }
@@ -85,12 +78,6 @@ impl cmp::Ord for CharPos {
     fn gt(&self, other: &CharPos) -> bool { **self > **other }
 }
 
-impl to_bytes::IterBytes for CharPos {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (**self).iter_bytes(lsb0, f)
-    }
-}
-
 impl Add<CharPos,CharPos> for CharPos {
     fn add(&self, rhs: &CharPos) -> CharPos {
         CharPos(**self + **rhs)
@@ -109,13 +96,14 @@ are *absolute* positions from the beginning of the codemap, not positions
 relative to FileMaps. Methods on the CodeMap can be used to relate spans back
 to the original source.
 */
+#[deriving(IterBytes)]
 pub struct span {
     lo: BytePos,
     hi: BytePos,
     expn_info: Option<@ExpnInfo>
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct spanned<T> { node: T, span: span }
 
 impl cmp::Eq for span {
@@ -138,14 +126,6 @@ impl<D:Decoder> Decodable<D> for span {
     }
 }
 
-impl to_bytes::IterBytes for span {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.lo.iter_bytes(lsb0, f) &&
-        self.hi.iter_bytes(lsb0, f) &&
-        self.expn_info.iter_bytes(lsb0, f)
-    }
-}
-
 pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> spanned<T> {
     respan(mk_sp(lo, hi), t)
 }
@@ -191,40 +171,21 @@ pub struct LocWithOpt {
 // used to be structural records. Better names, anyone?
 pub struct FileMapAndLine {fm: @FileMap, line: uint}
 pub struct FileMapAndBytePos {fm: @FileMap, pos: BytePos}
+#[deriving(IterBytes)]
 pub struct NameAndSpan {name: @str, span: Option<span>}
 
-impl to_bytes::IterBytes for NameAndSpan {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.name.iter_bytes(lsb0, f) && self.span.iter_bytes(lsb0, f)
-    }
-}
-
+#[deriving(IterBytes)]
 pub struct CallInfo {
     call_site: span,
     callee: NameAndSpan
 }
 
-impl to_bytes::IterBytes for CallInfo {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.call_site.iter_bytes(lsb0, f) && self.callee.iter_bytes(lsb0, f)
-    }
-}
-
 /// Extra information for tracking macro expansion of spans
+#[deriving(IterBytes)]
 pub enum ExpnInfo {
     ExpandedFrom(CallInfo)
 }
 
-impl to_bytes::IterBytes for ExpnInfo {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ExpandedFrom(ref call_info) => {
-                0u8.iter_bytes(lsb0, f) && call_info.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 pub type FileName = @str;
 
 pub struct FileLines
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 89867922b25..ab7d3fda501 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -13,7 +13,6 @@ use codemap;
 
 use std::io;
 use std::uint;
-use std::vec;
 use extra::term;
 
 pub type Emitter = @fn(cmsp: Option<(@codemap::CodeMap, span)>,
@@ -250,7 +249,7 @@ fn highlight_lines(cm: @codemap::CodeMap,
     let mut elided = false;
     let mut display_lines = /* FIXME (#2543) */ copy lines.lines;
     if display_lines.len() > max_lines {
-        display_lines = vec::slice(display_lines, 0u, max_lines).to_owned();
+        display_lines = display_lines.slice(0u, max_lines).to_owned();
         elided = true;
     }
     // Print the offending lines
@@ -264,8 +263,11 @@ fn highlight_lines(cm: @codemap::CodeMap,
         let s = fmt!("%s:%u ", fm.name, last_line + 1u);
         let mut indent = s.len();
         let mut out = ~"";
-        while indent > 0u { out += " "; indent -= 1u; }
-        out += "...\n";
+        while indent > 0u {
+            out.push_char(' ');
+            indent -= 1u;
+        }
+        out.push_str("...\n");
         io::stderr().write_str(out);
     }
 
@@ -286,23 +288,29 @@ fn highlight_lines(cm: @codemap::CodeMap,
         // part of the 'filename:line ' part of the previous line.
         let skip = fm.name.len() + digits + 3u;
         for skip.times() {
-            s += " ";
+            s.push_char(' ');
         }
         let orig = fm.get_line(lines.lines[0] as int);
         for uint::range(0u,left-skip) |pos| {
             let curChar = (orig[pos] as char);
-            s += match curChar { // Whenever a tab occurs on the previous
-                '\t' => "\t",    // line, we insert one on the error-point-
-                _ => " "         // -squiggly-line as well (instead of a
-            };                   // space). This way the squiggly-line will
-        }                        // usually appear in the correct position.
+            // Whenever a tab occurs on the previous line, we insert one on
+            // the error-point-squiggly-line as well (instead of a space).
+            // That way the squiggly line will usually appear in the correct
+            // position.
+            match curChar {
+                '\t' => s.push_char('\t'),
+                _ => s.push_char(' '),
+            };
+        }
         io::stderr().write_str(s);
         let mut s = ~"^";
         let hi = cm.lookup_char_pos(sp.hi);
         if hi.col != lo.col {
             // the ^ already takes up one space
             let num_squigglies = hi.col.to_uint()-lo.col.to_uint()-1u;
-            for num_squigglies.times() { s += "~"; }
+            for num_squigglies.times() {
+                s.push_char('~')
+            }
         }
         print_maybe_colored(s + "\n", diagnosticcolor(lvl));
     }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 282a28ff9e0..78fdb99753d 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -509,7 +509,7 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
                 }
             },
             ConsMapChain (~ref mut map, rest) => {
-                if satisfies_pred(map,&n,pred) {
+                if satisfies_pred(map,&n,|v|pred(v)) {
                     map.insert(key,ext);
                 } else {
                     rest.insert_into_frame(key,ext,n,pred)
diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs
index 80ab54b7e2c..7df8874076e 100644
--- a/src/libsyntax/ext/concat_idents.rs
+++ b/src/libsyntax/ext/concat_idents.rs
@@ -26,8 +26,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
             }
         } else {
             match *e {
-                ast::tt_tok(_, token::IDENT(ident,_)) =>
-                res_str += cx.str_of(ident),
+                ast::tt_tok(_, token::IDENT(ident,_)) => res_str.push_str(cx.str_of(ident)),
                 _ => cx.span_fatal(sp, "concat_idents! requires ident args.")
             }
         }
diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs
index 8403234f892..15fb6ee9ff7 100644
--- a/src/libsyntax/ext/deriving/iter_bytes.rs
+++ b/src/libsyntax/ext/deriving/iter_bytes.rs
@@ -43,15 +43,21 @@ pub fn expand_deriving_iter_bytes(cx: @ExtCtxt,
 }
 
 fn iter_bytes_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
-    let lsb0_f = match substr.nonself_args {
-        [l, f] => ~[l, f],
+    let (lsb0, f)= match substr.nonself_args {
+        [l, f] => (l, f),
         _ => cx.span_bug(span, "Incorrect number of arguments in `deriving(IterBytes)`")
     };
+    // Build the "explicitly borrowed" stack closure, "|_buf| f(_buf)".
+    let blk_arg = cx.ident_of("_buf");
+    let borrowed_f =
+        cx.lambda_expr_1(span, cx.expr_call(span, f, ~[cx.expr_ident(span, blk_arg)]),
+                         blk_arg);
+
     let iter_bytes_ident = substr.method_ident;
     let call_iterbytes = |thing_expr| {
         cx.expr_method_call(span,
                               thing_expr, iter_bytes_ident,
-                              copy lsb0_f)
+                              ~[lsb0, borrowed_f])
     };
     let mut exprs = ~[];
     let fields;
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index dfbc028ddf6..19aa29a62a9 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -99,7 +99,7 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
                     (ident, ref summary) => {
                         cx.arm(span,
                                ~[ pat ],
-                               rand_thing(cx, span, ident, summary, rand_call))
+                               rand_thing(cx, span, ident, summary, || rand_call()))
                     }
                 }
             };
diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs
index d1d4d173a3f..c9d63d2c416 100644
--- a/src/libsyntax/ext/deriving/to_str.rs
+++ b/src/libsyntax/ext/deriving/to_str.rs
@@ -30,7 +30,7 @@ pub fn expand_deriving_to_str(cx: @ExtCtxt,
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
                 args: ~[],
-                ret_ty: Ptr(~Literal(Path::new_local("str")), Owned),
+                ret_ty: Ptr(~Literal(Path::new_local("str")), Send),
                 const_nonmatching: false,
                 combine_substructure: to_str_substructure
             }
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index 2f21eba11d7..a2f9aa58d99 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -22,7 +22,7 @@ use opt_vec;
 
 /// The types of pointers
 pub enum PtrTy<'self> {
-    Owned, // ~
+    Send, // ~
     Managed(ast::mutability), // @[mut]
     Borrowed(Option<&'self str>, ast::mutability), // &['lifetime] [mut]
 }
@@ -128,7 +128,7 @@ impl<'self> Ty<'self> {
             Ptr(ref ty, ref ptr) => {
                 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
                 match *ptr {
-                    Owned => {
+                    Send => {
                         cx.ty_uniq(span, raw_ty)
                     }
                     Managed(mutbl) => {
@@ -248,7 +248,7 @@ pub fn get_explicit_self(cx: @ExtCtxt, span: span, self_ptr: &Option<PtrTy>)
             let self_ty = respan(
                 span,
                 match *ptr {
-                    Owned => ast::sty_uniq(ast::m_imm),
+                    Send => ast::sty_uniq(ast::m_imm),
                     Managed(mutbl) => ast::sty_box(mutbl),
                     Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| @cx.lifetime(span,
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index 2c5ec0909d9..3044cd50b34 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -65,8 +65,8 @@ impl gen_send for message {
                 args_ast);
 
             let mut body = ~"{\n";
-            body += fmt!("use super::%s;\n", name);
-            body += "let mut pipe = pipe;\n";
+            body.push_str(fmt!("use super::%s;\n", name));
+            body.push_str("let mut pipe = pipe;\n");
 
             if this.proto.is_bounded() {
                 let (sp, rp) = match (this.dir, next.dir) {
@@ -76,13 +76,15 @@ impl gen_send for message {
                   (recv, recv) => (~"c", ~"s")
                 };
 
-                body += "let mut b = pipe.reuse_buffer();\n";
-                body += fmt!("let %s = ::std::pipes::SendPacketBuffered(\
-                              &mut (b.buffer.data.%s));\n",
-                             sp, next.name);
-                body += fmt!("let %s = ::std::pipes::RecvPacketBuffered(\
-                              &mut (b.buffer.data.%s));\n",
-                             rp, next.name);
+                body.push_str("let mut b = pipe.reuse_buffer();\n");
+                body.push_str(fmt!("let %s = ::std::pipes::SendPacketBuffered(\
+                                    &mut (b.buffer.data.%s));\n",
+                                    sp,
+                                    next.name));
+                body.push_str(fmt!("let %s = ::std::pipes::RecvPacketBuffered(\
+                                   &mut (b.buffer.data.%s));\n",
+                                   rp,
+                                   next.name));
             }
             else {
                 let pat = match (this.dir, next.dir) {
@@ -92,23 +94,22 @@ impl gen_send for message {
                   (recv, recv) => "(s, c)"
                 };
 
-                body += fmt!("let %s = ::std::pipes::entangle();\n", pat);
+                body.push_str(fmt!("let %s = ::std::pipes::entangle();\n", pat));
             }
-            body += fmt!("let message = %s(%s);\n",
-                         name,
-                         vec::append_one(
-                             arg_names.map(|x| cx.str_of(*x)),
-                             @"s").connect(", "));
+            body.push_str(fmt!("let message = %s(%s);\n",
+                                name,
+                                vec::append_one(arg_names.map(|x| cx.str_of(*x)), @"s")
+                                                         .connect(", ")));
 
             if !try {
-                body += fmt!("::std::pipes::send(pipe, message);\n");
+                body.push_str(fmt!("::std::pipes::send(pipe, message);\n"));
                 // return the new channel
-                body += "c }";
+                body.push_str("c }");
             }
             else {
-                body += fmt!("if ::std::pipes::send(pipe, message) {\n \
+                body.push_str(fmt!("if ::std::pipes::send(pipe, message) {\n \
                                   ::std::pipes::rt::make_some(c) \
-                              } else { ::std::pipes::rt::make_none() } }");
+                              } else { ::std::pipes::rt::make_none() } }"));
             }
 
             let body = cx.parse_expr(body.to_managed());
@@ -155,19 +156,19 @@ impl gen_send for message {
                 };
 
                 let mut body = ~"{ ";
-                body += fmt!("use super::%s;\n", name);
-                body += fmt!("let message = %s%s;\n", name, message_args);
+                body.push_str(fmt!("use super::%s;\n", name));
+                body.push_str(fmt!("let message = %s%s;\n", name, message_args));
 
                 if !try {
-                    body += fmt!("::std::pipes::send(pipe, message);\n");
-                    body += " }";
+                    body.push_str(fmt!("::std::pipes::send(pipe, message);\n"));
+                    body.push_str(" }");
                 } else {
-                    body += fmt!("if ::std::pipes::send(pipe, message) \
+                    body.push_str(fmt!("if ::std::pipes::send(pipe, message) \
                                         { \
                                       ::std::pipes::rt::make_some(()) \
                                   } else { \
                                     ::std::pipes::rt::make_none() \
-                                  } }");
+                                  } }"));
                 }
 
                 let body = cx.parse_expr(body.to_managed());
@@ -433,10 +434,10 @@ impl gen_init for protocol {
         let mut server_states = ~[];
 
         for (copy self.states).iter().advance |s| {
-            items += s.to_type_decls(cx);
+            items.push_all_move(s.to_type_decls(cx));
 
-            client_states += s.to_endpoint_decls(cx, send);
-            server_states += s.to_endpoint_decls(cx, recv);
+            client_states.push_all_move(s.to_endpoint_decls(cx, send));
+            server_states.push_all_move(s.to_endpoint_decls(cx, recv));
         }
 
         if self.is_bounded() {
diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs
index fe050fc99f1..bf8c5ae462b 100644
--- a/src/libsyntax/opt_vec.rs
+++ b/src/libsyntax/opt_vec.rs
@@ -18,7 +18,7 @@
 
 use std::vec::VecIterator;
 
-#[deriving(Encodable, Decodable)]
+#[deriving(Encodable, Decodable,IterBytes)]
 pub enum OptVec<T> {
     Empty,
     Vec(~[T])
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index ddcad5c3e8f..d33b72ae3c9 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -42,7 +42,7 @@ impl parser_attr for Parser {
                 if self.look_ahead(1u) != token::LBRACKET {
                     break;
                 }
-                attrs += [self.parse_attribute(ast::attr_outer)];
+                attrs.push(self.parse_attribute(ast::attr_outer));
               }
               token::DOC_COMMENT(s) => {
                 let attr = ::attr::mk_sugared_doc_attr(
@@ -53,7 +53,7 @@ impl parser_attr for Parser {
                 if attr.node.style != ast::attr_outer {
                   self.fatal("expected outer comment");
                 }
-                attrs += [attr];
+                attrs.push(attr);
                 self.bump();
               }
               _ => break
@@ -77,9 +77,7 @@ impl parser_attr for Parser {
         self.expect(&token::RBRACKET);
         let hi = self.span.hi;
         return spanned(lo, hi, ast::attribute_ { style: style,
-                                                 value: meta_item,
-                                                 is_sugared_doc: false });
-    }
+                                                 value: meta_item, is_sugared_doc: false }); }
 
     // Parse attributes that appear after the opening of an item, each
     // terminated by a semicolon. In addition to a vector of inner attributes,
@@ -105,7 +103,7 @@ impl parser_attr for Parser {
                 let attr = self.parse_attribute(ast::attr_inner);
                 if *self.token == token::SEMI {
                     self.bump();
-                    inner_attrs += [attr];
+                    inner_attrs.push(attr);
                 } else {
                     // It's not really an inner attribute
                     let outer_attr =
@@ -113,7 +111,7 @@ impl parser_attr for Parser {
                             ast::attribute_ { style: ast::attr_outer,
                                               value: attr.node.value,
                                               is_sugared_doc: false });
-                    next_outer_attrs += [outer_attr];
+                    next_outer_attrs.push(outer_attr);
                     break;
                 }
               }
@@ -125,9 +123,9 @@ impl parser_attr for Parser {
                 );
                 self.bump();
                 if attr.node.style == ast::attr_inner {
-                  inner_attrs += [attr];
+                  inner_attrs.push(attr);
                 } else {
-                  next_outer_attrs += [attr];
+                  next_outer_attrs.push(attr);
                   break;
                 }
               }
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 2baf08b68f1..01af33b13b8 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -254,7 +254,7 @@ fn read_block_comment(rdr: @mut StringReader,
             bump(rdr);
         }
         if !is_eof(rdr) {
-            curr_line += "*/";
+            curr_line.push_str("*/");
             bump(rdr);
             bump(rdr);
         }
@@ -278,13 +278,13 @@ fn read_block_comment(rdr: @mut StringReader,
                 if rdr.curr == '/' && nextch(rdr) == '*' {
                     bump(rdr);
                     bump(rdr);
-                    curr_line += "*";
+                    curr_line.push_char('*');
                     level += 1;
                 } else {
                     if rdr.curr == '*' && nextch(rdr) == '/' {
                         bump(rdr);
                         bump(rdr);
-                        curr_line += "/";
+                        curr_line.push_char('/');
                         level -= 1;
                     } else { bump(rdr); }
                 }
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index cde4c754d56..04f62f35749 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -51,251 +51,3 @@ pub fn token_to_str(token: &token::Token) -> ~str {
     token::to_str(get_ident_interner(), token)
 }
 
-impl Parser {
-    // convert a token to a string using self's reader
-    pub fn token_to_str(&self, token: &token::Token) -> ~str {
-        token::to_str(get_ident_interner(), token)
-    }
-
-    // convert the current token to a string using self's reader
-    pub fn this_token_to_str(&self) -> ~str {
-        self.token_to_str(self.token)
-    }
-
-    pub fn unexpected_last(&self, t: &token::Token) -> ! {
-        self.span_fatal(
-            *self.last_span,
-            fmt!(
-                "unexpected token: `%s`",
-                self.token_to_str(t)
-            )
-        );
-    }
-
-    pub fn unexpected(&self) -> ! {
-        self.fatal(
-            fmt!(
-                "unexpected token: `%s`",
-                self.this_token_to_str()
-            )
-        );
-    }
-
-    // expect and consume the token t. Signal an error if
-    // the next token is not t.
-    pub fn expect(&self, t: &token::Token) {
-        if *self.token == *t {
-            self.bump();
-        } else {
-            self.fatal(
-                fmt!(
-                    "expected `%s` but found `%s`",
-                    self.token_to_str(t),
-                    self.this_token_to_str()
-                )
-            )
-        }
-    }
-
-    pub fn parse_ident(&self) -> ast::ident {
-        self.check_strict_keywords();
-        self.check_reserved_keywords();
-        match *self.token {
-            token::IDENT(i, _) => {
-                self.bump();
-                i
-            }
-            token::INTERPOLATED(token::nt_ident(*)) => {
-                self.bug("ident interpolation not converted to real token");
-            }
-            _ => {
-                self.fatal(
-                    fmt!(
-                        "expected ident, found `%s`",
-                        self.this_token_to_str()
-                    )
-                );
-            }
-        }
-    }
-
-    pub fn parse_path_list_ident(&self) -> ast::path_list_ident {
-        let lo = self.span.lo;
-        let ident = self.parse_ident();
-        let hi = self.last_span.hi;
-        spanned(lo, hi, ast::path_list_ident_ { name: ident,
-                                                id: self.get_id() })
-    }
-
-    // consume token 'tok' if it exists. Returns true if the given
-    // token was present, false otherwise.
-    pub fn eat(&self, tok: &token::Token) -> bool {
-        return if *self.token == *tok { self.bump(); true } else { false };
-    }
-
-    pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
-        token::is_keyword(kw, self.token)
-    }
-
-    // if the next token is the given keyword, eat it and return
-    // true. Otherwise, return false.
-    pub fn eat_keyword(&self, kw: keywords::Keyword) -> bool {
-        let is_kw = match *self.token {
-            token::IDENT(sid, false) => kw.to_ident().name == sid.name,
-            _ => false
-        };
-        if is_kw { self.bump() }
-        is_kw
-    }
-
-    // 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.
-    pub fn expect_keyword(&self, kw: keywords::Keyword) {
-        if !self.eat_keyword(kw) {
-            self.fatal(
-                fmt!(
-                    "expected `%s`, found `%s`",
-                    self.id_to_str(kw.to_ident()),
-                    self.this_token_to_str()
-                )
-            );
-        }
-    }
-
-    // signal an error if the given string is a strict keyword
-    pub fn check_strict_keywords(&self) {
-        if token::is_strict_keyword(self.token) {
-            self.span_err(*self.last_span,
-                          fmt!("found `%s` in ident position", self.this_token_to_str()));
-        }
-    }
-
-    // signal an error if the current token is a reserved keyword
-    pub fn check_reserved_keywords(&self) {
-        if token::is_reserved_keyword(self.token) {
-            self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str()));
-        }
-    }
-
-    // expect and consume a GT. if a >> is seen, replace it
-    // with a single > and continue. If a GT is not seen,
-    // signal an error.
-    pub fn expect_gt(&self) {
-        if *self.token == token::GT {
-            self.bump();
-        } else if *self.token == token::BINOP(token::SHR) {
-            self.replace_token(
-                token::GT,
-                self.span.lo + BytePos(1u),
-                self.span.hi
-            );
-        } else {
-            let mut s: ~str = ~"expected `";
-            s += self.token_to_str(&token::GT);
-            s += "`, found `";
-            s += self.this_token_to_str();
-            s += "`";
-            self.fatal(s);
-        }
-    }
-
-    // parse a sequence bracketed by '<' and '>', stopping
-    // before the '>'.
-    pub fn parse_seq_to_before_gt<T: Copy>(&self,
-                                           sep: Option<token::Token>,
-                                           f: &fn(&Parser) -> T)
-                                           -> OptVec<T> {
-        let mut first = true;
-        let mut v = opt_vec::Empty;
-        while *self.token != token::GT
-            && *self.token != token::BINOP(token::SHR) {
-            match sep {
-              Some(ref t) => {
-                if first { first = false; }
-                else { self.expect(t); }
-              }
-              _ => ()
-            }
-            v.push(f(self));
-        }
-        return v;
-    }
-
-    pub fn parse_seq_to_gt<T: Copy>(&self,
-                                    sep: Option<token::Token>,
-                                    f: &fn(&Parser) -> T)
-                                    -> OptVec<T> {
-        let v = self.parse_seq_to_before_gt(sep, f);
-        self.expect_gt();
-        return v;
-    }
-
-    // parse a sequence, including the closing delimiter. The function
-    // f must consume tokens until reaching the next separator or
-    // closing bracket.
-    pub fn parse_seq_to_end<T: Copy>(&self,
-                                     ket: &token::Token,
-                                     sep: SeqSep,
-                                     f: &fn(&Parser) -> T)
-                                     -> ~[T] {
-        let val = self.parse_seq_to_before_end(ket, sep, f);
-        self.bump();
-        val
-    }
-
-    // parse a sequence, not including the closing delimiter. The function
-    // f must consume tokens until reaching the next separator or
-    // closing bracket.
-    pub fn parse_seq_to_before_end<T: Copy>(&self,
-                                            ket: &token::Token,
-                                            sep: SeqSep,
-                                            f: &fn(&Parser) -> T)
-                                            -> ~[T] {
-        let mut first: bool = true;
-        let mut v: ~[T] = ~[];
-        while *self.token != *ket {
-            match sep.sep {
-              Some(ref t) => {
-                if first { first = false; }
-                else { self.expect(t); }
-              }
-              _ => ()
-            }
-            if sep.trailing_sep_allowed && *self.token == *ket { break; }
-            v.push(f(self));
-        }
-        return v;
-    }
-
-    // parse a sequence, including the closing delimiter. The function
-    // f must consume tokens until reaching the next separator or
-    // closing bracket.
-    pub fn parse_unspanned_seq<T: Copy>(&self,
-                                        bra: &token::Token,
-                                        ket: &token::Token,
-                                        sep: SeqSep,
-                                        f: &fn(&Parser) -> T)
-                                        -> ~[T] {
-        self.expect(bra);
-        let result = self.parse_seq_to_before_end(ket, sep, f);
-        self.bump();
-        result
-    }
-
-    // NB: Do not use this function unless you actually plan to place the
-    // spanned list in the AST.
-    pub fn parse_seq<T: Copy>(&self,
-                              bra: &token::Token,
-                              ket: &token::Token,
-                              sep: SeqSep,
-                              f: &fn(&Parser) -> T)
-                              -> spanned<~[T]> {
-        let lo = self.span.lo;
-        self.expect(bra);
-        let result = self.parse_seq_to_before_end(ket, sep, f);
-        let hi = self.span.hi;
-        self.bump();
-        spanned(lo, hi, result)
-    }
-}
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 2092f0fa5fa..4a872832952 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -180,7 +180,7 @@ pub fn bump(rdr: &mut StringReader) {
         let byte_offset_diff = next.next - current_byte_offset;
         rdr.pos = rdr.pos + BytePos(byte_offset_diff);
         rdr.curr = next.ch;
-        rdr.col += CharPos(1u);
+        rdr.col = rdr.col + CharPos(1u);
         if last_char == '\n' {
             rdr.filemap.next_line(rdr.last_pos);
             rdr.col = CharPos(0u);
@@ -448,8 +448,8 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
         is_float = true;
         bump(rdr);
         let dec_part = scan_digits(rdr, 10u);
-        num_str += ".";
-        num_str += dec_part;
+        num_str.push_char('.');
+        num_str.push_str(dec_part);
     }
     if is_float {
         match base {
@@ -461,7 +461,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
     match scan_exponent(rdr) {
       Some(ref s) => {
         is_float = true;
-        num_str += (*s);
+        num_str.push_str(*s);
       }
       None => ()
     }
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 32508f3b477..fff4c125af6 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -62,6 +62,8 @@ pub enum ObsoleteSyntax {
     ObsoleteFixedLengthVectorType,
     ObsoleteNamedExternModule,
     ObsoleteMultipleLocalDecl,
+    ObsoleteMutWithMultipleBindings,
+    ObsoletePatternCopyKeyword,
 }
 
 impl to_bytes::IterBytes for ObsoleteSyntax {
@@ -71,7 +73,26 @@ impl to_bytes::IterBytes for ObsoleteSyntax {
     }
 }
 
-impl Parser {
+pub trait ParserObsoleteMethods {
+    /// Reports an obsolete syntax non-fatal error.
+    fn obsolete(&self, sp: span, kind: ObsoleteSyntax);
+    // Reports an obsolete syntax non-fatal error, and returns
+    // a placeholder expression
+    fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr;
+    fn report(&self,
+              sp: span,
+              kind: ObsoleteSyntax,
+              kind_str: &str,
+              desc: &str);
+    fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool;
+    fn is_obsolete_ident(&self, ident: &str) -> bool;
+    fn eat_obsolete_ident(&self, ident: &str) -> bool;
+    fn try_parse_obsolete_struct_ctor(&self) -> bool;
+    fn try_parse_obsolete_with(&self) -> bool;
+    fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) -> bool;
+}
+
+impl ParserObsoleteMethods for Parser {
     /// Reports an obsolete syntax non-fatal error.
     pub fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
         let (kind_str, desc) = match kind {
@@ -223,6 +244,15 @@ impl Parser {
                 "instead of e.g. `let a = 1, b = 2`, write \
                  `let (a, b) = (1, 2)`."
             ),
+            ObsoleteMutWithMultipleBindings => (
+                "`mut` with multiple bindings",
+                "use multiple local declarations instead of e.g. `let mut \
+                 (x, y) = ...`."
+            ),
+            ObsoletePatternCopyKeyword => (
+                "`copy` in patterns",
+                "`copy` in patterns no longer has any effect"
+            ),
         };
 
         self.report(sp, kind, kind_str, desc);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index d67771fc435..f1b5c4d16be 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -64,7 +64,7 @@ use codemap::{span, BytePos, spanned, mk_sp};
 use codemap;
 use parse::attr::parser_attr;
 use parse::classify;
-use parse::common::{seq_sep_none};
+use parse::common::{SeqSep, seq_sep_none};
 use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed};
 use parse::lexer::reader;
 use parse::lexer::TokenAndSpan;
@@ -83,8 +83,12 @@ use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer};
 use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod};
 use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType};
 use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl};
-use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident, is_ident_or_path};
-use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents, token_to_binop};
+use parse::obsolete::{ObsoleteMutWithMultipleBindings};
+use parse::obsolete::{ObsoletePatternCopyKeyword, ParserObsoleteMethods};
+use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident};
+use parse::token::{is_ident_or_path};
+use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents};
+use parse::token::{token_to_binop};
 use parse::token;
 use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
 use opt_vec;
@@ -270,6 +274,253 @@ impl Drop for Parser {
 }
 
 impl Parser {
+    // convert a token to a string using self's reader
+    pub fn token_to_str(&self, token: &token::Token) -> ~str {
+        token::to_str(get_ident_interner(), token)
+    }
+
+    // convert the current token to a string using self's reader
+    pub fn this_token_to_str(&self) -> ~str {
+        self.token_to_str(self.token)
+    }
+
+    pub fn unexpected_last(&self, t: &token::Token) -> ! {
+        self.span_fatal(
+            *self.last_span,
+            fmt!(
+                "unexpected token: `%s`",
+                self.token_to_str(t)
+            )
+        );
+    }
+
+    pub fn unexpected(&self) -> ! {
+        self.fatal(
+            fmt!(
+                "unexpected token: `%s`",
+                self.this_token_to_str()
+            )
+        );
+    }
+
+    // expect and consume the token t. Signal an error if
+    // the next token is not t.
+    pub fn expect(&self, t: &token::Token) {
+        if *self.token == *t {
+            self.bump();
+        } else {
+            self.fatal(
+                fmt!(
+                    "expected `%s` but found `%s`",
+                    self.token_to_str(t),
+                    self.this_token_to_str()
+                )
+            )
+        }
+    }
+
+    pub fn parse_ident(&self) -> ast::ident {
+        self.check_strict_keywords();
+        self.check_reserved_keywords();
+        match *self.token {
+            token::IDENT(i, _) => {
+                self.bump();
+                i
+            }
+            token::INTERPOLATED(token::nt_ident(*)) => {
+                self.bug("ident interpolation not converted to real token");
+            }
+            _ => {
+                self.fatal(
+                    fmt!(
+                        "expected ident, found `%s`",
+                        self.this_token_to_str()
+                    )
+                );
+            }
+        }
+    }
+
+    pub fn parse_path_list_ident(&self) -> ast::path_list_ident {
+        let lo = self.span.lo;
+        let ident = self.parse_ident();
+        let hi = self.last_span.hi;
+        spanned(lo, hi, ast::path_list_ident_ { name: ident,
+                                                id: self.get_id() })
+    }
+
+    // consume token 'tok' if it exists. Returns true if the given
+    // token was present, false otherwise.
+    pub fn eat(&self, tok: &token::Token) -> bool {
+        return if *self.token == *tok { self.bump(); true } else { false };
+    }
+
+    pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
+        token::is_keyword(kw, self.token)
+    }
+
+    // if the next token is the given keyword, eat it and return
+    // true. Otherwise, return false.
+    pub fn eat_keyword(&self, kw: keywords::Keyword) -> bool {
+        let is_kw = match *self.token {
+            token::IDENT(sid, false) => kw.to_ident().name == sid.name,
+            _ => false
+        };
+        if is_kw { self.bump() }
+        is_kw
+    }
+
+    // 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.
+    pub fn expect_keyword(&self, kw: keywords::Keyword) {
+        if !self.eat_keyword(kw) {
+            self.fatal(
+                fmt!(
+                    "expected `%s`, found `%s`",
+                    self.id_to_str(kw.to_ident()).to_str(),
+                    self.this_token_to_str()
+                )
+            );
+        }
+    }
+
+    // signal an error if the given string is a strict keyword
+    pub fn check_strict_keywords(&self) {
+        if token::is_strict_keyword(self.token) {
+            self.span_err(*self.last_span,
+                          fmt!("found `%s` in ident position", self.this_token_to_str()));
+        }
+    }
+
+    // signal an error if the current token is a reserved keyword
+    pub fn check_reserved_keywords(&self) {
+        if token::is_reserved_keyword(self.token) {
+            self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str()));
+        }
+    }
+
+    // expect and consume a GT. if a >> is seen, replace it
+    // with a single > and continue. If a GT is not seen,
+    // signal an error.
+    pub fn expect_gt(&self) {
+        if *self.token == token::GT {
+            self.bump();
+        } else if *self.token == token::BINOP(token::SHR) {
+            self.replace_token(
+                token::GT,
+                self.span.lo + BytePos(1u),
+                self.span.hi
+            );
+        } else {
+            let mut s: ~str = ~"expected `";
+            s.push_str(self.token_to_str(&token::GT));
+            s.push_str("`, found `");
+            s.push_str(self.this_token_to_str());
+            s.push_str("`");
+            self.fatal(s);
+        }
+    }
+
+    // parse a sequence bracketed by '<' and '>', stopping
+    // before the '>'.
+    pub fn parse_seq_to_before_gt<T: Copy>(&self,
+                                           sep: Option<token::Token>,
+                                           f: &fn(&Parser) -> T)
+                                           -> OptVec<T> {
+        let mut first = true;
+        let mut v = opt_vec::Empty;
+        while *self.token != token::GT
+            && *self.token != token::BINOP(token::SHR) {
+            match sep {
+              Some(ref t) => {
+                if first { first = false; }
+                else { self.expect(t); }
+              }
+              _ => ()
+            }
+            v.push(f(self));
+        }
+        return v;
+    }
+
+    pub fn parse_seq_to_gt<T: Copy>(&self,
+                                    sep: Option<token::Token>,
+                                    f: &fn(&Parser) -> T)
+                                    -> OptVec<T> {
+        let v = self.parse_seq_to_before_gt(sep, f);
+        self.expect_gt();
+        return v;
+    }
+
+    // parse a sequence, including the closing delimiter. The function
+    // f must consume tokens until reaching the next separator or
+    // closing bracket.
+    pub fn parse_seq_to_end<T: Copy>(&self,
+                                     ket: &token::Token,
+                                     sep: SeqSep,
+                                     f: &fn(&Parser) -> T)
+                                     -> ~[T] {
+        let val = self.parse_seq_to_before_end(ket, sep, f);
+        self.bump();
+        val
+    }
+
+    // parse a sequence, not including the closing delimiter. The function
+    // f must consume tokens until reaching the next separator or
+    // closing bracket.
+    pub fn parse_seq_to_before_end<T: Copy>(&self,
+                                            ket: &token::Token,
+                                            sep: SeqSep,
+                                            f: &fn(&Parser) -> T)
+                                            -> ~[T] {
+        let mut first: bool = true;
+        let mut v: ~[T] = ~[];
+        while *self.token != *ket {
+            match sep.sep {
+              Some(ref t) => {
+                if first { first = false; }
+                else { self.expect(t); }
+              }
+              _ => ()
+            }
+            if sep.trailing_sep_allowed && *self.token == *ket { break; }
+            v.push(f(self));
+        }
+        return v;
+    }
+
+    // parse a sequence, including the closing delimiter. The function
+    // f must consume tokens until reaching the next separator or
+    // closing bracket.
+    pub fn parse_unspanned_seq<T: Copy>(&self,
+                                        bra: &token::Token,
+                                        ket: &token::Token,
+                                        sep: SeqSep,
+                                        f: &fn(&Parser) -> T)
+                                        -> ~[T] {
+        self.expect(bra);
+        let result = self.parse_seq_to_before_end(ket, sep, f);
+        self.bump();
+        result
+    }
+
+    // NB: Do not use this function unless you actually plan to place the
+    // spanned list in the AST.
+    pub fn parse_seq<T: Copy>(&self,
+                              bra: &token::Token,
+                              ket: &token::Token,
+                              sep: SeqSep,
+                              f: &fn(&Parser) -> T)
+                              -> spanned<~[T]> {
+        let lo = self.span.lo;
+        self.expect(bra);
+        let result = self.parse_seq_to_before_end(ket, sep, f);
+        let hi = self.span.hi;
+        self.bump();
+        spanned(lo, hi, result)
+    }
+
     // advance the parser by one token
     pub fn bump(&self) {
         *self.last_span = copy *self.span;
@@ -821,6 +1072,11 @@ impl Parser {
             self.parse_arg_mode();
             is_mutbl = self.eat_keyword(keywords::Mut);
             let pat = self.parse_pat();
+
+            if is_mutbl && !ast_util::pat_is_ident(pat) {
+                self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
+            }
+
             self.expect(&token::COLON);
             pat
         } else {
@@ -2437,8 +2693,7 @@ impl Parser {
                 pat = self.parse_pat_ident(bind_by_ref(mutbl));
             } else if self.eat_keyword(keywords::Copy) {
                 // parse copy pat
-                self.warn("copy keyword in patterns no longer has any effect, \
-                           remove it");
+                self.obsolete(*self.span, ObsoletePatternCopyKeyword);
                 pat = self.parse_pat_ident(bind_infer);
             } else {
                 let can_be_enum_or_struct;
@@ -2560,6 +2815,11 @@ impl Parser {
     fn parse_local(&self, is_mutbl: bool) -> @local {
         let lo = self.span.lo;
         let pat = self.parse_pat();
+
+        if is_mutbl && !ast_util::pat_is_ident(pat) {
+            self.obsolete(*self.span, ObsoleteMutWithMultipleBindings)
+        }
+
         let mut ty = @Ty {
             id: self.get_id(),
             node: ty_infer,
@@ -4244,8 +4504,12 @@ impl Parser {
         // FAILURE TO PARSE ITEM
         if visibility != inherited {
             let mut s = ~"unmatched visibility `";
-            s += if visibility == public { "pub" } else { "priv" };
-            s += "`";
+            if visibility == public {
+                s.push_str("pub")
+            } else {
+                s.push_str("priv")
+            }
+            s.push_char('`');
             self.span_fatal(*self.last_span, s);
         }
         return iovi_none;
@@ -4420,7 +4684,8 @@ impl Parser {
         let mut attrs = vec::append(first_item_attrs,
                                     self.parse_outer_attributes());
         // First, parse view items.
-        let mut (view_items, items) = (~[], ~[]);
+        let mut view_items = ~[];
+        let mut items = ~[];
         let mut done = false;
         // I think this code would probably read better as a single
         // loop with a mutable three-state-variable (for extern mods,
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 2ddae73a3fc..94147825da4 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -22,7 +22,7 @@ use std::local_data;
 use std::rand;
 use std::rand::RngUtil;
 
-#[deriving(Encodable, Decodable, Eq)]
+#[deriving(Encodable, Decodable, Eq, IterBytes)]
 pub enum binop {
     PLUS,
     MINUS,
@@ -36,7 +36,7 @@ pub enum binop {
     SHR,
 }
 
-#[deriving(Encodable, Decodable, Eq)]
+#[deriving(Encodable, Decodable, Eq, IterBytes)]
 pub enum Token {
     /* Expression-operator symbols. */
     EQ,
@@ -97,7 +97,7 @@ pub enum Token {
     EOF,
 }
 
-#[deriving(Encodable, Decodable, Eq)]
+#[deriving(Encodable, Decodable, Eq, IterBytes)]
 /// For interpolation during macro expansion.
 pub enum nonterminal {
     nt_item(@ast::item),
@@ -178,14 +178,14 @@ pub fn to_str(in: @ident_interner, t: &Token) -> ~str {
       LIT_FLOAT(ref s, t) => {
         let mut body = ident_to_str(s).to_owned();
         if body.ends_with(".") {
-            body += "0";  // `10.f` is not a float literal
+            body.push_char('0');  // `10.f` is not a float literal
         }
         body + ast_util::float_ty_to_str(t)
       }
       LIT_FLOAT_UNSUFFIXED(ref s) => {
         let mut body = ident_to_str(s).to_owned();
         if body.ends_with(".") {
-            body += "0";  // `10.f` is not a float literal
+            body.push_char('0');  // `10.f` is not a float literal
         }
         body
       }
@@ -484,7 +484,7 @@ pub fn get_ident_interner() -> @ident_interner {
     unsafe {
         let key =
             (cast::transmute::<(uint, uint),
-             &fn(v: @@::parse::token::ident_interner)>(
+             &fn:Copy(v: @@::parse::token::ident_interner)>(
                  (-3 as uint, 0u)));
         match local_data::local_data_get(key) {
             Some(interner) => *interner,
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 4e03d9bac70..7cd3faf9a90 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -122,12 +122,14 @@ pub fn buf_str(toks: ~[token], szs: ~[int], left: uint, right: uint,
     let mut s = ~"[";
     while i != right && L != 0u {
         L -= 1u;
-        if i != left { s += ", "; }
-        s += fmt!("%d=%s", szs[i], tok_str(toks[i]));
+        if i != left {
+            s.push_str(", ");
+        }
+        s.push_str(fmt!("%d=%s", szs[i], tok_str(toks[i])));
         i += 1u;
         i %= n;
     }
-    s += "]";
+    s.push_char(']');
     return s;
 }
 
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index af37c1d27d8..3cdc4fd0fa1 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -21,7 +21,7 @@ pub struct Interner<T> {
 }
 
 // when traits can extend traits, we should extend index<uint,T> to get []
-impl<T:Eq + IterBytes + Hash + Const + Copy> Interner<T> {
+impl<T:Eq + IterBytes + Hash + Freeze + Copy> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
             map: @mut HashMap::new(),
diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs
index e45bfc8ea5d..beca0adbe3c 100644
--- a/src/test/auxiliary/cci_capture_clause.rs
+++ b/src/test/auxiliary/cci_capture_clause.rs
@@ -11,7 +11,7 @@
 use std::comm::*;
 use std::task;
 
-pub fn foo<T:Owned + Copy>(x: T) -> Port<T> {
+pub fn foo<T:Send + Copy>(x: T) -> Port<T> {
     let (p, c) = stream();
     do task::spawn() {
         c.send(copy x);
diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs
index d4f6a1ec404..8c491a4dfc8 100644
--- a/src/test/auxiliary/issue-2526.rs
+++ b/src/test/auxiliary/issue-2526.rs
@@ -20,17 +20,17 @@ struct arc_destruct<T> {
 }
 
 #[unsafe_destructor]
-impl<T:Const> Drop for arc_destruct<T> {
+impl<T:Freeze> Drop for arc_destruct<T> {
     fn drop(&self) {}
 }
 
-fn arc_destruct<T:Const>(data: int) -> arc_destruct<T> {
+fn arc_destruct<T:Freeze>(data: int) -> arc_destruct<T> {
     arc_destruct {
         _data: data
     }
 }
 
-fn arc<T:Const>(_data: T) -> arc_destruct<T> {
+fn arc<T:Freeze>(_data: T) -> arc_destruct<T> {
     arc_destruct(0)
 }
 
diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs
index 4b5880de8a5..c4d89a698c1 100644
--- a/src/test/bench/core-std.rs
+++ b/src/test/bench/core-std.rs
@@ -29,7 +29,7 @@ macro_rules! bench (
 
 fn main() {
     let argv = os::args();
-    let tests = vec::slice(argv, 1, argv.len());
+    let tests = argv.slice(1, argv.len());
 
     bench!(shift_push);
     bench!(read_line);
@@ -87,9 +87,8 @@ fn vec_plus() {
     while i < 1500 {
         let rv = vec::from_elem(r.gen_uint_range(0, i + 1), i);
         if r.gen() {
-            v += rv;
-        }
-        else {
+            v.push_all_move(rv);
+        } else {
             v = rv + v;
         }
         i += 1;
diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs
index 25bdf7dc3fe..b65a6429f2c 100644
--- a/src/test/bench/noise.rs
+++ b/src/test/bench/noise.rs
@@ -118,10 +118,10 @@ fn main() {
         };
     };
 
-    /*for int::range(0, 256) |y| {
+    for int::range(0, 256) |y| {
         for int::range(0, 256) |x| {
-            io::print(symbols[pixels[y*256+x] / 0.2f32 as int]);
+            print(symbols[pixels[y*256+x] / 0.2f32 as int]);
         }
-        io::println("");
-    }*/
+        println("");
+    }
 }
diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs
index 63e4174a0fc..1d32a78303a 100644
--- a/src/test/bench/pingpong.rs
+++ b/src/test/bench/pingpong.rs
@@ -82,7 +82,7 @@ endpoint. The send endpoint is returned to the caller and the receive
 endpoint is passed to the new task.
 
 */
-pub fn spawn_service<T:Owned,Tb:Owned>(
+pub fn spawn_service<T:Send,Tb:Send>(
             init: extern fn() -> (RecvPacketBuffered<T, Tb>,
                                   SendPacketBuffered<T, Tb>),
             service: ~fn(v: RecvPacketBuffered<T, Tb>))
@@ -103,7 +103,7 @@ pub fn spawn_service<T:Owned,Tb:Owned>(
 receive state.
 
 */
-pub fn spawn_service_recv<T:Owned,Tb:Owned>(
+pub fn spawn_service_recv<T:Send,Tb:Send>(
         init: extern fn() -> (SendPacketBuffered<T, Tb>,
                               RecvPacketBuffered<T, Tb>),
         service: ~fn(v: SendPacketBuffered<T, Tb>))
@@ -120,7 +120,7 @@ pub fn spawn_service_recv<T:Owned,Tb:Owned>(
     client
 }
 
-fn switch<T:Owned,Tb:Owned,U>(endp: std::pipes::RecvPacketBuffered<T, Tb>,
+fn switch<T:Send,Tb:Send,U>(endp: std::pipes::RecvPacketBuffered<T, Tb>,
                               f: &fn(v: Option<T>) -> U)
                               -> U {
     f(std::pipes::try_recv(endp))
diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs
index 96c7e4e9b37..49a3a3ec5d7 100644
--- a/src/test/bench/shootout-chameneos-redux.rs
+++ b/src/test/bench/shootout-chameneos-redux.rs
@@ -50,8 +50,8 @@ fn show_color(cc: color) -> ~str {
 fn show_color_list(set: ~[color]) -> ~str {
     let mut out = ~"";
     for set.iter().advance |col| {
-        out += " ";
-        out += show_color(*col);
+        out.push_char(' ');
+        out.push_str(show_color(*col));
     }
     return out;
 }
diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs
index 670e77bc3a0..5ebcfe164ce 100644
--- a/src/test/bench/shootout-fasta-redux.rs
+++ b/src/test/bench/shootout-fasta-redux.rs
@@ -96,7 +96,7 @@ impl RepeatFasta {
 
             copy_memory(buf, alu, alu_len);
             let buf_len = buf.len();
-            copy_memory(vec::mut_slice(buf, alu_len, buf_len),
+            copy_memory(buf.mut_slice(alu_len, buf_len),
                         alu,
                         LINE_LEN);
 
diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs
index f3efcc21ea9..da8d65a1dcb 100644
--- a/src/test/bench/shootout-fasta.rs
+++ b/src/test/bench/shootout-fasta.rs
@@ -47,7 +47,7 @@ fn make_cumulative(aa: ~[AminoAcids]) -> ~[AminoAcids] {
     let mut ans: ~[AminoAcids] = ~[];
     for aa.iter().advance |a| {
         cp += a.prob;
-        ans += [AminoAcids {ch: a.ch, prob: cp}];
+        ans.push(AminoAcids {ch: a.ch, prob: cp});
     }
     ans
 }
diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs
index 20042aa0e91..d26fe80e8a1 100644
--- a/src/test/bench/shootout-k-nucleotide-pipes.rs
+++ b/src/test/bench/shootout-k-nucleotide-pipes.rs
@@ -70,7 +70,7 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
            let b = str::raw::from_bytes(k);
            // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
            // to_ascii_consume and to_str_consume to not do a unnecessary copy.
-           buffer += (fmt!("%s %0.3f\n", b.to_ascii().to_upper().to_str_ascii(), v));
+           buffer.push_str(fmt!("%s %0.3f\n", b.to_ascii().to_upper().to_str_ascii(), v));
        }
    }
 
@@ -90,7 +90,7 @@ fn find(mm: &HashMap<~[u8], uint>, key: ~str) -> uint {
 
 // given a map, increment the counter for a key
 fn update_freq(mm: &mut HashMap<~[u8], uint>, key: &[u8]) {
-    let key = vec::slice(key, 0, key.len()).to_owned();
+    let key = key.to_owned();
     let newval = match mm.pop(&key) {
         Some(v) => v + 1,
         None => 1
@@ -107,11 +107,11 @@ fn windows_with_carry(bb: &[u8], nn: uint,
 
    let len = bb.len();
    while ii < len - (nn - 1u) {
-      it(vec::slice(bb, ii, ii+nn));
+      it(bb.slice(ii, ii+nn));
       ii += 1u;
    }
 
-   return vec::slice(bb, len - (nn - 1u), len).to_owned();
+   return bb.slice(len - (nn - 1u), len).to_owned();
 }
 
 fn make_sequence_processor(sz: uint,
diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs
index 646b9788f70..405aa68c483 100644
--- a/src/test/bench/shootout-k-nucleotide.rs
+++ b/src/test/bench/shootout-k-nucleotide.rs
@@ -8,7 +8,7 @@ use std::libc::{STDIN_FILENO, c_int, fdopen, fgets, fileno, fopen, fstat};
 use std::libc::{stat, strlen};
 use std::ptr::null;
 use std::unstable::intrinsics::init;
-use std::vec::{reverse, slice};
+use std::vec::{reverse};
 use extra::sort::quick_sort3;
 
 static LINE_LEN: uint = 80;
@@ -194,7 +194,7 @@ fn unpack_symbol(c: u8) -> u8 {
 
 fn next_char<'a>(mut buf: &'a [u8]) -> &'a [u8] {
     loop {
-        buf = slice(buf, 1, buf.len());
+        buf = buf.slice(1, buf.len());
         if buf.len() == 0 {
             break;
         }
@@ -226,7 +226,7 @@ fn read_stdin() -> ~[u8] {
                 fgets(transmute(&mut window[0]), LINE_LEN as c_int, stdin);
 
                 {
-                    if vec::slice(window, 0, 6) == header {
+                    if window.slice(0, 6) == header {
                         break;
                     }
                 }
@@ -235,9 +235,7 @@ fn read_stdin() -> ~[u8] {
             while fgets(transmute(&mut window[0]),
                         LINE_LEN as c_int,
                         stdin) != null() {
-                window = vec::mut_slice(window,
-                                        strlen(transmute(&window[0])) as uint,
-                                        window.len());
+                window = window.mut_slice(strlen(transmute(&window[0])) as uint, window.len());
             }
         }
 
diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs
index 70f56f5c5a3..b79ecd03c0c 100644
--- a/src/test/bench/shootout-mandelbrot.rs
+++ b/src/test/bench/shootout-mandelbrot.rs
@@ -23,7 +23,10 @@ fn main() {
         for range(0, h) |y| {
             let y = y as f64;
             for range(0, w) |x| {
-                let mut (Zr, Zi, Tr, Ti) = (0f64, 0f64, 0f64, 0f64);
+                let mut Zr = 0f64;
+                let mut Zi = 0f64;
+                let mut Tr = 0f64;
+                let mut Ti = 0f64;
                 let Cr = 2.0 * (x as f64) / (w as f64) - 1.5;
                 let Ci = 2.0 * (y as f64) / (h as f64) - 1.0;
 
diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs
index 01425d82db2..295211e03a1 100644
--- a/src/test/bench/shootout-pfib.rs
+++ b/src/test/bench/shootout-pfib.rs
@@ -32,7 +32,6 @@ use std::str;
 use std::task;
 use std::u64;
 use std::uint;
-use std::vec;
 
 fn fib(n: int) -> int {
     fn pfib(c: &Chan<int>, n: int) {
@@ -62,7 +61,7 @@ struct Config {
 fn parse_opts(argv: ~[~str]) -> Config {
     let opts = ~[getopts::optflag(~"stress")];
 
-    let opt_args = vec::slice(argv, 1, argv.len());
+    let opt_args = argv.slice(1, argv.len());
 
     match getopts::getopts(opt_args, opts) {
       Ok(ref m) => {
diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs
index 9893785ecfa..e57dee06c75 100644
--- a/src/test/bench/shootout-reverse-complement.rs
+++ b/src/test/bench/shootout-reverse-complement.rs
@@ -5,7 +5,6 @@ use std::cast::transmute;
 use std::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite};
 use std::libc::{size_t};
 use std::ptr::null;
-use std::vec::{capacity, reserve, reserve_at_least};
 use std::vec::raw::set_len;
 
 static LINE_LEN: u32 = 80;
@@ -103,13 +102,13 @@ fn main() {
         let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
 
         let mut out: ~[u8] = ~[];
-        reserve(&mut out, 12777888);
+        out.reserve(12777888);
         let mut pos = 0;
 
         loop {
             let needed = pos + (LINE_LEN as uint) + 1;
-            if capacity(&out) < needed {
-                reserve_at_least(&mut out, needed);
+            if out.capacity() < needed {
+                out.reserve_at_least(needed);
             }
 
             let mut ptr = out.unsafe_mut_ref(pos);
diff --git a/src/test/bench/shootout-threadring.rs b/src/test/bench/shootout-threadring.rs
index a67bbb05dfb..97168de5d43 100644
--- a/src/test/bench/shootout-threadring.rs
+++ b/src/test/bench/shootout-threadring.rs
@@ -13,7 +13,9 @@
 use std::os;
 
 fn start(n_tasks: int, token: int) {
-    let mut (p, ch1) = stream();
+    let (p, ch1) = stream();
+    let mut p = p;
+    let mut ch1 = ch1;
     ch1.send(token);
     //  XXX could not get this to work with a range closure
     let mut i = 2;
diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs
index f66de385374..2396d6efc5c 100644
--- a/src/test/bench/sudoku.rs
+++ b/src/test/bench/sudoku.rs
@@ -103,7 +103,9 @@ impl Sudoku {
         for u8::range(0u8, 9u8) |row| {
             for u8::range(0u8, 9u8) |col| {
                 let color = self.grid[row][col];
-                if color == 0u8 { work += [(row, col)]; }
+                if color == 0u8 {
+                    work.push((row, col));
+                }
             }
         }
 
diff --git a/src/test/compile-fail/closure-bounds-subtype.rs b/src/test/compile-fail/closure-bounds-subtype.rs
index 887346e35e5..0c9220d18ab 100644
--- a/src/test/compile-fail/closure-bounds-subtype.rs
+++ b/src/test/compile-fail/closure-bounds-subtype.rs
@@ -5,35 +5,35 @@ fn take_any(_: &fn:()) {
 fn take_copyable(_: &fn:Copy()) {
 }
 
-fn take_copyable_owned(_: &fn:Copy+Owned()) {
+fn take_copyable_owned(_: &fn:Copy+Send()) {
 }
 
-fn take_const_owned(_: &fn:Const+Owned()) {
+fn take_const_owned(_: &fn:Freeze+Send()) {
 }
 
 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
+    take_copyable_owned(f); //~ ERROR expected bounds `Copy+Send` 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`
+    take_copyable_owned(f); //~ ERROR expected bounds `Copy+Send` but found bounds `Copy`
 }
 
-fn give_owned(f: &fn:Owned()) {
+fn give_owned(f: &fn:Send()) {
     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`
+    take_copyable(f); //~ ERROR expected bounds `Copy` but found bounds `Send`
+    take_copyable_owned(f); //~ ERROR expected bounds `Copy+Send` but found bounds `Send`
 }
 
-fn give_copyable_owned(f: &fn:Copy+Owned()) {
+fn give_copyable_owned(f: &fn:Copy+Send()) {
     take_any(f);
     take_copyable(f);
     take_copyable_owned(f);
-    take_const_owned(f); //~ ERROR expected bounds `Owned+Const` but found bounds `Copy+Owned`
+    take_const_owned(f); //~ ERROR expected bounds `Send+Freeze` but found bounds `Copy+Send`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/impl-bounds-checking.rs b/src/test/compile-fail/impl-bounds-checking.rs
new file mode 100644
index 00000000000..00c415a860d
--- /dev/null
+++ b/src/test/compile-fail/impl-bounds-checking.rs
@@ -0,0 +1,24 @@
+// 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.
+
+pub trait Clone2 {
+    fn clone(&self) -> Self;
+}
+
+
+trait Getter<T: Clone2> {
+    fn get(&self) -> T;
+}
+
+impl Getter<int> for int { //~ ERROR failed to find an implementation of trait Clone2 for int
+    fn get(&self) -> int { *self }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/impl-duplicate-methods.rs b/src/test/compile-fail/impl-duplicate-methods.rs
index ec766e5ce9b..c6ce4d04e10 100644
--- a/src/test/compile-fail/impl-duplicate-methods.rs
+++ b/src/test/compile-fail/impl-duplicate-methods.rs
@@ -11,7 +11,7 @@
 struct Foo;
 impl Foo {
     fn orange(&self){}
-    fn orange(&self){}   //~ ERROR error: duplicate definition of method `orange`
+    fn orange(&self){}   //~ ERROR error: duplicate definition of value `orange`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs
index f7b9371df57..b5a5eed6a35 100644
--- a/src/test/compile-fail/issue-2149.rs
+++ b/src/test/compile-fail/issue-2149.rs
@@ -15,7 +15,7 @@ trait vec_monad<A> {
 impl<A> vec_monad<A> for ~[A] {
     fn bind<B>(&self, f: &fn(A) -> ~[B]) {
         let mut r = fail!();
-        for self.iter().advance |elt| { r += f(*elt); }
+        for self.iter().advance |elt| { r = r + f(*elt); }
         //~^ WARNING unreachable expression
         //~^^ ERROR the type of this value must be known
    }
diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/compile-fail/issue-2611-4.rs
index 2385be5723e..531d4eab535 100644
--- a/src/test/compile-fail/issue-2611-4.rs
+++ b/src/test/compile-fail/issue-2611-4.rs
@@ -20,7 +20,7 @@ struct E {
 }
 
 impl A for E {
-  fn b<F:Copy + Const,G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Const`
+  fn b<F:Copy + Freeze,G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Freeze`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs
index 91ae0e1c07a..c5d13c81b7c 100644
--- a/src/test/compile-fail/issue-2766-a.rs
+++ b/src/test/compile-fail/issue-2766-a.rs
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 pub mod stream {
-    pub enum Stream<T:Owned> { send(T, ::stream::server::Stream<T>), }
+    pub enum Stream<T:Send> { send(T, ::stream::server::Stream<T>), }
     pub mod server {
         use std::option;
         use std::pipes;
 
-        impl<T:Owned> Stream<T> {
+        impl<T:Send> Stream<T> {
             pub fn recv() -> extern fn(v: Stream<T>) -> ::stream::Stream<T> {
               // resolve really should report just one error here.
               // Change the test case when it changes.
@@ -28,7 +28,7 @@ pub mod stream {
             }
         }
 
-        pub type Stream<T:Owned> = pipes::RecvPacket<::stream::Stream<T>>;
+        pub type Stream<T:Send> = pipes::RecvPacket<::stream::Stream<T>>;
     }
 }
 
diff --git a/src/test/compile-fail/issue-3177-mutable-struct.rs b/src/test/compile-fail/issue-3177-mutable-struct.rs
index 31c0dc7d9c4..180f13d0371 100644
--- a/src/test/compile-fail/issue-3177-mutable-struct.rs
+++ b/src/test/compile-fail/issue-3177-mutable-struct.rs
@@ -10,7 +10,7 @@
 
 // xfail-test
 // error-pattern: instantiating a type parameter with an incompatible type
-struct S<T:Const> {
+struct S<T:Freeze> {
     s: T,
     cant_nest: ()
 }
diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs
index 551b50c94f2..07adc3d81e5 100644
--- a/src/test/compile-fail/kindck-destructor-owned.rs
+++ b/src/test/compile-fail/kindck-destructor-owned.rs
@@ -2,7 +2,7 @@ struct Foo {
     f: @mut int,
 }
 
-impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Owned
+impl Drop for Foo { //~ ERROR cannot implement a destructor on a structure that does not satisfy Send
     fn drop(&self) {
         *self.f = 10;
     }
diff --git a/src/test/compile-fail/kindck-nonsendable-1.rs b/src/test/compile-fail/kindck-nonsendable-1.rs
index 38983a9aca6..99057ba940c 100644
--- a/src/test/compile-fail/kindck-nonsendable-1.rs
+++ b/src/test/compile-fail/kindck-nonsendable-1.rs
@@ -12,7 +12,7 @@ fn foo(_x: @uint) {}
 
 fn main() {
     let x = @3u;
-    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
-    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
-    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Owned`
+    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send`
+    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send`
+    let _: ~fn() = || foo(x); //~ ERROR does not fulfill `Send`
 }
diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs
index 3f859b7dc84..848fd95a560 100644
--- a/src/test/compile-fail/kindck-owned.rs
+++ b/src/test/compile-fail/kindck-owned.rs
@@ -29,6 +29,6 @@ fn main() {
     copy2(boxed);
     let owned: ~fn() = || {};
     copy2(owned);    //~ ERROR does not fulfill `Copy`
-    let borrowed: &fn() = || {};
+    let borrowed: &fn:Copy() = || {};
     copy2(borrowed); //~ ERROR does not fulfill `'static`
 }
diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs
index 23d3fff01cf..72555d7e851 100644
--- a/src/test/compile-fail/liveness-use-after-send.rs
+++ b/src/test/compile-fail/liveness-use-after-send.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn send<T:Owned>(ch: _chan<T>, data: T) {
+fn send<T:Send>(ch: _chan<T>, data: T) {
     debug!(ch);
     debug!(data);
     fail!();
diff --git a/src/test/compile-fail/mutable-enum.rs b/src/test/compile-fail/mutable-enum.rs
index 2368e5eb5c5..35842a53a31 100644
--- a/src/test/compile-fail/mutable-enum.rs
+++ b/src/test/compile-fail/mutable-enum.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[mutable]
+#[no_freeze]
 enum Foo { A }
 
-fn bar<T: Const>(_: T) {}
+fn bar<T: Freeze>(_: T) {}
 
 fn main() {
     let x = A;
-    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const`
+    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Freeze`
 }
diff --git a/src/test/compile-fail/mutable-struct.rs b/src/test/compile-fail/mutable-struct.rs
index ee040506c40..6f29fcfd96d 100644
--- a/src/test/compile-fail/mutable-struct.rs
+++ b/src/test/compile-fail/mutable-struct.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[mutable]
+#[no_freeze]
 struct Foo { a: int }
 
-fn bar<T: Const>(_: T) {}
+fn bar<T: Freeze>(_: T) {}
 
 fn main() {
     let x = Foo { a: 5 };
-    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const`
+    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Freeze`
 }
diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs
index 605e59d56c8..5f0d4bc60ac 100644
--- a/src/test/compile-fail/no-send-res-ports.rs
+++ b/src/test/compile-fail/no-send-res-ports.rs
@@ -32,7 +32,7 @@ fn main() {
     let x = Cell::new(foo(Port(@())));
 
     do task::spawn {
-        let y = x.take();   //~ ERROR does not fulfill `Owned`
+        let y = x.take();   //~ ERROR does not fulfill `Send`
         error!(y);
     }
 }
diff --git a/src/test/compile-fail/non_owned-enum.rs b/src/test/compile-fail/non_owned-enum.rs
index 79c2be8183a..b436bfb8b0f 100644
--- a/src/test/compile-fail/non_owned-enum.rs
+++ b/src/test/compile-fail/non_owned-enum.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[non_owned]
+#[no_send]
 enum Foo { A }
 
-fn bar<T: Owned>(_: T) {}
+fn bar<T: Send>(_: T) {}
 
 fn main() {
     let x = A;
-    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned`
+    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Send`
 }
diff --git a/src/test/compile-fail/non_owned-struct.rs b/src/test/compile-fail/non_owned-struct.rs
index 2d0bc9a7e8e..542c3aa212b 100644
--- a/src/test/compile-fail/non_owned-struct.rs
+++ b/src/test/compile-fail/non_owned-struct.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[non_owned]
+#[no_send]
 struct Foo { a: int }
 
-fn bar<T: Owned>(_: T) {}
+fn bar<T: Send>(_: T) {}
 
 fn main() {
     let x = Foo { a: 5 };
-    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned`
+    bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Send`
 }
diff --git a/src/test/compile-fail/once-cant-call-twice-on-heap.rs b/src/test/compile-fail/once-cant-call-twice-on-heap.rs
new file mode 100644
index 00000000000..4436675d69a
--- /dev/null
+++ b/src/test/compile-fail/once-cant-call-twice-on-heap.rs
@@ -0,0 +1,29 @@
+// 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.
+
+// Testing guarantees provided by once functions.
+// This program would segfault if it were legal.
+
+extern mod extra;
+use extra::arc;
+use std::util;
+
+fn foo(blk: ~once fn()) {
+    blk();
+    blk(); //~ ERROR use of moved value
+}
+
+fn main() {
+    let x = arc::ARC(true);
+    do foo {
+        assert!(*x.get());
+        util::ignore(x);
+    }
+}
diff --git a/src/test/compile-fail/once-cant-call-twice-on-stack.rs b/src/test/compile-fail/once-cant-call-twice-on-stack.rs
new file mode 100644
index 00000000000..10877be549e
--- /dev/null
+++ b/src/test/compile-fail/once-cant-call-twice-on-stack.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// Testing guarantees provided by once functions.
+// This program would segfault if it were legal.
+
+// compile-flags:-Z once-fns
+extern mod extra;
+use extra::arc;
+use std::util;
+
+fn foo(blk: &once fn()) {
+    blk();
+    blk(); //~ ERROR use of moved value
+}
+
+fn main() {
+    let x = arc::ARC(true);
+    do foo {
+        assert!(*x.get());
+        util::ignore(x);
+    }
+}
diff --git a/src/test/compile-fail/once-cant-copy-stack-once-fn-copy.rs b/src/test/compile-fail/once-cant-copy-stack-once-fn-copy.rs
new file mode 100644
index 00000000000..6f524c0068b
--- /dev/null
+++ b/src/test/compile-fail/once-cant-copy-stack-once-fn-copy.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// Though it should be legal to copy a heap-allocated "once fn:Copy",
+// stack closures are not deep-copied, so (counterintuitively) it should be
+// illegal to copy them.
+
+fn foo<'r>(blk: &'r once fn:Copy()) -> (&'r once fn:Copy(), &'r once fn:Copy()) {
+    (copy blk, blk) //~ ERROR copying a value of non-copyable type
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/once-cant-move-out-of-non-once-on-heap.rs b/src/test/compile-fail/once-cant-move-out-of-non-once-on-heap.rs
new file mode 100644
index 00000000000..61f158cec27
--- /dev/null
+++ b/src/test/compile-fail/once-cant-move-out-of-non-once-on-heap.rs
@@ -0,0 +1,29 @@
+// 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.
+
+// Testing guarantees provided by once functions.
+// This program would segfault if it were legal.
+
+extern mod extra;
+use extra::arc;
+use std::util;
+
+fn foo(blk: ~fn()) {
+    blk();
+    blk();
+}
+
+fn main() {
+    let x = arc::ARC(true);
+    do foo {
+        assert!(*x.get());
+        util::ignore(x); //~ ERROR cannot move out of captured outer variable
+    }
+}
diff --git a/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs b/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs
new file mode 100644
index 00000000000..42c8b9a9998
--- /dev/null
+++ b/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs
@@ -0,0 +1,29 @@
+// 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.
+
+// Testing guarantees provided by once functions.
+// This program would segfault if it were legal.
+
+extern mod extra;
+use extra::arc;
+use std::util;
+
+fn foo(blk: &fn()) {
+    blk();
+    blk();
+}
+
+fn main() {
+    let x = arc::ARC(true);
+    do foo {
+        assert!(*x.get());
+        util::ignore(x); //~ ERROR cannot move out of captured outer variable
+    }
+}
diff --git a/src/test/compile-fail/rcmut-not-const-and-not-owned.rs b/src/test/compile-fail/rcmut-not-const-and-not-owned.rs
index 9e7236a67d9..45cb137b084 100644
--- a/src/test/compile-fail/rcmut-not-const-and-not-owned.rs
+++ b/src/test/compile-fail/rcmut-not-const-and-not-owned.rs
@@ -10,11 +10,11 @@
 
 extern mod extra;
 
-fn o<T: Owned>(_: &T) {}
-fn c<T: Const>(_: &T) {}
+fn o<T: Send>(_: &T) {}
+fn c<T: Freeze>(_: &T) {}
 
 fn main() {
     let x = extra::rc::rc_mut_from_owned(0);
-    o(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Owned`
-    c(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Const`
+    o(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Send`
+    c(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Freeze`
 }
diff --git a/src/test/compile-fail/regions-creating-enums.rs b/src/test/compile-fail/regions-creating-enums.rs
index 2ab0c14b49b..c2d8427d5eb 100644
--- a/src/test/compile-fail/regions-creating-enums.rs
+++ b/src/test/compile-fail/regions-creating-enums.rs
@@ -33,8 +33,8 @@ fn map_nums(x: &ast, f: &fn(uint) -> uint) -> &ast {
         return &num(f(x)); //~ ERROR borrowed value does not live long enough
       }
       add(x, y) => {
-        let m_x = map_nums(x, f);
-        let m_y = map_nums(y, f);
+        let m_x = map_nums(x, |z| f(z));
+        let m_y = map_nums(y, |z| f(z));
         return &add(m_x, m_y);  //~ ERROR borrowed value does not live long enough
       }
     }
diff --git a/src/test/compile-fail/the-case-of-the-recurring-closure-2.rs b/src/test/compile-fail/the-case-of-the-recurring-closure-2.rs
new file mode 100644
index 00000000000..bfb1e910495
--- /dev/null
+++ b/src/test/compile-fail/the-case-of-the-recurring-closure-2.rs
@@ -0,0 +1,44 @@
+// 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.
+
+// Tests correct kind-checking of the reason stack closures without the :Copy
+// bound must be noncopyable. For details see
+// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
+
+struct R<'self> {
+    // This struct is needed to create the
+    // otherwise infinite type of a fn that
+    // accepts itself as argument:
+    c: &'self fn:Copy(&R, bool)
+}
+
+fn innocent_looking_victim() {
+    let mut x = Some(~"hello");
+    do conspirator |f, writer| {
+        if writer {
+            x = None; //~ ERROR cannot implicitly borrow
+        } else {
+            match x {
+                Some(ref msg) => {
+                    (f.c)(f, true);
+                    println(fmt!("%?", msg));
+                },
+                None => fail!("oops"),
+            }
+        }
+    }
+}
+
+fn conspirator(f: &fn:Copy(&R, bool)) {
+    let r = R {c: f};
+    f(&r, false)
+}
+
+fn main() { innocent_looking_victim() }
diff --git a/src/test/compile-fail/the-case-of-the-recurring-closure.rs b/src/test/compile-fail/the-case-of-the-recurring-closure.rs
new file mode 100644
index 00000000000..f05c30c3355
--- /dev/null
+++ b/src/test/compile-fail/the-case-of-the-recurring-closure.rs
@@ -0,0 +1,44 @@
+// 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.
+
+// Tests correct kind-checking of the reason stack closures without the :Copy
+// bound must be noncopyable. For details see
+// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
+
+struct R<'self> {
+    // This struct is needed to create the
+    // otherwise infinite type of a fn that
+    // accepts itself as argument:
+    c: &'self fn(&R, bool)
+}
+
+fn innocent_looking_victim() {
+    let mut x = Some(~"hello");
+    do conspirator |f, writer| {
+        if writer {
+            x = None;
+        } else {
+            match x {
+                Some(ref msg) => {
+                    (f.c)(f, true);
+                    println(fmt!("%?", msg));
+                },
+                None => fail!("oops"),
+            }
+        }
+    }
+}
+
+fn conspirator(f: &fn(&R, bool)) {
+    let r = R {c: f};
+    f(&r, false) //~ ERROR use of moved value
+}
+
+fn main() { innocent_looking_victim() }
diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs
index adaea1de9bd..a96da398f5a 100644
--- a/src/test/compile-fail/trait-bounds-cant-coerce.rs
+++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs
@@ -11,14 +11,14 @@
 trait Foo {
 }
 
-fn a(_x: ~Foo:Owned) {
+fn a(_x: ~Foo:Send) {
 }
 
-fn b(_x: ~Foo:Owned+Copy) {
+fn b(_x: ~Foo:Send+Copy) {
 }
 
-fn c(x: ~Foo:Const+Owned) {
-    b(x); //~ ERROR expected bounds `Copy+Owned`
+fn c(x: ~Foo:Freeze+Send) {
+    b(x); //~ ERROR expected bounds `Copy+Send`
 }
 
 fn d(x: ~Foo:) {
diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs
index e9cc9575003..d7c98ec4e9d 100644
--- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs
@@ -13,7 +13,7 @@ trait Foo {
 
 // This should emit the less confusing error, not the more confusing one.
 
-fn foo(_x: Foo:Owned) { //~ERROR reference to trait `Foo` where a type is expected
+fn foo(_x: Foo:Send) { //~ERROR reference to trait `Foo` where a type is expected
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs
index 45bb5e29a88..ebffd0303e0 100644
--- a/src/test/compile-fail/trait-bounds-not-on-struct.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs
@@ -10,6 +10,6 @@
 
 struct Foo;
 
-fn foo(_x: ~Foo:Owned) { } //~ ERROR kind bounds can only be used on trait types
+fn foo(_x: ~Foo:Send) { } //~ ERROR kind bounds can only be used on trait types
 
 fn main() { }
diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs
index 8c641f4c850..68a0ae90014 100644
--- a/src/test/compile-fail/trait-bounds-sugar.rs
+++ b/src/test/compile-fail/trait-bounds-sugar.rs
@@ -13,7 +13,7 @@
 trait Foo {
 }
 
-fn a(_x: ~Foo) { // should be same as ~Foo:Owned
+fn a(_x: ~Foo) { // should be same as ~Foo:Send
 }
 
 fn b(_x: @Foo) { // should be same as ~Foo:'static
@@ -22,15 +22,15 @@ fn b(_x: @Foo) { // should be same as ~Foo:'static
 fn c(_x: &'static Foo) { // should be same as &'static Foo:'static
 }
 
-fn d(x: ~Foo:Const) {
-    a(x); //~ ERROR expected bounds `Owned`
+fn d(x: ~Foo:Freeze) {
+    a(x); //~ ERROR expected bounds `Send`
 }
 
-fn e(x: @Foo:Const) {
+fn e(x: @Foo:Freeze) {
     b(x); //~ ERROR expected bounds `'static`
 }
 
-fn f(x: &'static Foo:Const) {
+fn f(x: &'static Foo:Freeze) {
     c(x); //~ ERROR expected bounds `'static`
 }
 
diff --git a/src/test/compile-fail/trait-duplicate-methods.rs b/src/test/compile-fail/trait-duplicate-methods.rs
index e2ba5267eba..ba8101d16ab 100644
--- a/src/test/compile-fail/trait-duplicate-methods.rs
+++ b/src/test/compile-fail/trait-duplicate-methods.rs
@@ -10,7 +10,7 @@
 
 trait Foo {
     fn orange(&self);
-    fn orange(&self);   //~ ERROR error: duplicate definition of method `orange`
+    fn orange(&self);   //~ ERROR error: duplicate definition of value `orange`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs
index f687a6f9702..c44887593ab 100644
--- a/src/test/compile-fail/trait-or-new-type-instead.rs
+++ b/src/test/compile-fail/trait-or-new-type-instead.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: implement a trait or new type instead
+// error-pattern: found value name used as a type
 impl<T> Option<T> {
     pub fn foo(&self) { }
 }
diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs
index 26058bf89ca..d51df4979e3 100644
--- a/src/test/compile-fail/unique-unique-kind.rs
+++ b/src/test/compile-fail/unique-unique-kind.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f<T:Owned>(_i: T) {
+fn f<T:Send>(_i: T) {
 }
 
 fn main() {
     let i = ~@100;
-    f(i); //~ ERROR does not fulfill `Owned`
+    f(i); //~ ERROR does not fulfill `Send`
 }
diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs
index 58de0926f7c..de089dcf914 100644
--- a/src/test/compile-fail/unsendable-class.rs
+++ b/src/test/compile-fail/unsendable-class.rs
@@ -27,6 +27,6 @@ fn foo(i:int, j: @~str) -> foo {
 
 fn main() {
   let cat = ~"kitty";
-    let (_, ch) = comm::stream(); //~ ERROR does not fulfill `Owned`
-  ch.send(foo(42, @(cat))); //~ ERROR does not fulfill `Owned`
+    let (_, ch) = comm::stream(); //~ ERROR does not fulfill `Send`
+  ch.send(foo(42, @(cat))); //~ ERROR does not fulfill `Send`
 }
diff --git a/src/test/debug-info/basic-types.rs b/src/test/debug-info/basic-types.rs
index 616740c850c..7125ebe8d56 100644
--- a/src/test/debug-info/basic-types.rs
+++ b/src/test/debug-info/basic-types.rs
@@ -26,8 +26,8 @@
 // check:$2 = -1
 // debugger:print c
 // check:$3 = 97
-// debugger:print i8
-// check:$4 = 68 'D'
+// debugger:print/d i8
+// check:$4 = 68
 // debugger:print i16
 // check:$5 = -16
 // debugger:print i32
@@ -36,8 +36,8 @@
 // check:$7 = -64
 // debugger:print u
 // check:$8 = 1
-// debugger:print u8
-// check:$9 = 100 'd'
+// debugger:print/d u8
+// check:$9 = 100
 // debugger:print u16
 // check:$10 = 16
 // debugger:print u32
diff --git a/src/test/debug-info/tuple.rs b/src/test/debug-info/destructured-local.rs
index a50996871ce..bf53d95b588 100644
--- a/src/test/debug-info/tuple.rs
+++ b/src/test/debug-info/destructured-local.rs
@@ -8,19 +8,26 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+// xfail-test
+
+// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
+// value.
 
 // compile-flags:-Z extra-debug-info
-// debugger:set print pretty off
-// debugger:break _zzz
+// debugger:break zzz
 // debugger:run
 // debugger:finish
-// debugger:print t
-// check:$1 = {4, 5.5, true}
+
+// debugger:print a
+// check:$1 = 9898
+
+// debugger:print b
+// check:$2 = false
 
 fn main() {
-    let t = (4, 5.5, true);
-    _zzz();
+    let (a, b) : (int, bool) = (9898, false);
+
+    zzz();
 }
 
-fn _zzz() {()}
\ No newline at end of file
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/function-arguments.rs b/src/test/debug-info/function-arguments.rs
new file mode 100644
index 00000000000..f5563cda259
--- /dev/null
+++ b/src/test/debug-info/function-arguments.rs
@@ -0,0 +1,51 @@
+// 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.
+
+// xfail-test
+
+// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
+// value.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print x
+// check:$1 = 111102
+// debugger:print y
+// check:$2 = true
+
+// debugger:continue
+// debugger:finish
+
+// debugger:print a
+// check:$3 = 2000
+// debugger:print b
+// check:$4 = 3000
+
+fn main() {
+
+    fun(111102, true);
+    nested(2000, 3000);
+
+    fn nested(a: i32, b: i64) -> (i32, i64) {
+        zzz()
+        (a, b)
+    }
+}
+
+fn fun(x: int, y: bool) -> (int, bool) {
+    zzz();
+
+    (x, y)
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/reference-to-basic.rs b/src/test/debug-info/reference-to-basic.rs
new file mode 100644
index 00000000000..dfd0fbf8655
--- /dev/null
+++ b/src/test/debug-info/reference-to-basic.rs
@@ -0,0 +1,116 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
+// as its numerical value along with its associated ASCII char, there
+// doesn't seem to be any way around this. Also, gdb doesn't know
+// about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+// debugger:print *bool_ref
+// check:$1 = true
+
+// debugger:print *int_ref
+// check:$2 = -1
+
+// debugger:print *char_ref
+// check:$3 = 97
+
+// debugger:print *i8_ref
+// check:$4 = 68 'D'
+
+// debugger:print *i16_ref
+// check:$5 = -16
+
+// debugger:print *i32_ref
+// check:$6 = -32
+
+// debugger:print *i64_ref
+// check:$7 = -64
+
+// debugger:print *uint_ref
+// check:$8 = 1
+
+// debugger:print *u8_ref
+// check:$9 = 100 'd'
+
+// debugger:print *u16_ref
+// check:$10 = 16
+
+// debugger:print *u32_ref
+// check:$11 = 32
+
+// debugger:print *u64_ref
+// check:$12 = 64
+
+// debugger:print *float_ref
+// check:$13 = 1.5
+
+// debugger:print *f32_ref
+// check:$14 = 2.5
+
+// debugger:print *f64_ref
+// check:$15 = 3.5
+
+fn main() {
+    let bool_val: bool = true;
+    let bool_ref : &bool = &bool_val;
+
+    let int_val: int = -1;
+    let int_ref : &int = &int_val;
+
+    let char_val: char = 'a';
+    let char_ref : &char = &char_val;
+
+    let i8_val: i8 = 68;
+    let i8_ref : &i8 = &i8_val;
+
+    let i16_val: i16 = -16;
+    let i16_ref : &i16 = &i16_val;
+
+    let i32_val: i32 = -32;
+    let i32_ref : &i32 = &i32_val;
+
+    let uint_val: i64 = -64;
+    let i64_ref : &i64 = &uint_val;
+
+    let uint_val: uint = 1;
+    let uint_ref : &uint = &uint_val;
+
+    let u8_val: u8 = 100;
+    let u8_ref : &u8 = &u8_val;
+
+    let u16_val: u16 = 16;
+    let u16_ref : &u16 = &u16_val;
+
+    let u32_val: u32 = 32;
+    let u32_ref : &u32 = &u32_val;
+
+    let u64_val: u64 = 64;
+    let u64_ref : &u64 = &u64_val;
+
+    let float_val: float = 1.5;
+    let float_ref : &float = &float_val;
+
+    let f32_val: f32 = 2.5;
+    let f32_ref : &f32 = &f32_val;
+
+    let f64_val: f64 = 3.5;
+    let f64_ref : &f64 = &f64_val;
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/reference-to-managed-basic.rs b/src/test/debug-info/reference-to-managed-basic.rs
new file mode 100644
index 00000000000..e3951c94b6f
--- /dev/null
+++ b/src/test/debug-info/reference-to-managed-basic.rs
@@ -0,0 +1,114 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+// debugger:print *bool_ref
+// check:$1 = true
+
+// debugger:print *int_ref
+// check:$2 = -1
+
+// debugger:print *char_ref
+// check:$3 = 97
+
+// debugger:print/d *i8_ref
+// check:$4 = 68
+
+// debugger:print *i16_ref
+// check:$5 = -16
+
+// debugger:print *i32_ref
+// check:$6 = -32
+
+// debugger:print *i64_ref
+// check:$7 = -64
+
+// debugger:print *uint_ref
+// check:$8 = 1
+
+// debugger:print/d *u8_ref
+// check:$9 = 100
+
+// debugger:print *u16_ref
+// check:$10 = 16
+
+// debugger:print *u32_ref
+// check:$11 = 32
+
+// debugger:print *u64_ref
+// check:$12 = 64
+
+// debugger:print *float_ref
+// check:$13 = 1.5
+
+// debugger:print *f32_ref
+// check:$14 = 2.5
+
+// debugger:print *f64_ref
+// check:$15 = 3.5
+
+
+fn main() {
+    let bool_box: @bool = @true;
+    let bool_ref : &bool = bool_box;
+
+    let int_box: @int = @-1;
+    let int_ref : &int = int_box;
+
+    let char_box: @char = @'a';
+    let char_ref : &char = char_box;
+
+    let i8_box: @i8 = @68;
+    let i8_ref : &i8 = i8_box;
+
+    let i16_box: @i16 = @-16;
+    let i16_ref : &i16 = i16_box;
+
+    let i32_box: @i32 = @-32;
+    let i32_ref : &i32 = i32_box;
+
+    let i64_box: @i64 = @-64;
+    let i64_ref : &i64 = i64_box;
+
+    let uint_box: @uint = @1;
+    let uint_ref : &uint = uint_box;
+
+    let u8_box: @u8 = @100;
+    let u8_ref : &u8 = u8_box;
+
+    let u16_box: @u16 = @16;
+    let u16_ref : &u16 = u16_box;
+
+    let u32_box: @u32 = @32;
+    let u32_ref : &u32 = u32_box;
+
+    let u64_box: @u64 = @64;
+    let u64_ref : &u64 = u64_box;
+
+    let float_box: @float = @1.5;
+    let float_ref : &float = float_box;
+
+    let f32_box: @f32 = @2.5;
+    let f32_ref : &f32 = f32_box;
+
+    let f64_box: @f64 = @3.5;
+    let f64_ref : &f64 = f64_box;
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/reference-to-struct.rs b/src/test/debug-info/reference-to-struct.rs
new file mode 100644
index 00000000000..f00872c00b0
--- /dev/null
+++ b/src/test/debug-info/reference-to-struct.rs
@@ -0,0 +1,78 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
+// value.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *stack_val_ref
+// check:$1 = {x = 10, y = 23.5}
+
+// debugger:print *stack_val_interior_ref_1
+// check:$2 = 10
+
+// debugger:print *stack_val_interior_ref_2
+// check:$3 = 23.5
+
+// debugger:print *ref_to_unnamed
+// check:$4 = {x = 11, y = 24.5}
+
+// debugger:print *managed_val_ref
+// check:$5 = {x = 12, y = 25.5}
+
+// debugger:print *managed_val_interior_ref_1
+// check:$6 = 12
+
+// debugger:print *managed_val_interior_ref_2
+// check:$7 = 25.5
+
+// debugger:print *unique_val_ref
+// check:$8 = {x = 13, y = 26.5}
+
+// debugger:print *unique_val_interior_ref_1
+// check:$9 = 13
+
+// debugger:print *unique_val_interior_ref_2
+// check:$10 = 26.5
+
+
+
+struct SomeStruct {
+    x: int,
+    y: f64
+}
+
+fn main() {
+    let stack_val: SomeStruct = SomeStruct { x: 10, y: 23.5 };
+    let stack_val_ref : &SomeStruct = &stack_val;
+    let stack_val_interior_ref_1 : &int = &stack_val.x;
+    let stack_val_interior_ref_2 : &f64 = &stack_val.y;
+    let ref_to_unnamed : &SomeStruct = &SomeStruct { x: 11, y: 24.5 };
+
+    let managed_val = @SomeStruct { x: 12, y: 25.5 };
+    let managed_val_ref : &SomeStruct = managed_val;
+    let managed_val_interior_ref_1 : &int = &managed_val.x;
+    let managed_val_interior_ref_2 : &f64 = &managed_val.y;
+
+    let unique_val = ~SomeStruct { x: 13, y: 26.5 };
+    let unique_val_ref : &SomeStruct = unique_val;
+    let unique_val_interior_ref_1 : &int = &unique_val.x;
+    let unique_val_interior_ref_2 : &f64 = &unique_val.y;
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/reference-to-tuple.rs b/src/test/debug-info/reference-to-tuple.rs
new file mode 100644
index 00000000000..86d02185bda
--- /dev/null
+++ b/src/test/debug-info/reference-to-tuple.rs
@@ -0,0 +1,47 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
+// value.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *stack_val_ref
+// check:$1 = {-14, -19}
+
+// debugger:print *ref_to_unnamed
+// check:$2 = {-15, -20}
+
+// debugger:print *managed_val_ref
+// check:$3 = {-16, -21}
+
+// debugger:print *unique_val_ref
+// check:$4 = {-17, -22}
+
+fn main() {
+    let stack_val: (i16, f32) = (-14, -19f32);
+    let stack_val_ref : &(i16, f32) = &stack_val;
+    let ref_to_unnamed : &(i16, f32) = &(-15, -20f32);
+
+    let managed_val : @(i16, f32) = @(-16, -21f32);
+    let managed_val_ref : &(i16, f32) = managed_val;
+
+    let unique_val: ~(i16, f32) = ~(-17, -22f32);
+    let unique_val_ref : &(i16, f32) = unique_val;
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/reference-to-unique-basic.rs b/src/test/debug-info/reference-to-unique-basic.rs
new file mode 100644
index 00000000000..ce5b50459f6
--- /dev/null
+++ b/src/test/debug-info/reference-to-unique-basic.rs
@@ -0,0 +1,115 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// Gdb doesn't know
+// about UTF-32 character encoding and will print a rust char as only
+// its numerical value.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+// debugger:print *bool_ref
+// check:$1 = true
+
+// debugger:print *int_ref
+// check:$2 = -1
+
+// debugger:print *char_ref
+// check:$3 = 97
+
+// debugger:print/d *i8_ref
+// check:$4 = 68
+
+// debugger:print *i16_ref
+// check:$5 = -16
+
+// debugger:print *i32_ref
+// check:$6 = -32
+
+// debugger:print *i64_ref
+// check:$7 = -64
+
+// debugger:print *uint_ref
+// check:$8 = 1
+
+// debugger:print/d *u8_ref
+// check:$9 = 100
+
+// debugger:print *u16_ref
+// check:$10 = 16
+
+// debugger:print *u32_ref
+// check:$11 = 32
+
+// debugger:print *u64_ref
+// check:$12 = 64
+
+// debugger:print *float_ref
+// check:$13 = 1.5
+
+// debugger:print *f32_ref
+// check:$14 = 2.5
+
+// debugger:print *f64_ref
+// check:$15 = 3.5
+
+
+fn main() {
+    let bool_box: ~bool = ~true;
+    let bool_ref : &bool = bool_box;
+
+    let int_box: ~int = ~-1;
+    let int_ref : &int = int_box;
+
+    let char_box: ~char = ~'a';
+    let char_ref : &char = char_box;
+
+    let i8_box: ~i8 = ~68;
+    let i8_ref : &i8 = i8_box;
+
+    let i16_box: ~i16 = ~-16;
+    let i16_ref : &i16 = i16_box;
+
+    let i32_box: ~i32 = ~-32;
+    let i32_ref : &i32 = i32_box;
+
+    let i64_box: ~i64 = ~-64;
+    let i64_ref : &i64 = i64_box;
+
+    let uint_box: ~uint = ~1;
+    let uint_ref : &uint = uint_box;
+
+    let u8_box: ~u8 = ~100;
+    let u8_ref : &u8 = u8_box;
+
+    let u16_box: ~u16 = ~16;
+    let u16_ref : &u16 = u16_box;
+
+    let u32_box: ~u32 = ~32;
+    let u32_ref : &u32 = u32_box;
+
+    let u64_box: ~u64 = ~64;
+    let u64_ref : &u64 = u64_box;
+
+    let float_box: ~float = ~1.5;
+    let float_ref : &float = float_box;
+
+    let f32_box: ~f32 = ~2.5;
+    let f32_ref : &f32 = f32_box;
+
+    let f64_box: ~f64 = ~3.5;
+    let f64_ref : &f64 = f64_box;
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/simple-struct.rs b/src/test/debug-info/simple-struct.rs
new file mode 100644
index 00000000000..49e7bc255c1
--- /dev/null
+++ b/src/test/debug-info/simple-struct.rs
@@ -0,0 +1,84 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print no_padding16
+// check:$1 = {x = 10000, y = -10001}
+
+// debugger:print no_padding32
+// check:$2 = {x = -10002, y = -10003.5, z = 10004}
+
+// debugger:print no_padding64
+// check:$3 = {x = -10005.5, y = 10006, z = 10007}
+
+// debugger:print no_padding163264
+// check:$4 = {a = -10008, b = 10009, c = 10010, d = 10011}
+
+// debugger:print internal_padding
+// check:$5 = {x = 10012, y = -10013}
+
+// debugger:print padding_at_end
+// check:$6 = {x = -10014, y = 10015}
+
+
+struct NoPadding16 {
+    x: u16,
+    y: i16
+}
+
+struct NoPadding32 {
+    x: i32,
+    y: f32,
+    z: u32
+}
+
+struct NoPadding64 {
+    x: f64,
+    y: i64,
+    z: u64
+}
+
+struct NoPadding163264 {
+    a: i16,
+    b: u16,
+    c: i32,
+    d: u64
+}
+
+struct InternalPadding {
+    x: u16,
+    y: i64
+}
+
+struct PaddingAtEnd {
+    x: i64,
+    y: u16
+}
+
+fn main() {
+    let no_padding16 = NoPadding16 { x: 10000, y: -10001 };
+    let no_padding32 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 };
+    let no_padding64 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 };
+    let no_padding163264 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 };
+
+    let internal_padding = InternalPadding { x: 10012, y: -10013 };
+    let padding_at_end = PaddingAtEnd { x: -10014, y: 10015 };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/simple-tuple.rs b/src/test/debug-info/simple-tuple.rs
new file mode 100644
index 00000000000..84c736fab6b
--- /dev/null
+++ b/src/test/debug-info/simple-tuple.rs
@@ -0,0 +1,51 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print/d noPadding8
+// check:$1 = {-100, 100}
+// debugger:print noPadding16
+// check:$2 = {0, 1, 2}
+// debugger:print noPadding32
+// check:$3 = {3, 4.5, 5}
+// debugger:print noPadding64
+// check:$4 = {6, 7.5, 8}
+
+// debugger:print internalPadding1
+// check:$5 = {9, 10}
+// debugger:print internalPadding2
+// check:$6 = {11, 12, 13, 14}
+
+// debugger:print paddingAtEnd
+// check:$7 = {15, 16}
+
+
+fn main() {
+    let noPadding8 : (i8, u8) = (-100, 100);
+    let noPadding16 : (i16, i16, u16) = (0, 1, 2);
+    let noPadding32 : (i32, f32, u32) = (3, 4.5, 5);
+    let noPadding64 : (i64, f64, u64) = (6, 7.5, 8);
+
+    let internalPadding1 : (i16, i32) = (9, 10);
+    let internalPadding2 : (i16, i32, u32, u64) = (11, 12, 13, 14);
+
+    let paddingAtEnd : (i32, i16) = (15, 16);
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/struct-in-struct.rs b/src/test/debug-info/struct-in-struct.rs
new file mode 100644
index 00000000000..04c5eec610b
--- /dev/null
+++ b/src/test/debug-info/struct-in-struct.rs
@@ -0,0 +1,145 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print three_simple_structs
+// check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}}
+
+// debugger:print internal_padding_parent
+// check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}}
+
+// debugger:print padding_at_end_parent
+// check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}}
+
+
+struct Simple {
+    x: i32
+}
+
+struct InternalPadding {
+    x: i32,
+    y: i64
+}
+
+struct PaddingAtEnd {
+    x: i64,
+    y: i32
+}
+
+struct ThreeSimpleStructs {
+    x: Simple,
+    y: Simple,
+    z: Simple
+}
+
+struct InternalPaddingParent {
+    x: InternalPadding,
+    y: InternalPadding,
+    z: InternalPadding
+}
+
+struct PaddingAtEndParent {
+    x: PaddingAtEnd,
+    y: PaddingAtEnd,
+    z: PaddingAtEnd
+}
+
+struct Mixed {
+    x: PaddingAtEnd,
+    y: InternalPadding,
+    z: Simple,
+    w: i16
+}
+
+struct Bag {
+    x: Simple
+}
+
+struct BagInBag {
+    x: Bag
+}
+
+struct ThatsJustOverkill {
+    x: BagInBag
+}
+
+struct Tree {
+    x: Simple,
+    y: InternalPaddingParent,
+    z: BagInBag
+}
+
+fn main() {
+
+    let three_simple_structs = ThreeSimpleStructs {
+        x: Simple { x: 1 },
+        y: Simple { x: 2 },
+        z: Simple { x: 3 }
+    };
+
+    let internal_padding_parent = InternalPaddingParent {
+        x: InternalPadding { x: 4, y: 5 },
+        y: InternalPadding { x: 6, y: 7 },
+        z: InternalPadding { x: 8, y: 9 }
+    };
+
+    let padding_at_end_parent = PaddingAtEndParent {
+        x: PaddingAtEnd { x: 10, y: 11 },
+        y: PaddingAtEnd { x: 12, y: 13 },
+        z: PaddingAtEnd { x: 14, y: 15 }
+    };
+
+    let mixed = Mixed {
+        x: PaddingAtEnd { x: 16, y: 17 },
+        y: InternalPadding { x: 18, y: 19 },
+        z: Simple { x: 20 },
+        w: 21
+    };
+
+    let bag = Bag { x: Simple { x: 22 } };
+    let bag_in_bag = BagInBag {
+        x: Bag {
+            x: Simple { x: 23 }
+        }
+    };
+
+    let tjo = ThatsJustOverkill {
+        x: BagInBag {
+            x: Bag {
+                x: Simple { x: 24 }
+            }
+        }
+    };
+
+    let tree = Tree {
+        x: Simple { x: 25 },
+        y: InternalPaddingParent {
+            x: InternalPadding { x: 26, y: 27 },
+            y: InternalPadding { x: 28, y: 29 },
+            z: InternalPadding { x: 30, y: 31 }
+        },
+        z: BagInBag {
+            x: Bag {
+                x: Simple { x: 32 }
+            }
+        }
+    };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs
new file mode 100644
index 00000000000..f8281bba49e
--- /dev/null
+++ b/src/test/debug-info/struct-with-destructor.rs
@@ -0,0 +1,88 @@
+// 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.
+
+// xfail-test
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+// debugger:print simple
+// check:$1 = {x = 10, y = 20}
+
+// debugger:print noDestructor
+// check:$2 = {a = {x = 10, y = 20}, guard = -1}
+
+// debugger:print withDestructor
+// check:$3 = {a = {x = 10, y = 20}, guard = -1}
+
+struct NoDestructor {
+    x : i32,
+    y : i64
+}
+
+struct WithDestructor {
+    x : i32,
+    y : i64
+}
+
+impl Drop for WithDestructor {
+    fn finalize(&self) {}
+}
+
+struct NoDestructorGuarded {
+    a: NoDestructor,
+    guard: i64
+}
+
+struct WithDestructorGuarded {
+    a: WithDestructor,
+    guard: i64
+}
+
+
+// The compiler adds a 'destructed' boolean field to structs implementing Drop. This field is used
+// at runtime to prevent drop() to be executed more than once (see middle::trans::adt).
+// This field must be incorporated by the debug info generation. Otherwise the debugger assumes a
+// wrong size/layout for the struct.
+fn main() {
+
+    let simple = WithDestructor { x: 10, y: 20 };
+
+    let noDestructor = NoDestructorGuarded {
+        a: NoDestructor { x: 10, y: 20 },
+        guard: -1
+    };
+
+    // If the destructor flag field is not incorporated into the debug info for 'WithDestructor'
+    // then the debugger will have an invalid offset for the field 'guard' and thus should not be
+    // able to read its value correctly (dots are padding bytes, D is the boolean destructor flag):
+    //
+    // NoDestructorGuarded = 0000....00000000FFFFFFFF
+    //                       <--------------><------>
+    //                         NoDestructor   guard
+    //
+    //
+    // withDestructorGuarded = 0000....00000000D.......FFFFFFFF
+    //                         <--------------><------>          // How debug info says it is
+    //                          WithDestructor  guard
+    //
+    //                         <----------------------><------>  // How it actually is
+    //                              WithDestructor      guard
+    //
+    let withDestructor = WithDestructorGuarded {
+        a: WithDestructor { x: 10, y: 20 },
+        guard: -1
+    };
+
+    zzz();
+}
+
+fn zzz() {()}
diff --git a/src/test/debug-info/tuple-in-struct.rs b/src/test/debug-info/tuple-in-struct.rs
new file mode 100644
index 00000000000..369c9fd28cc
--- /dev/null
+++ b/src/test/debug-info/tuple-in-struct.rs
@@ -0,0 +1,151 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print no_padding1
+// check:$1 = {x = {0, 1}, y = 2, z = {3, 4, 5}}
+// debugger:print no_padding2
+// check:$2 = {x = {6, 7}, y = {{8, 9}, 10}}
+
+// debugger:print tuple_internal_padding
+// check:$3 = {x = {11, 12}, y = {13, 14}}
+// debugger:print struct_internal_padding
+// check:$4 = {x = {15, 16}, y = {17, 18}}
+// debugger:print both_internally_padded
+// check:$5 = {x = {19, 20, 21}, y = {22, 23}}
+
+// debugger:print single_tuple
+// check:$6 = {x = {24, 25, 26}}
+
+// debugger:print tuple_padded_at_end
+// check:$7 = {x = {27, 28}, y = {29, 30}}
+// debugger:print struct_padded_at_end
+// check:$8 = {x = {31, 32}, y = {33, 34}}
+// debugger:print both_padded_at_end
+// check:$9 = {x = {35, 36, 37}, y = {38, 39}}
+
+// debugger:print mixed_padding
+// check:$10 = {x = {{40, 41, 42}, {43, 44}}, y = {45, 46, 47, 48}}
+
+struct NoPadding1 {
+    x: (i32, i32),
+    y: i32,
+    z: (i32, i32, i32)
+}
+
+struct NoPadding2 {
+    x: (i32, i32),
+    y: ((i32, i32), i32)
+}
+
+struct TupleInternalPadding {
+    x: (i16, i32),
+    y: (i32, i64)
+}
+
+struct StructInternalPadding {
+    x: (i16, i16),
+    y: (i64, i64)
+}
+
+struct BothInternallyPadded {
+    x: (i16, i32, i32),
+    y: (i32, i64)
+}
+
+struct SingleTuple {
+    x: (i16, i32, i64)
+}
+
+struct TuplePaddedAtEnd {
+    x: (i32, i16),
+    y: (i64, i32)
+}
+
+struct StructPaddedAtEnd {
+    x: (i64, i64),
+    y: (i16, i16)
+}
+
+struct BothPaddedAtEnd {
+    x: (i32, i32, i16),
+    y: (i64, i32)
+}
+
+// Data-layout (padding signified by dots, one column = 2 bytes):
+// [a.bbc...ddddee..ffffg.hhi...]
+struct MixedPadding {
+    x: ((i16, i32, i16), (i64, i32)),
+    y: (i64, i16, i32, i16)
+}
+
+
+fn main() {
+    let no_padding1 = NoPadding1 {
+        x: (0, 1),
+        y: 2,
+        z: (3, 4, 5)
+    };
+
+    let no_padding2 = NoPadding2 {
+        x: (6, 7),
+        y: ((8, 9), 10)
+    };
+
+    let tuple_internal_padding = TupleInternalPadding {
+        x: (11, 12),
+        y: (13, 14)
+    };
+
+    let struct_internal_padding = StructInternalPadding {
+        x: (15, 16),
+        y: (17, 18)
+    };
+
+    let both_internally_padded = BothInternallyPadded {
+        x: (19, 20, 21),
+        y: (22, 23)
+    };
+
+    let single_tuple = SingleTuple {
+        x: (24, 25, 26)
+    };
+
+    let tuple_padded_at_end = TuplePaddedAtEnd {
+        x: (27, 28),
+        y: (29, 30)
+    };
+
+    let struct_padded_at_end = StructPaddedAtEnd {
+        x: (31, 32),
+        y: (33, 34)
+    };
+
+    let both_padded_at_end = BothPaddedAtEnd {
+        x: (35, 36, 37),
+        y: (38, 39)
+    };
+
+    let mixed_padding = MixedPadding {
+        x: ((40, 41, 42), (43, 44)),
+        y: (45, 46, 47, 48)
+    };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/tuple-in-tuple.rs b/src/test/debug-info/tuple-in-tuple.rs
new file mode 100644
index 00000000000..13f8719694e
--- /dev/null
+++ b/src/test/debug-info/tuple-in-tuple.rs
@@ -0,0 +1,50 @@
+// 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.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print no_padding1
+// check:$1 = {{0, 1}, 2, 3}
+// debugger:print no_padding2
+// check:$2 = {4, {5, 6}, 7}
+// debugger:print no_padding3
+// check:$3 = {8, 9, {10, 11}}
+
+// debugger:print internal_padding1
+// check:$4 = {12, {13, 14}}
+// debugger:print internal_padding2
+// check:$5 = {15, {16, 17}}
+
+// debugger:print padding_at_end1
+// check:$6 = {18, {19, 20}}
+// debugger:print padding_at_end2
+// check:$7 = {{21, 22}, 23}
+
+fn main() {
+    let no_padding1 : ((u32, u32), u32, u32) = ((0, 1), 2, 3);
+    let no_padding2 : (u32, (u32, u32), u32) = (4, (5, 6), 7);
+    let no_padding3 : (u32, u32, (u32, u32)) = (8, 9, (10, 11));
+
+    let internal_padding1 : (i16, (i32, i32)) = (12, (13, 14));
+    let internal_padding2 : (i16, (i16, i32)) = (15, (16, 17));
+
+    let padding_at_end1 : (i32, (i32, i16)) = (18, (19, 20));
+    let padding_at_end2 : ((i32, i16), i32) = ((21, 22), 23);
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/variable-scope.rs
index ddfac9cbeea..dd3a1671b78 100644
--- a/src/test/debug-info/struct.rs
+++ b/src/test/debug-info/variable-scope.rs
@@ -8,28 +8,42 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+// xfail-test
 
 // compile-flags:-Z extra-debug-info
-// debugger:set print pretty off
-// debugger:break _zzz
+// debugger:break zzz
 // debugger:run
 // debugger:finish
-// debugger:print pair
-// check:$1 = {x = 1, y = 2}
-// debugger:print pair.x
-// check:$2 = 1
-// debugger:print pair.y
-// check:$3 = 2
-
-struct Pair {
-    x: int,
-    y: int
-}
+// debugger:print x
+// check:$1 = false
+// debugger:print y
+// check:$2 = true
+
+// debugger:continue
+// debugger:finish
+// debugger:print x
+// check:$3 = 10
+
+// debugger:continue
+// debugger:finish
+// debugger:print x
+// check:$4 = false
+// debugger:print y
+// check:$5 = 11
 
 fn main() {
-    let pair = Pair { x: 1, y: 2 };
-    _zzz();
+    let x = false;
+    let y = true;
+
+    zzz();
+
+    {
+        let x = 10;
+        zzz();
+    }
+
+    let y = 11;
+    zzz();
 }
 
-fn _zzz() {()}
\ No newline at end of file
+fn zzz() {()}
diff --git a/src/test/run-fail/bug-811.rs b/src/test/run-fail/bug-811.rs
index b497b0224b9..992747187f6 100644
--- a/src/test/run-fail/bug-811.rs
+++ b/src/test/run-fail/bug-811.rs
@@ -19,6 +19,6 @@ struct chan_t<T> {
     port: port_id,
 }
 
-fn send<T:Owned>(ch: chan_t<T>, data: T) { fail!(); }
+fn send<T:Send>(ch: chan_t<T>, data: T) { fail!(); }
 
 fn main() { fail!("quux"); }
diff --git a/src/test/run-fail/issue-3029.rs b/src/test/run-fail/issue-3029.rs
index 6f4a3f5ab1d..caee0002788 100644
--- a/src/test/run-fail/issue-3029.rs
+++ b/src/test/run-fail/issue-3029.rs
@@ -10,9 +10,9 @@
 
 // error-pattern:so long
 fn main() {
-    let x = ~[];
+    let mut x = ~[];
     let y = ~[3];
     fail!("so long");
-    x += y;
+    x.push_all_move(y);
     ~"good" + ~"bye";
 }
diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs
index 753e5339de9..24709fb2974 100644
--- a/src/test/run-pass/alignment-gep-tup-like-2.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-2.rs
@@ -23,7 +23,7 @@ fn make_cycle<A:Copy>(a: A) {
     g.rec = Some(g);
 }
 
-fn f<A:Owned + Copy,B:Owned + Copy>(a: A, b: B) -> @fn() -> (A, B) {
+fn f<A:Send + Copy,B:Send + Copy>(a: A, b: B) -> @fn() -> (A, B) {
     let result: @fn() -> (A, B) = || (copy a, copy b);
     result
 }
diff --git a/src/test/run-pass/attr-no-drop-flag-size.rs b/src/test/run-pass/attr-no-drop-flag-size.rs
index 00a7955d834..87c476d781e 100644
--- a/src/test/run-pass/attr-no-drop-flag-size.rs
+++ b/src/test/run-pass/attr-no-drop-flag-size.rs
@@ -10,7 +10,7 @@
 
 use std::sys::size_of;
 
-#[no_drop_flag]
+#[unsafe_no_drop_flag]
 struct Test<T> {
     a: T
 }
diff --git a/src/test/run-pass/bug-7183-generics.rs b/src/test/run-pass/bug-7183-generics.rs
new file mode 100644
index 00000000000..4fc5587e7f3
--- /dev/null
+++ b/src/test/run-pass/bug-7183-generics.rs
@@ -0,0 +1,45 @@
+// 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(default_methods)]
+trait Speak {
+    fn say(&self, s:&str) -> ~str;
+    fn hi(&self) -> ~str { hello(self) }
+}
+
+fn hello<S:Speak>(s:&S) -> ~str{
+    s.say("hello")
+}
+
+impl Speak for int {
+    fn say(&self, s:&str) -> ~str {
+        fmt!("%s: %d", s, *self)
+    }
+}
+
+impl<T: Speak> Speak for Option<T> {
+    fn say(&self, s:&str) -> ~str {
+        match *self {
+            None => fmt!("%s - none", s),
+            Some(ref x) => { ~"something!" + x.say(s) }
+        }
+    }
+}
+
+
+fn main() {
+    assert_eq!(3.hi(), ~"hello: 3");
+    assert_eq!(Some(Some(3)).hi(), ~"something!something!hello: 3");
+    assert_eq!(None::<int>.hi(), ~"hello - none");
+
+    // These fail because of a bug in monomorphization's ID generation.
+    //assert_eq!(Some(None::<int>).hi(), ~"something!hello - none");
+    //assert_eq!(Some(3).hi(), ~"something!hello: 3");
+}
diff --git a/src/test/run-pass/closure-bounds-can-capture-chan.rs b/src/test/run-pass/closure-bounds-can-capture-chan.rs
index 26bea0e5141..95b0c9d79b7 100644
--- a/src/test/run-pass/closure-bounds-can-capture-chan.rs
+++ b/src/test/run-pass/closure-bounds-can-capture-chan.rs
@@ -10,7 +10,7 @@
 
 use std::comm;
 
-fn foo(blk: ~fn:Owned()) {
+fn foo(blk: ~fn:Send()) {
     blk();
 }
 
diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs
index 685d86c740d..05f586f76e9 100644
--- a/src/test/run-pass/const-bound.rs
+++ b/src/test/run-pass/const-bound.rs
@@ -12,7 +12,7 @@
 // are const.
 
 
-fn foo<T:Copy + Const>(x: T) -> T { x }
+fn foo<T:Copy + Freeze>(x: T) -> T { x }
 
 struct F { field: int }
 
diff --git a/src/test/run-pass/fixed-point-bind-unique.rs b/src/test/run-pass/fixed-point-bind-unique.rs
index 53f9c723a47..c7b64fde3fd 100644
--- a/src/test/run-pass/fixed-point-bind-unique.rs
+++ b/src/test/run-pass/fixed-point-bind-unique.rs
@@ -10,11 +10,11 @@
 
 // xfail-fast
 
-fn fix_help<A:'static,B:Owned>(f: extern fn(@fn(A) -> B, A) -> B, x: A) -> B {
+fn fix_help<A:'static,B:Send>(f: extern fn(@fn(A) -> B, A) -> B, x: A) -> B {
     return f(|a| fix_help(f, a), x);
 }
 
-fn fix<A:'static,B:Owned>(f: extern fn(@fn(A) -> B, A) -> B) -> @fn(A) -> B {
+fn fix<A:'static,B:Send>(f: extern fn(@fn(A) -> B, A) -> B) -> @fn(A) -> B {
     return |a| fix_help(f, a);
 }
 
diff --git a/src/test/run-pass/fn-bare-spawn.rs b/src/test/run-pass/fn-bare-spawn.rs
index 4f0f451a08c..e9954be9357 100644
--- a/src/test/run-pass/fn-bare-spawn.rs
+++ b/src/test/run-pass/fn-bare-spawn.rs
@@ -10,7 +10,7 @@
 
 // This is what the signature to spawn should look like with bare functions
 
-fn spawn<T:Owned>(val: T, f: extern fn(T)) {
+fn spawn<T:Send>(val: T, f: extern fn(T)) {
     f(val);
 }
 
diff --git a/src/test/run-pass/generic-alias-unique.rs b/src/test/run-pass/generic-alias-unique.rs
index ad271186639..815cc1bc79b 100644
--- a/src/test/run-pass/generic-alias-unique.rs
+++ b/src/test/run-pass/generic-alias-unique.rs
@@ -10,7 +10,7 @@
 
 
 
-fn id<T:Copy + Owned>(t: T) -> T { return t; }
+fn id<T:Copy + Send>(t: T) -> T { return t; }
 
 pub fn main() {
     let expected = ~100;
diff --git a/src/test/run-pass/issue-2611-3.rs b/src/test/run-pass/issue-2611-3.rs
index acc6ffd0dd1..7f653552631 100644
--- a/src/test/run-pass/issue-2611-3.rs
+++ b/src/test/run-pass/issue-2611-3.rs
@@ -12,7 +12,7 @@
 // than the traits require.
 
 trait A {
-  fn b<C:Copy + Const,D>(x: C) -> C;
+  fn b<C:Copy + Freeze,D>(x: C) -> C;
 }
 
 struct E {
diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs
index 9fbca7d0572..14915555889 100644
--- a/src/test/run-pass/issue-2718.rs
+++ b/src/test/run-pass/issue-2718.rs
@@ -39,7 +39,7 @@ pub mod pipes {
         payload: Option<T>
     }
 
-    pub fn packet<T:Owned>() -> *packet<T> {
+    pub fn packet<T:Send>() -> *packet<T> {
         unsafe {
             let p: *packet<T> = cast::transmute(~Stuff{
                 state: empty,
@@ -74,7 +74,7 @@ pub mod pipes {
         }
     }
 
-    pub fn send<T:Owned>(mut p: send_packet<T>, payload: T) {
+    pub fn send<T:Send>(mut p: send_packet<T>, payload: T) {
         let mut p = p.unwrap();
         let mut p = unsafe { uniquify(p) };
         assert!((*p).payload.is_none());
@@ -100,7 +100,7 @@ pub mod pipes {
         }
     }
 
-    pub fn recv<T:Owned>(mut p: recv_packet<T>) -> Option<T> {
+    pub fn recv<T:Send>(mut p: recv_packet<T>) -> Option<T> {
         let mut p = p.unwrap();
         let mut p = unsafe { uniquify(p) };
         loop {
@@ -120,7 +120,7 @@ pub mod pipes {
         }
     }
 
-    pub fn sender_terminate<T:Owned>(mut p: *packet<T>) {
+    pub fn sender_terminate<T:Send>(mut p: *packet<T>) {
         let mut p = unsafe { uniquify(p) };
         match swap_state_rel(&mut (*p).state, terminated) {
           empty | blocked => {
@@ -137,7 +137,7 @@ pub mod pipes {
         }
     }
 
-    pub fn receiver_terminate<T:Owned>(mut p: *packet<T>) {
+    pub fn receiver_terminate<T:Send>(mut p: *packet<T>) {
         let mut p = unsafe { uniquify(p) };
         match swap_state_rel(&mut (*p).state, terminated) {
           empty => {
@@ -159,7 +159,7 @@ pub mod pipes {
     }
 
     #[unsafe_destructor]
-    impl<T:Owned> Drop for send_packet<T> {
+    impl<T:Send> Drop for send_packet<T> {
         fn drop(&self) {
             unsafe {
                 if self.p != None {
@@ -172,13 +172,13 @@ pub mod pipes {
         }
     }
 
-    impl<T:Owned> send_packet<T> {
+    impl<T:Send> send_packet<T> {
         pub fn unwrap(&mut self) -> *packet<T> {
             util::replace(&mut self.p, None).unwrap()
         }
     }
 
-    pub fn send_packet<T:Owned>(p: *packet<T>) -> send_packet<T> {
+    pub fn send_packet<T:Send>(p: *packet<T>) -> send_packet<T> {
         send_packet {
             p: Some(p)
         }
@@ -189,7 +189,7 @@ pub mod pipes {
     }
 
     #[unsafe_destructor]
-    impl<T:Owned> Drop for recv_packet<T> {
+    impl<T:Send> Drop for recv_packet<T> {
         fn drop(&self) {
             unsafe {
                 if self.p != None {
@@ -202,19 +202,19 @@ pub mod pipes {
         }
     }
 
-    impl<T:Owned> recv_packet<T> {
+    impl<T:Send> recv_packet<T> {
         pub fn unwrap(&mut self) -> *packet<T> {
             util::replace(&mut self.p, None).unwrap()
         }
     }
 
-    pub fn recv_packet<T:Owned>(p: *packet<T>) -> recv_packet<T> {
+    pub fn recv_packet<T:Send>(p: *packet<T>) -> recv_packet<T> {
         recv_packet {
             p: Some(p)
         }
     }
 
-    pub fn entangle<T:Owned>() -> (send_packet<T>, recv_packet<T>) {
+    pub fn entangle<T:Send>() -> (send_packet<T>, recv_packet<T>) {
         let p = packet();
         (send_packet(p), recv_packet(p))
     }
diff --git a/src/test/run-pass/issue-2834.rs b/src/test/run-pass/issue-2834.rs
index 5d3a2d2331c..b0ddccf2894 100644
--- a/src/test/run-pass/issue-2834.rs
+++ b/src/test/run-pass/issue-2834.rs
@@ -12,7 +12,7 @@
 //
 
 proto! streamp (
-    open:send<T:Owned> {
+    open:send<T:Send> {
         data(T) -> open<T>
     }
 )
diff --git a/src/test/run-pass/issue-2930.rs b/src/test/run-pass/issue-2930.rs
index cfce19826d7..10a19d62bd9 100644
--- a/src/test/run-pass/issue-2930.rs
+++ b/src/test/run-pass/issue-2930.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 proto! stream (
-    Stream:send<T:Owned> {
+    Stream:send<T:Send> {
         send(T) -> Stream<T>
     }
 )
diff --git a/src/test/run-pass/issue-3888-2.rs b/src/test/run-pass/issue-3888-2.rs
index 60c50624435..c9f6733fa25 100644
--- a/src/test/run-pass/issue-3888-2.rs
+++ b/src/test/run-pass/issue-3888-2.rs
@@ -8,12 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::vec;
-
 fn vec_peek<'r, T>(v: &'r [T]) -> &'r [T] {
-// This doesn't work, and should.
-//    v.slice(1, 5)
-    vec::slice(v, 1, 5)
+    v.slice(1, 5)
 }
 
 pub fn main() {}
diff --git a/src/test/run-pass/issue-5321-immediates-with-bare-self.rs b/src/test/run-pass/issue-5321-immediates-with-bare-self.rs
new file mode 100644
index 00000000000..7b809c39cb8
--- /dev/null
+++ b/src/test/run-pass/issue-5321-immediates-with-bare-self.rs
@@ -0,0 +1,25 @@
+// 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.
+
+trait Fooable {
+    fn yes(self);
+}
+
+impl Fooable for uint {
+    fn yes(self) {
+        for self.times {
+            println("yes");
+        }
+    }
+}
+
+fn main() {
+    2.yes();
+}
diff --git a/src/test/run-pass/istr.rs b/src/test/run-pass/istr.rs
index a82b2639449..ab89a357d34 100644
--- a/src/test/run-pass/istr.rs
+++ b/src/test/run-pass/istr.rs
@@ -44,19 +44,19 @@ fn test_heap_add() {
 
 fn test_append() {
     let mut s = ~"";
-    s += ~"a";
+    s.push_str(~"a");
     assert_eq!(s, ~"a");
 
     let mut s = ~"a";
-    s += ~"b";
+    s.push_str(~"b");
     debug!(s.clone());
     assert_eq!(s, ~"ab");
 
     let mut s = ~"c";
-    s += ~"offee";
+    s.push_str(~"offee");
     assert!(s == ~"coffee");
 
-    s += ~"&tea";
+    s.push_str(~"&tea");
     assert!(s == ~"coffee&tea");
 }
 
diff --git a/src/test/run-pass/let-destruct-fresh-mem.rs b/src/test/run-pass/let-destruct-fresh-mem.rs
index 500502320df..2615396653d 100644
--- a/src/test/run-pass/let-destruct-fresh-mem.rs
+++ b/src/test/run-pass/let-destruct-fresh-mem.rs
@@ -13,7 +13,9 @@ struct A { a: int }
 
 pub fn main() {
     let u = X {x: 10, y: @A {a: 20}};
-    let mut X {x: x, y: @A {a: a}} = u;
+    let X {x: x, y: @A {a: a}} = u;
+    let mut x = x;
+    let mut a = a;
     x = 100;
     a = 100;
     assert_eq!(x, 100);
diff --git a/src/test/run-pass/liveness-move-in-loop.rs b/src/test/run-pass/liveness-move-in-loop.rs
index acdf388a8ff..d910ac9a4e7 100644
--- a/src/test/run-pass/liveness-move-in-loop.rs
+++ b/src/test/run-pass/liveness-move-in-loop.rs
@@ -15,7 +15,7 @@ fn the_loop() {
     loop {
         let x = 5;
         if x > 3 {
-            list += ~[take(x)];
+            list.push(take(x));
         } else {
             break;
         }
diff --git a/src/test/run-pass/match-join.rs b/src/test/run-pass/match-join.rs
index 66b64768060..5ac62bae392 100644
--- a/src/test/run-pass/match-join.rs
+++ b/src/test/run-pass/match-join.rs
@@ -23,7 +23,7 @@ fn foo<T>(y: Option<T>) {
           None::<T> => x = 17,
           _ => x = 42
         }
-        rs += ~[x];
+        rs.push(x);
     }
     return;
 }
diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs
index 3f3cf5e5aaa..fe06c973dbf 100644
--- a/src/test/run-pass/monad.rs
+++ b/src/test/run-pass/monad.rs
@@ -19,7 +19,9 @@ trait vec_monad<A> {
 impl<A> vec_monad<A> for ~[A] {
     fn bind<B:Copy>(&self, f: &fn(&A) -> ~[B]) -> ~[B] {
         let mut r = ~[];
-        for self.iter().advance |elt| { r += f(elt); }
+        for self.iter().advance |elt| {
+            r.push_all_move(f(elt));
+        }
         r
     }
 }
diff --git a/src/test/run-pass/mutable-alias-vec.rs b/src/test/run-pass/mutable-alias-vec.rs
index 1d9e7d3c649..538aedcf7c8 100644
--- a/src/test/run-pass/mutable-alias-vec.rs
+++ b/src/test/run-pass/mutable-alias-vec.rs
@@ -13,7 +13,9 @@ extern mod extra;
 
 use std::vec;
 
-fn grow(v: &mut ~[int]) { *v += ~[1]; }
+fn grow(v: &mut ~[int]) {
+    v.push(1);
+}
 
 pub fn main() {
     let mut v: ~[int] = ~[];
diff --git a/src/test/run-pass/once-move-out-on-heap.rs b/src/test/run-pass/once-move-out-on-heap.rs
new file mode 100644
index 00000000000..38b23fd128d
--- /dev/null
+++ b/src/test/run-pass/once-move-out-on-heap.rs
@@ -0,0 +1,29 @@
+// 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.
+
+// Testing guarantees provided by once functions.
+
+// xfail-fast
+
+extern mod extra;
+use extra::arc;
+use std::util;
+
+fn foo(blk: ~once fn()) {
+    blk();
+}
+
+fn main() {
+    let x = arc::ARC(true);
+    do foo {
+        assert!(*x.get());
+        util::ignore(x);
+    }
+}
diff --git a/src/test/run-pass/once-move-out-on-stack.rs b/src/test/run-pass/once-move-out-on-stack.rs
new file mode 100644
index 00000000000..e881f576673
--- /dev/null
+++ b/src/test/run-pass/once-move-out-on-stack.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// Testing guarantees provided by once functions.
+
+// xfail-fast
+
+// compile-flags:-Z once-fns
+extern mod extra;
+use extra::arc;
+use std::util;
+
+fn foo(blk: &once fn()) {
+    blk();
+}
+
+fn main() {
+    let x = arc::ARC(true);
+    do foo {
+        assert!(*x.get());
+        util::ignore(x);
+    }
+}
diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs
index e75af5729d5..05aa1e74608 100644
--- a/src/test/run-pass/operator-overloading.rs
+++ b/src/test/run-pass/operator-overloading.rs
@@ -57,7 +57,7 @@ impl cmp::Eq for Point {
 
 pub fn main() {
     let mut p = Point {x: 10, y: 20};
-    p += Point {x: 101, y: 102};
+    p = p + Point {x: 101, y: 102};
     p = p - Point {x: 100, y: 100};
     assert_eq!(p + Point {x: 5, y: 5}, Point {x: 16, y: 27});
     assert_eq!(-p, Point {x: -11, y: -22});
diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs
index 7ac38966faa..11c43b93901 100644
--- a/src/test/run-pass/pipe-bank-proto.rs
+++ b/src/test/run-pass/pipe-bank-proto.rs
@@ -45,8 +45,8 @@ proto! bank (
     }
 )
 
-fn switch<T:Owned,U>(endp: pipes::RecvPacket<T>,
-                     f: &fn(v: Option<T>) -> U) -> U {
+fn switch<T:Send,U>(endp: pipes::RecvPacket<T>,
+                    f: &fn(v: Option<T>) -> U) -> U {
     f(pipes::try_recv(endp))
 }
 
diff --git a/src/test/run-pass/pipe-peek.rs b/src/test/run-pass/pipe-peek.rs
index 8d8c96c6f51..cbc822060ce 100644
--- a/src/test/run-pass/pipe-peek.rs
+++ b/src/test/run-pass/pipe-peek.rs
@@ -22,7 +22,9 @@ proto! oneshot (
 )
 
 pub fn main() {
-    let mut (p, c) = oneshot::init();
+    let (p, c) = oneshot::init();
+    let mut p = p;
+    let mut c = c;
 
     assert!(!pipes::peek(&mut p));
 
diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs
index 0a860d0a1e2..36f144152f2 100644
--- a/src/test/run-pass/pipe-select.rs
+++ b/src/test/run-pass/pipe-select.rs
@@ -29,12 +29,12 @@ proto! oneshot (
 )
 
 proto! stream (
-    Stream:send<T:Owned> {
+    Stream:send<T:Send> {
         send(T) -> Stream<T>
     }
 )
 
-pub fn spawn_service<T:Owned,Tb:Owned>(
+pub fn spawn_service<T:Send,Tb:Send>(
             init: extern fn() -> (RecvPacketBuffered<T, Tb>,
                                   SendPacketBuffered<T, Tb>),
             service: ~fn(v: RecvPacketBuffered<T, Tb>))
diff --git a/src/test/run-pass/pipe-sleep.rs b/src/test/run-pass/pipe-sleep.rs
index dc88f36ba11..dbf860cd040 100644
--- a/src/test/run-pass/pipe-sleep.rs
+++ b/src/test/run-pass/pipe-sleep.rs
@@ -33,7 +33,7 @@ endpoint. The send endpoint is returned to the caller and the receive
 endpoint is passed to the new task.
 
 */
-pub fn spawn_service<T:Owned,Tb:Owned>(
+pub fn spawn_service<T:Send,Tb:Send>(
             init: extern fn() -> (RecvPacketBuffered<T, Tb>,
                                   SendPacketBuffered<T, Tb>),
             service: ~fn(v: RecvPacketBuffered<T, Tb>))
diff --git a/src/test/run-pass/send-type-inference.rs b/src/test/run-pass/send-type-inference.rs
index bdb1fbaf422..4fcbc789f57 100644
--- a/src/test/run-pass/send-type-inference.rs
+++ b/src/test/run-pass/send-type-inference.rs
@@ -16,7 +16,7 @@ struct Command<K, V> {
     val: V
 }
 
-fn cache_server<K:Owned,V:Owned>(c: Chan<Chan<Command<K, V>>>) {
+fn cache_server<K:Send,V:Send>(c: Chan<Chan<Command<K, V>>>) {
     let (ctrl_port, ctrl_chan) = stream();
     c.send(ctrl_chan);
 }
diff --git a/src/test/run-pass/shadow.rs b/src/test/run-pass/shadow.rs
index 85575b2ea8b..d0c58b50e2c 100644
--- a/src/test/run-pass/shadow.rs
+++ b/src/test/run-pass/shadow.rs
@@ -19,7 +19,7 @@ fn foo(c: ~[int]) {
             for c.iter().advance |i| {
                 debug!(a);
                 let a = 17;
-                b += ~[a];
+                b.push(a);
             }
         }
         _ => { }
diff --git a/src/test/run-pass/static-impl.rs b/src/test/run-pass/static-impl.rs
index 421cd1d4d0b..0ddc39d6b18 100644
--- a/src/test/run-pass/static-impl.rs
+++ b/src/test/run-pass/static-impl.rs
@@ -51,7 +51,9 @@ impl<T> vec_utils<T> for ~[T] {
     fn iter_(&self, f: &fn(&T)) { for self.iter().advance |x| { f(x); } }
     fn map_<U:Copy>(&self, f: &fn(&T) -> U) -> ~[U] {
         let mut r = ~[];
-        for self.iter().advance |elt| { r += ~[f(elt)]; }
+        for self.iter().advance |elt| {
+            r.push(f(elt));
+        }
         r
     }
 }
diff --git a/src/test/run-pass/str-append.rs b/src/test/run-pass/str-append.rs
index 4fdf7dde031..556247eb426 100644
--- a/src/test/run-pass/str-append.rs
+++ b/src/test/run-pass/str-append.rs
@@ -15,7 +15,7 @@ extern mod extra;
 
 fn test1() {
     let mut s: ~str = ~"hello";
-    s += ~"world";
+    s.push_str("world");
     debug!(s.clone());
     assert_eq!(s[9], 'd' as u8);
 }
diff --git a/src/test/run-pass/str-growth.rs b/src/test/run-pass/str-growth.rs
index 6938b52eee8..0cdf1841331 100644
--- a/src/test/run-pass/str-growth.rs
+++ b/src/test/run-pass/str-growth.rs
@@ -12,11 +12,11 @@
 
 pub fn main() {
     let mut s = ~"a";
-    s += ~"b";
+    s.push_char('b');
     assert_eq!(s[0], 'a' as u8);
     assert_eq!(s[1], 'b' as u8);
-    s += ~"c";
-    s += ~"d";
+    s.push_char('c');
+    s.push_char('d');
     assert_eq!(s[0], 'a' as u8);
     assert_eq!(s[1], 'b' as u8);
     assert_eq!(s[2], 'c' as u8);
diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs
index 5bfbf84d8ac..e0d60d62bb5 100644
--- a/src/test/run-pass/trait-bounds-basic.rs
+++ b/src/test/run-pass/trait-bounds-basic.rs
@@ -14,14 +14,14 @@ trait Foo {
 fn a(_x: ~Foo:) {
 }
 
-fn b(_x: ~Foo:Owned) {
+fn b(_x: ~Foo:Send) {
 }
 
-fn c(x: ~Foo:Const+Owned) {
+fn c(x: ~Foo:Freeze+Send) {
     a(x);
 }
 
-fn d(x: ~Foo:Owned+Copy) {
+fn d(x: ~Foo:Send+Copy) {
     b(x);
 }
 
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
index 585c2185a7e..a3b2ea02db3 100644
--- a/src/test/run-pass/trait-bounds-in-arc.rs
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // Tests that a heterogeneous list of existential types can be put inside an ARC
-// and shared between tasks as long as all types fulfill Const+Owned.
+// and shared between tasks as long as all types fulfill Freeze+Send.
 
 // xfail-fast
 
@@ -64,10 +64,10 @@ fn main() {
     let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: ~"alan_turing" };
     let dogge2 = Dogge { bark_decibels: 55,  tricks_known: 11, name: ~"albert_einstein" };
     let fishe = Goldfyshe { swim_speed: 998, name: ~"alec_guinness" };
-    let arc = arc::ARC(~[~catte  as ~Pet:Const+Owned,
-                         ~dogge1 as ~Pet:Const+Owned,
-                         ~fishe  as ~Pet:Const+Owned,
-                         ~dogge2 as ~Pet:Const+Owned]);
+    let arc = arc::ARC(~[~catte  as ~Pet:Freeze+Send,
+                         ~dogge1 as ~Pet:Freeze+Send,
+                         ~fishe  as ~Pet:Freeze+Send,
+                         ~dogge2 as ~Pet:Freeze+Send]);
     let (p1,c1) = comm::stream();
     let arc1 = cell::Cell::new(arc.clone());
     do task::spawn { check_legs(arc1.take()); c1.send(()); }
@@ -82,21 +82,21 @@ fn main() {
     p3.recv();
 }
 
-fn check_legs(arc: arc::ARC<~[~Pet:Const+Owned]>) {
+fn check_legs(arc: arc::ARC<~[~Pet:Freeze+Send]>) {
     let mut legs = 0;
     for arc.get().iter().advance |pet| {
         legs += pet.num_legs();
     }
     assert!(legs == 12);
 }
-fn check_names(arc: arc::ARC<~[~Pet:Const+Owned]>) {
+fn check_names(arc: arc::ARC<~[~Pet:Freeze+Send]>) {
     for arc.get().iter().advance |pet| {
         do pet.name |name| {
             assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
         }
     }
 }
-fn check_pedigree(arc: arc::ARC<~[~Pet:Const+Owned]>) {
+fn check_pedigree(arc: arc::ARC<~[~Pet:Freeze+Send]>) {
     for arc.get().iter().advance |pet| {
         assert!(pet.of_good_pedigree());
     }
diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs
index e6e5b8605a1..f6c119c4fae 100644
--- a/src/test/run-pass/trait-default-method-xc.rs
+++ b/src/test/run-pass/trait-default-method-xc.rs
@@ -44,12 +44,12 @@ fn main () {
     let a = thing { x: 0 };
     let b = thing { x: 1 };
 
-    assert_eq!(0i.g(), 10);
+    //assert_eq!(0i.g(), 10);
     assert_eq!(a.g(), 10);
     assert_eq!(a.h(), 10);
 
 
-    assert_eq!(0i.thing(3.14, 1), (3.14, 1));
+    //assert_eq!(0i.thing(3.14, 1), (3.14, 1));
 
     assert_eq!(g(0i, 3.14, 1), (3.14, 1));
     assert_eq!(g(false, 3.14, 1), (3.14, 1));
@@ -59,8 +59,8 @@ fn main () {
 
 
     // Trying out a real one
-    assert!(12.test_neq(&10));
-    assert!(!10.test_neq(&10));
+    //assert!(12.test_neq(&10));
+    //assert!(!10.test_neq(&10));
     assert!(a.test_neq(&b));
     assert!(!a.test_neq(&a));
 
diff --git a/src/test/run-pass/trait-generic.rs b/src/test/run-pass/trait-generic.rs
index dc6bdbf5c1a..5952afa6676 100644
--- a/src/test/run-pass/trait-generic.rs
+++ b/src/test/run-pass/trait-generic.rs
@@ -33,7 +33,7 @@ impl<T> map<T> for ~[T] {
         let mut r = ~[];
         // FIXME: #7355 generates bad code with Iterator
         for std::uint::range(0, self.len()) |i| {
-            r += ~[f(&self[i])];
+            r.push(f(&self[i]));
         }
         r
     }
diff --git a/src/test/run-pass/trait-with-bounds-default.rs b/src/test/run-pass/trait-with-bounds-default.rs
new file mode 100644
index 00000000000..b3ddbbb9dc1
--- /dev/null
+++ b/src/test/run-pass/trait-with-bounds-default.rs
@@ -0,0 +1,41 @@
+// 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.
+
+pub trait Clone2 {
+    /// Returns a copy of the value. The contents of owned pointers
+    /// are copied to maintain uniqueness, while the contents of
+    /// managed pointers are not copied.
+    fn clone(&self) -> Self;
+}
+
+#[allow(default_methods)]
+trait Getter<T: Clone> {
+    fn do_get(&self) -> T;
+
+    fn do_get2(&self) -> (T, T) {
+        let x = self.do_get();
+        (x.clone(), x.clone())
+    }
+
+}
+
+impl Getter<int> for int {
+    fn do_get(&self) -> int { *self }
+}
+
+impl<T: Clone> Getter<T> for Option<T> {
+    fn do_get(&self) -> T { self.get_ref().clone() }
+}
+
+
+fn main() {
+    assert_eq!(3.do_get2(), (3, 3));
+    assert_eq!(Some(~"hi").do_get2(), (~"hi", ~"hi"));
+}
diff --git a/src/test/run-pass/type-param-constraints.rs b/src/test/run-pass/type-param-constraints.rs
index 416e7bf82bb..216a7a939fe 100644
--- a/src/test/run-pass/type-param-constraints.rs
+++ b/src/test/run-pass/type-param-constraints.rs
@@ -12,7 +12,7 @@
 
 fn p_foo<T>(pinned: T) { }
 fn s_foo<T:Copy>(shared: T) { }
-fn u_foo<T:Owned>(unique: T) { }
+fn u_foo<T:Send>(unique: T) { }
 
 struct r {
   i: int,
diff --git a/src/test/run-pass/unfoldr-cross-crate.rs b/src/test/run-pass/unfoldr-cross-crate.rs
index 4e98543ae82..7fcae90a8d1 100644
--- a/src/test/run-pass/unfoldr-cross-crate.rs
+++ b/src/test/run-pass/unfoldr-cross-crate.rs
@@ -24,7 +24,7 @@ fn main() {
         }
     }
 
-    let mut it = UnfoldrIterator::new(count, 0);
+    let mut it = UnfoldrIterator::new(0, count);
     let mut i = 0;
     for it.advance |counted| {
         assert_eq!(counted, i);
diff --git a/src/test/run-pass/uniq-cc-generic.rs b/src/test/run-pass/uniq-cc-generic.rs
index b54b3b52692..2c3424d1f06 100644
--- a/src/test/run-pass/uniq-cc-generic.rs
+++ b/src/test/run-pass/uniq-cc-generic.rs
@@ -20,7 +20,7 @@ struct Pointy {
     d : ~fn() -> uint,
 }
 
-fn make_uniq_closure<A:Owned + Copy>(a: A) -> ~fn() -> uint {
+fn make_uniq_closure<A:Send + Copy>(a: A) -> ~fn() -> uint {
     let result: ~fn() -> uint = || ptr::to_unsafe_ptr(&a) as uint;
     result
 }
diff --git a/src/test/run-pass/unique-kinds.rs b/src/test/run-pass/unique-kinds.rs
index b3ce71dcbff..391881deff6 100644
--- a/src/test/run-pass/unique-kinds.rs
+++ b/src/test/run-pass/unique-kinds.rs
@@ -12,11 +12,11 @@ use std::cmp::Eq;
 
 fn sendable() {
 
-    fn f<T:Owned + Eq>(i: T, j: T) {
+    fn f<T:Send + Eq>(i: T, j: T) {
         assert_eq!(i, j);
     }
 
-    fn g<T:Owned + Eq>(i: T, j: T) {
+    fn g<T:Send + Eq>(i: T, j: T) {
         assert!(i != j);
     }
 
diff --git a/src/test/run-pass/vec-growth.rs b/src/test/run-pass/vec-growth.rs
index 816228b62c6..c9a4c57cc9d 100644
--- a/src/test/run-pass/vec-growth.rs
+++ b/src/test/run-pass/vec-growth.rs
@@ -12,10 +12,10 @@
 
 pub fn main() {
     let mut v = ~[1];
-    v += ~[2];
-    v += ~[3];
-    v += ~[4];
-    v += ~[5];
+    v.push(2);
+    v.push(3);
+    v.push(4);
+    v.push(5);
     assert_eq!(v[0], 1);
     assert_eq!(v[1], 2);
     assert_eq!(v[2], 3);
diff --git a/src/test/run-pass/vec-slice.rs b/src/test/run-pass/vec-slice.rs
index 8448e4e0532..e3012b08621 100644
--- a/src/test/run-pass/vec-slice.rs
+++ b/src/test/run-pass/vec-slice.rs
@@ -8,11 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::vec;
-
 pub fn main() {
     let  v = ~[1,2,3,4,5];
-    let v2 = vec::slice(v, 1, 3);
+    let v2 = v.slice(1, 3);
     assert_eq!(v2[0], 2);
     assert_eq!(v2[1], 3);
 }
diff --git a/src/test/run-pass/while-prelude-drop.rs b/src/test/run-pass/while-prelude-drop.rs
index 082f2db259a..503e37fcd76 100644
--- a/src/test/run-pass/while-prelude-drop.rs
+++ b/src/test/run-pass/while-prelude-drop.rs
@@ -17,7 +17,7 @@ fn make(i: int) -> t {
     let mut s = ~"hello";
     // Ensure s is non-const.
 
-    s += ~"there";
+    s.push_str("there");
     return b(s);
 }