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.rs3
-rw-r--r--src/etc/mingw-fix-include/README.txt6
-rw-r--r--src/etc/mingw-fix-include/bits/c++config.h8
-rw-r--r--src/etc/mingw-fix-include/winbase.h8
-rw-r--r--src/etc/mingw-fix-include/winsock2.h12
-rw-r--r--src/libextra/glob.rs39
-rw-r--r--src/libextra/num/bigint.rs142
-rw-r--r--src/libextra/rl.rs21
-rw-r--r--src/libextra/workcache.rs1
-rw-r--r--src/librustc/back/link.rs2
-rw-r--r--src/librustc/front/test.rs116
-rw-r--r--src/librustc/middle/const_eval.rs5
-rw-r--r--src/librustc/middle/trans/base.rs59
-rw-r--r--src/librustc/middle/trans/context.rs2
-rw-r--r--src/librustc/middle/trans/inline.rs8
-rw-r--r--src/librustc/rustc.rs2
-rw-r--r--src/librusti/program.rs2
-rw-r--r--src/librustpkg/api.rs57
-rw-r--r--src/librustpkg/exit_codes.rs11
-rw-r--r--src/librustpkg/package_id.rs6
-rw-r--r--src/librustpkg/package_source.rs62
-rw-r--r--src/librustpkg/rustpkg.rs299
-rw-r--r--src/librustpkg/target.rs41
-rw-r--r--src/librustpkg/tests.rs134
-rw-r--r--src/librustpkg/usage.rs7
-rw-r--r--src/librustpkg/util.rs60
-rw-r--r--src/librustpkg/workcache_support.rs5
-rw-r--r--src/libstd/c_str.rs4
-rw-r--r--src/libstd/libc.rs165
-rw-r--r--src/libstd/logging.rs11
-rw-r--r--src/libstd/num/f32.rs112
-rw-r--r--src/libstd/num/f64.rs112
-rw-r--r--src/libstd/num/float.rs174
-rw-r--r--src/libstd/os.rs25
-rw-r--r--src/libstd/ptr.rs87
-rw-r--r--src/libstd/rand.rs2
-rw-r--r--src/libstd/reflect_stage0.rs493
-rw-r--r--src/libstd/repr_stage0.rs626
-rw-r--r--src/libstd/rt/args.rs12
-rw-r--r--src/libstd/rt/io/buffered.rs4
-rw-r--r--src/libstd/rt/io/file.rs679
-rw-r--r--src/libstd/rt/io/mod.rs59
-rw-r--r--src/libstd/rt/io/pipe.rs76
-rw-r--r--src/libstd/rt/io/process.rs278
-rw-r--r--src/libstd/rt/mod.rs12
-rw-r--r--src/libstd/rt/rc.rs9
-rw-r--r--src/libstd/rt/rtio.rs26
-rw-r--r--src/libstd/rt/task.rs11
-rw-r--r--src/libstd/rt/uv/file.rs582
-rw-r--r--src/libstd/rt/uv/mod.rs12
-rw-r--r--src/libstd/rt/uv/pipe.rs66
-rw-r--r--src/libstd/rt/uv/process.rs219
-rw-r--r--src/libstd/rt/uv/uvio.rs494
-rw-r--r--src/libstd/rt/uv/uvll.rs233
-rw-r--r--src/libstd/run.rs2
-rw-r--r--src/libstd/std.rs6
-rw-r--r--src/libstd/str.rs48
-rw-r--r--src/libstd/sys.rs9
-rw-r--r--src/libstd/unstable/atomics.rs8
-rw-r--r--src/libstd/unstable/intrinsics.rs101
-rw-r--r--src/libstd/unstable/sync.rs17
-rw-r--r--src/libsyntax/ast_util.rs4
-rw-r--r--src/libsyntax/diagnostic.rs2
-rw-r--r--src/libsyntax/ext/build.rs14
-rw-r--r--src/libsyntax/ext/bytes.rs20
-rw-r--r--src/libsyntax/ext/env.rs12
-rw-r--r--src/libsyntax/ext/expand.rs10
-rw-r--r--src/libsyntax/parse/lexer.rs2
-rw-r--r--src/libsyntax/parse/token.rs3
-rw-r--r--src/libsyntax/print/pp.rs2
-rw-r--r--src/libsyntax/print/pprust.rs14
-rw-r--r--src/rt/rust_uv.cpp86
-rw-r--r--src/rt/rustrt.def.in14
-rw-r--r--src/snapshots.txt8
-rw-r--r--src/test/auxiliary/xcrate_address_insignificant.rs19
-rw-r--r--src/test/pretty/path-type-bounds.rs13
-rw-r--r--src/test/run-pass/extern-pass-TwoU64s-ref.rs1
-rw-r--r--src/test/run-pass/extern-pass-TwoU64s.rs1
-rw-r--r--src/test/run-pass/extern-return-TwoU64s.rs2
-rw-r--r--src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs2
-rw-r--r--src/test/run-pass/nul-characters.rs44
-rw-r--r--src/test/run-pass/struct-return.rs2
-rw-r--r--src/test/run-pass/xcrate-address-insignificant.rs18
83 files changed, 3649 insertions, 2536 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index 166638bc359..270b1097c55 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -17,7 +17,6 @@ extern mod extra;
 
 use std::os;
 use std::rt;
-use std::f64;
 
 use extra::getopts;
 use extra::getopts::groups::{optopt, optflag, reqopt};
@@ -131,7 +130,7 @@ pub fn parse_config(args: ~[~str]) -> config {
         ratchet_noise_percent:
             getopts::opt_maybe_str(matches,
                                    "ratchet-noise-percent").map_move(|s|
-                                                                     f64::from_str(s).unwrap()),
+                                                                     from_str::<f64>(s).unwrap()),
         runtool: getopts::opt_maybe_str(matches, "runtool"),
         rustcflags: getopts::opt_maybe_str(matches, "rustcflags"),
         jit: getopts::opt_present(matches, "jit"),
diff --git a/src/etc/mingw-fix-include/README.txt b/src/etc/mingw-fix-include/README.txt
new file mode 100644
index 00000000000..876db17a248
--- /dev/null
+++ b/src/etc/mingw-fix-include/README.txt
@@ -0,0 +1,6 @@
+The purpose of these headers is to fix issues with mingw v4.0, as described in #9246.
+
+This works by adding this directory to GCC include search path before mingw system headers directories, 
+so we can intercept their inclusions and add missing definitions without having to modify files in mingw/include.
+
+Once mingw fixes all 3 issues mentioned in #9246, this directory and all references to it from rust/mk/* may be removed.
diff --git a/src/etc/mingw-fix-include/bits/c++config.h b/src/etc/mingw-fix-include/bits/c++config.h
new file mode 100644
index 00000000000..4520779e275
--- /dev/null
+++ b/src/etc/mingw-fix-include/bits/c++config.h
@@ -0,0 +1,8 @@
+#ifndef _FIX_CXXCONFIG_H
+#define _FIX_CXXCONFIG_H 1
+
+#define _GLIBCXX_HAVE_FENV_H 1
+
+#include_next <bits/c++config.h>
+
+#endif
diff --git a/src/etc/mingw-fix-include/winbase.h b/src/etc/mingw-fix-include/winbase.h
new file mode 100644
index 00000000000..3be26d1cb34
--- /dev/null
+++ b/src/etc/mingw-fix-include/winbase.h
@@ -0,0 +1,8 @@
+#ifndef _FIX_WINBASE_H
+#define _FIX_WINBASE_H 1
+
+#define NTDDK_VERSION NTDDI_VERSION
+
+#include_next <winbase.h>
+
+#endif
diff --git a/src/etc/mingw-fix-include/winsock2.h b/src/etc/mingw-fix-include/winsock2.h
new file mode 100644
index 00000000000..36b58dcd1ee
--- /dev/null
+++ b/src/etc/mingw-fix-include/winsock2.h
@@ -0,0 +1,12 @@
+#ifndef _FIX_WINSOCK2_H
+#define _FIX_WINSOCK2_H 1
+
+#include_next <winsock2.h>
+
+typedef struct pollfd {
+  SOCKET fd;
+  short  events;
+  short  revents;
+} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
+
+#endif
diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs
index 39a4ac61846..43a4ecf5616 100644
--- a/src/libextra/glob.rs
+++ b/src/libextra/glob.rs
@@ -137,16 +137,6 @@ fn list_dir_sorted(path: &Path) -> ~[Path] {
 /**
  * A compiled Unix shell style pattern.
  */
-#[cfg(stage0)]
-#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes)]
-pub struct Pattern {
-    priv tokens: ~[PatternToken]
-}
-
-/**
- * A compiled Unix shell style pattern.
- */
-#[cfg(not(stage0))]
 #[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Default)]
 pub struct Pattern {
     priv tokens: ~[PatternToken]
@@ -465,39 +455,10 @@ fn is_sep(c: char) -> bool {
     }
 }
 
-/**
- * Configuration options to modify the behaviour of `Pattern::matches_with(..)`
- */
-#[cfg(stage0)]
-#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes)]
-pub struct MatchOptions {
-
-    /**
-     * Whether or not patterns should be matched in a case-sensitive manner. This
-     * currently only considers upper/lower case relationships between ASCII characters,
-     * but in future this might be extended to work with Unicode.
-     */
-    case_sensitive: bool,
-
-    /**
-     * If this is true then path-component separator characters (e.g. `/` on Posix)
-     * must be matched by a literal `/`, rather than by `*` or `?` or `[...]`
-     */
-    require_literal_separator: bool,
-
-    /**
-     * If this is true then paths that contain components that start with a `.` will
-     * not match unless the `.` appears literally in the pattern: `*`, `?` or `[...]`
-     * will not match. This is useful because such files are conventionally considered
-     * hidden on Unix systems and it might be desirable to skip them when listing files.
-     */
-    require_literal_leading_dot: bool
-}
 
 /**
  * Configuration options to modify the behaviour of `Pattern::matches_with(..)`
  */
-#[cfg(not(stage0))]
 #[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Default)]
 pub struct MatchOptions {
 
diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs
index 24f44c8a2a8..039694f5881 100644
--- a/src/libextra/num/bigint.rs
+++ b/src/libextra/num/bigint.rs
@@ -697,6 +697,13 @@ impl BigUint {
         }
         return BigUint::new(shifted);
     }
+
+    /// Determines the fewest bits necessary to express the BigUint.
+    pub fn bits(&self) -> uint {
+        if self.is_zero() { return 0; }
+        let zeros = self.data.last().leading_zeros();
+        return self.data.len()*BigDigit::bits - (zeros as uint);
+    }
 }
 
 #[cfg(target_word_size = "64")]
@@ -1115,10 +1122,23 @@ trait RandBigInt {
 
     /// Generate a random BigInt of the given bit size.
     fn gen_bigint(&mut self, bit_size: uint) -> BigInt;
+
+    /// Generate a random BigUint less than the given bound. Fails
+    /// when the bound is zero.
+    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
+
+    /// Generate a random BigUint within the given range. The lower
+    /// bound is inclusive; the upper bound is exclusive. Fails when
+    /// the upper bound is not greater than the lower bound.
+    fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
+
+    /// Generate a random BigInt within the given range. The lower
+    /// bound is inclusive; the upper bound is exclusive. Fails when
+    /// the upper bound is not greater than the lower bound.
+    fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
 }
 
 impl<R: Rng> RandBigInt for R {
-    /// Generate a random BigUint of the given bit size.
     fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
         let (digits, rem) = bit_size.div_rem(&BigDigit::bits);
         let mut data = vec::with_capacity(digits+1);
@@ -1132,7 +1152,6 @@ impl<R: Rng> RandBigInt for R {
         return BigUint::new(data);
     }
 
-    /// Generate a random BigInt of the given bit size.
     fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
         // Generate a random BigUint...
         let biguint = self.gen_biguint(bit_size);
@@ -1154,6 +1173,32 @@ impl<R: Rng> RandBigInt for R {
         };
         return BigInt::from_biguint(sign, biguint);
     }
+
+    fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
+        assert!(!bound.is_zero());
+        let bits = bound.bits();
+        loop {
+            let n = self.gen_biguint(bits);
+            if n < *bound { return n; }
+        }
+    }
+
+    fn gen_biguint_range(&mut self,
+                         lbound: &BigUint,
+                         ubound: &BigUint)
+                         -> BigUint {
+        assert!(*lbound < *ubound);
+        return *lbound + self.gen_biguint_below(&(*ubound - *lbound));
+    }
+
+    fn gen_bigint_range(&mut self,
+                        lbound: &BigInt,
+                        ubound: &BigInt)
+                        -> BigInt {
+        assert!(*lbound < *ubound);
+        let delta = (*ubound - *lbound).to_biguint();
+        return *lbound + self.gen_biguint_below(&delta).to_bigint();
+    }
 }
 
 impl BigInt {
@@ -1781,11 +1826,62 @@ mod biguint_tests {
     }
 
     #[test]
+    fn test_bits() {
+        assert_eq!(BigUint::new(~[0,0,0,0]).bits(), 0);
+        assert_eq!(BigUint::from_uint(0).bits(), 0);
+        assert_eq!(BigUint::from_uint(1).bits(), 1);
+        assert_eq!(BigUint::from_uint(3).bits(), 2);
+        let n: BigUint = FromStrRadix::from_str_radix("4000000000", 16).unwrap();
+        assert_eq!(n.bits(), 39);
+        let one: BigUint = One::one();
+        assert_eq!((one << 426).bits(), 427);
+    }
+
+    #[test]
     fn test_rand() {
         let mut rng = task_rng();
         let _n: BigUint = rng.gen_biguint(137);
         assert!(rng.gen_biguint(0).is_zero());
     }
+
+    #[test]
+    fn test_rand_range() {
+        let mut rng = task_rng();
+
+        do 10.times {
+            assert_eq!(rng.gen_bigint_range(&BigInt::from_uint(236),
+                                            &BigInt::from_uint(237)),
+                       BigInt::from_uint(236));
+        }
+
+        let l = BigUint::from_uint(403469000 + 2352);
+        let u = BigUint::from_uint(403469000 + 3513);
+        do 1000.times {
+            let n: BigUint = rng.gen_biguint_below(&u);
+            assert!(n < u);
+
+            let n: BigUint = rng.gen_biguint_range(&l, &u);
+            assert!(n >= l);
+            assert!(n < u);
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_zero_rand_range() {
+        task_rng().gen_biguint_range(&BigUint::from_uint(54),
+                                     &BigUint::from_uint(54));
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_negative_rand_range() {
+        let mut rng = task_rng();
+        let l = BigUint::from_uint(2352);
+        let u = BigUint::from_uint(3513);
+        // Switching u and l should fail:
+        let _n: BigUint = rng.gen_biguint_range(&u, &l);
+    }
 }
 
 #[cfg(test)]
@@ -2237,6 +2333,48 @@ mod bigint_tests {
         let _n: BigInt = rng.gen_bigint(137);
         assert!(rng.gen_bigint(0).is_zero());
     }
+
+    #[test]
+    fn test_rand_range() {
+        let mut rng = task_rng();
+
+        do 10.times {
+            assert_eq!(rng.gen_bigint_range(&BigInt::from_uint(236),
+                                            &BigInt::from_uint(237)),
+                       BigInt::from_uint(236));
+        }
+
+        fn check(l: BigInt, u: BigInt) {
+            let mut rng = task_rng();
+            do 1000.times {
+                let n: BigInt = rng.gen_bigint_range(&l, &u);
+                assert!(n >= l);
+                assert!(n < u);
+            }
+        }
+        let l = BigInt::from_uint(403469000 + 2352);
+        let u = BigInt::from_uint(403469000 + 3513);
+        check( l.clone(),  u.clone());
+        check(-l.clone(),  u.clone());
+        check(-u.clone(), -l.clone());
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_zero_rand_range() {
+        task_rng().gen_bigint_range(&IntConvertible::from_int(54),
+                                    &IntConvertible::from_int(54));
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_negative_rand_range() {
+        let mut rng = task_rng();
+        let l = BigInt::from_uint(2352);
+        let u = BigInt::from_uint(3513);
+        // Switching u and l should fail:
+        let _n: BigInt = rng.gen_bigint_range(&u, &l);
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs
index 74b7aea9978..9476bcb8926 100644
--- a/src/libextra/rl.rs
+++ b/src/libextra/rl.rs
@@ -13,25 +13,6 @@ use std::libc::{c_char, c_int};
 use std::{local_data, str, rt};
 use std::unstable::finally::Finally;
 
-#[cfg(stage0)]
-pub mod rustrt {
-    use std::libc::{c_char, c_int};
-
-    extern {
-        fn linenoise(prompt: *c_char) -> *c_char;
-        fn linenoiseHistoryAdd(line: *c_char) -> c_int;
-        fn linenoiseHistorySetMaxLen(len: c_int) -> c_int;
-        fn linenoiseHistorySave(file: *c_char) -> c_int;
-        fn linenoiseHistoryLoad(file: *c_char) -> c_int;
-        fn linenoiseSetCompletionCallback(callback: *u8);
-        fn linenoiseAddCompletion(completions: *(), line: *c_char);
-
-        fn rust_take_linenoise_lock();
-        fn rust_drop_linenoise_lock();
-    }
-}
-
-#[cfg(not(stage0))]
 pub mod rustrt {
     use std::libc::{c_char, c_int};
 
@@ -109,7 +90,7 @@ pub fn read(prompt: &str) -> Option<~str> {
 
 pub type CompletionCb = @fn(~str, @fn(~str));
 
-static complete_key: local_data::Key<CompletionCb> = &local_data::Key;
+local_data_key!(complete_key: CompletionCb)
 
 /// Bind to the main completion callback in the current task.
 ///
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index 4d3b5ae035e..24ab8360e8f 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -198,7 +198,6 @@ impl Database {
     }
 }
 
-// FIXME #4330: use &mut self here
 #[unsafe_destructor]
 impl Drop for Database {
     fn drop(&mut self) {
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 1fbbc1db05a..ee7fbed9e9f 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -190,7 +190,7 @@ pub mod jit {
 
     // The stage1 compiler won't work, but that doesn't really matter. TLS
     // changed only very recently to allow storage of owned values.
-    static engine_key: local_data::Key<~Engine> = &local_data::Key;
+    local_data_key!(engine_key: ~Engine)
 
     fn set_engine(engine: ~Engine) {
         local_data::set(engine_key, engine)
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 9c788065133..49176c7bc17 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -293,50 +293,6 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
     }
 }
 
-#[cfg(stage0)]
-fn mk_test_module(cx: &TestCtxt) -> @ast::item {
-
-    // Link to extra
-    let view_items = ~[mk_std(cx)];
-
-    // A constant vector of test descriptors.
-    let tests = mk_tests(cx);
-
-    // The synthesized main function which will call the console test runner
-    // with our list of tests
-    let ext_cx = cx.ext_cx;
-    let mainfn = (quote_item!(
-        pub fn main() {
-            #[main];
-            extra::test::test_main_static(::std::os::args(), TESTS);
-        }
-    )).unwrap();
-
-    let testmod = ast::_mod {
-        view_items: view_items,
-        items: ~[mainfn, tests],
-    };
-    let item_ = ast::item_mod(testmod);
-
-    // This attribute tells resolve to let us call unexported functions
-    let resolve_unexported_attr =
-        attr::mk_attr(attr::mk_word_item(@"!resolve_unexported"));
-
-    let item = ast::item {
-        ident: cx.sess.ident_of("__test"),
-        attrs: ~[resolve_unexported_attr],
-        id: ast::DUMMY_NODE_ID,
-        node: item_,
-        vis: ast::public,
-        span: dummy_sp(),
-     };
-
-    debug!("Synthetic test module:\n%s\n",
-           pprust::item_to_str(@item.clone(), cx.sess.intr()));
-
-    return @item;
-}
-#[cfg(not(stage0))]
 fn mk_test_module(cx: &TestCtxt) -> @ast::item {
 
     // Link to extra
@@ -407,21 +363,6 @@ fn path_node_global(ids: ~[ast::Ident]) -> ast::Path {
     }
 }
 
-#[cfg(stage0)]
-fn mk_tests(cx: &TestCtxt) -> @ast::item {
-
-    let ext_cx = cx.ext_cx;
-
-    // The vector of test_descs for this crate
-    let test_descs = mk_test_descs(cx);
-
-    (quote_item!(
-        pub static TESTS : &'static [self::extra::test::TestDescAndFn] =
-            $test_descs
-        ;
-    )).unwrap()
-}
-#[cfg(not(stage0))]
 fn mk_tests(cx: &TestCtxt) -> @ast::item {
     // The vector of test_descs for this crate
     let test_descs = mk_test_descs(cx);
@@ -461,63 +402,6 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::Expr {
     }
 }
 
-#[cfg(stage0)]
-fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
-    let span = test.span;
-    let path = test.path.clone();
-
-    let ext_cx = cx.ext_cx;
-
-    debug!("encoding %s", ast_util::path_name_i(path));
-
-    let name_lit: ast::lit =
-        nospan(ast::lit_str(ast_util::path_name_i(path).to_managed()));
-
-    let name_expr = @ast::Expr {
-          id: ast::DUMMY_NODE_ID,
-          node: ast::ExprLit(@name_lit),
-          span: span
-    };
-
-    let fn_path = path_node_global(path);
-
-    let fn_expr = @ast::Expr {
-        id: ast::DUMMY_NODE_ID,
-        node: ast::ExprPath(fn_path),
-        span: span,
-    };
-
-    let t_expr = if test.bench {
-        quote_expr!( self::extra::test::StaticBenchFn($fn_expr) )
-    } else {
-        quote_expr!( self::extra::test::StaticTestFn($fn_expr) )
-    };
-
-    let ignore_expr = if test.ignore {
-        quote_expr!( true )
-    } else {
-        quote_expr!( false )
-    };
-
-    let fail_expr = if test.should_fail {
-        quote_expr!( true )
-    } else {
-        quote_expr!( false )
-    };
-
-    let e = quote_expr!(
-        self::extra::test::TestDescAndFn {
-            desc: self::extra::test::TestDesc {
-                name: self::extra::test::StaticTestName($name_expr),
-                ignore: $ignore_expr,
-                should_fail: $fail_expr
-            },
-            testfn: $t_expr,
-        }
-    );
-    e
-}
-#[cfg(not(stage0))]
 fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
     let span = test.span;
     let path = test.path.clone();
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 2e5e87f225a..bba3ca9f212 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -19,7 +19,6 @@ use syntax::visit;
 use syntax::visit::Visitor;
 use syntax::ast::*;
 
-use std::float;
 use std::hashmap::{HashMap, HashSet};
 
 //
@@ -476,9 +475,9 @@ pub fn lit_to_const(lit: &lit) -> const_val {
       lit_int(n, _) => const_int(n),
       lit_uint(n, _) => const_uint(n),
       lit_int_unsuffixed(n) => const_int(n),
-      lit_float(n, _) => const_float(float::from_str(n).unwrap() as f64),
+      lit_float(n, _) => const_float(from_str::<float>(n).unwrap() as f64),
       lit_float_unsuffixed(n) =>
-        const_float(float::from_str(n).unwrap() as f64),
+        const_float(from_str::<float>(n).unwrap() as f64),
       lit_nil => const_int(0i64),
       lit_bool(b) => const_bool(b)
     }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index b4979c335b5..f7fcd8f908d 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -92,7 +92,7 @@ use syntax::visit::Visitor;
 
 pub use middle::trans::context::task_llcx;
 
-static task_local_insn_key: local_data::Key<@~[&'static str]> = &local_data::Key;
+local_data_key!(task_local_insn_key: @~[&'static str])
 
 pub fn with_insn_ctxt(blk: &fn(&[&'static str])) {
     let opt = local_data::get(task_local_insn_key, |k| k.map_move(|k| *k));
@@ -2388,38 +2388,12 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
     let et = ccx.sess.entry_type.unwrap();
     match et {
         session::EntryMain => {
-            let llfn = create_main(ccx, main_llfn);
-            create_entry_fn(ccx, llfn, true);
+            create_entry_fn(ccx, main_llfn, true);
         }
         session::EntryStart => create_entry_fn(ccx, main_llfn, false),
         session::EntryNone => {}    // Do nothing.
     }
 
-    fn create_main(ccx: @mut CrateContext, main_llfn: ValueRef) -> ValueRef {
-        let nt = ty::mk_nil();
-        let llfty = type_of_rust_fn(ccx, [], nt);
-        let llfdecl = decl_fn(ccx.llmod, "_rust_main",
-                              lib::llvm::CCallConv, llfty);
-
-        let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None);
-
-        // the args vector built in create_entry_fn will need
-        // be updated if this assertion starts to fail.
-        assert!(!fcx.caller_expects_out_pointer);
-
-        let bcx = fcx.entry_bcx.unwrap();
-        // Call main.
-        let llenvarg = unsafe {
-            let env_arg = fcx.env_arg_pos();
-            llvm::LLVMGetParam(llfdecl, env_arg as c_uint)
-        };
-        let args = ~[llenvarg];
-        Call(bcx, main_llfn, args, []);
-
-        finish_fn(fcx, bcx);
-        return llfdecl;
-    }
-
     fn create_entry_fn(ccx: @mut CrateContext,
                        rust_main: ValueRef,
                        use_start_lang_item: bool) {
@@ -2559,10 +2533,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
                             // LLVM type is not fully determined by the Rust type.
                             let (v, inlineable) = consts::const_expr(ccx, expr);
                             ccx.const_values.insert(id, v);
-                            if !inlineable {
-                                debug!("%s not inlined", sym);
-                                ccx.non_inlineable_statics.insert(id);
-                            }
+                            let mut inlineable = inlineable;
                             exprt = true;
 
                             unsafe {
@@ -2578,8 +2549,30 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
                                     lib::llvm::SetUnnamedAddr(g, true);
                                     lib::llvm::SetLinkage(g,
                                         lib::llvm::InternalLinkage);
+
+                                    // This is a curious case where we must make
+                                    // all of these statics inlineable. If a
+                                    // global is tagged as
+                                    // address_insignificant, then LLVM won't
+                                    // coalesce globals unless they have an
+                                    // internal linkage type. This means that
+                                    // external crates cannot use this global.
+                                    // This is a problem for things like inner
+                                    // statics in generic functions, because the
+                                    // function will be inlined into another
+                                    // crate and then attempt to link to the
+                                    // static in the original crate, only to
+                                    // find that it's not there. On the other
+                                    // side of inlininig, the crates knows to
+                                    // not declare this static as
+                                    // available_externally (because it isn't)
+                                    inlineable = true;
                                 }
 
+                                if !inlineable {
+                                    debug!("%s not inlined", sym);
+                                    ccx.non_inlineable_statics.insert(id);
+                                }
                                 ccx.item_symbols.insert(i.id, sym);
                                 g
                             }
@@ -2641,7 +2634,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef {
                             foreign::register_foreign_item_fn(ccx, abis, &path, ni)
                         }
                         ast::foreign_item_static(*) => {
-                            let ident = token::ident_to_str(&ni.ident);
+                            let ident = foreign::link_name(ccx, ni);
                             let g = do ident.with_c_str |buf| {
                                 unsafe {
                                     let ty = type_of(ccx, ty);
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index 7e1c2c369b1..e342bcaf4fa 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -287,7 +287,7 @@ impl Drop for CrateContext {
     }
 }
 
-static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
+local_data_key!(task_local_llcx_key: @ContextRef)
 
 pub fn task_llcx() -> ContextRef {
     let opt = local_data::get(task_local_llcx_key, |k| k.map_move(|k| *k));
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index a571e56a48e..8900b50b49d 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -21,6 +21,7 @@ use std::vec;
 use syntax::ast;
 use syntax::ast_map::path_name;
 use syntax::ast_util::local_def;
+use syntax::attr;
 
 pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId)
     -> ast::DefId {
@@ -68,7 +69,12 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId)
             match item.node {
                 ast::item_static(*) => {
                     let g = get_item_val(ccx, item.id);
-                    SetLinkage(g, AvailableExternallyLinkage);
+                    // see the comment in get_item_val() as to why this check is
+                    // performed here.
+                    if !attr::contains_name(item.attrs,
+                                            "address_insignificant") {
+                        SetLinkage(g, AvailableExternallyLinkage);
+                    }
                 }
                 _ => {}
             }
diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs
index bca2ceb2f84..902734b05a2 100644
--- a/src/librustc/rustc.rs
+++ b/src/librustc/rustc.rs
@@ -134,7 +134,7 @@ pub fn version(argv0: &str) {
 
 pub fn usage(argv0: &str) {
     let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
-    printfln!("%s\
+    printfln!("%s\n\
 Additional help:
     -W help             Print 'lint' options and default settings
     -Z help             Print internal options for debugging rustc\n",
diff --git a/src/librusti/program.rs b/src/librusti/program.rs
index 9208191e364..4deaa458f19 100644
--- a/src/librusti/program.rs
+++ b/src/librusti/program.rs
@@ -60,7 +60,7 @@ struct LocalVariable {
 }
 
 type LocalCache = @mut HashMap<~str, @~[u8]>;
-static tls_key: local_data::Key<LocalCache> = &local_data::Key;
+local_data_key!(tls_key: LocalCache)
 
 impl Program {
     pub fn new() -> Program {
diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs
index 727bbcb30b4..e1092458ffa 100644
--- a/src/librustpkg/api.rs
+++ b/src/librustpkg/api.rs
@@ -12,6 +12,7 @@ use context::*;
 use crate::*;
 use package_id::*;
 use package_source::*;
+use target::*;
 use version::Version;
 use workcache_support::*;
 
@@ -63,56 +64,40 @@ pub fn new_workcache_context(p: &Path) -> workcache::Context {
 pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
                  lib: Path) {
     let cx = default_context(sysroot);
-    let subroot = root.clone();
-    let subversion = version.clone();
-    let sublib = lib.clone();
-    do cx.workcache_context.with_prep(name) |prep| {
-        let pkg_src = PkgSrc {
-            workspace: subroot.clone(),
-            start_dir: subroot.push("src").push(name),
-            id: PkgId{ version: subversion.clone(), ..PkgId::new(name)},
-            libs: ~[mk_crate(sublib.clone())],
+    let pkg_src = PkgSrc {
+            workspace: root.clone(),
+            start_dir: root.push("src").push(name),
+            id: PkgId{ version: version, ..PkgId::new(name)},
+            // n.b. This assumes the package only has one crate
+            libs: ~[mk_crate(lib)],
             mains: ~[],
             tests: ~[],
             benchs: ~[]
         };
-        pkg_src.declare_inputs(prep);
-        let subcx = cx.clone();
-        let subsrc = pkg_src.clone();
-        do prep.exec |exec| {
-            subsrc.build(exec, &subcx.clone(), ~[]);
-        }
-    };
+    pkg_src.build(&cx, ~[]);
 }
 
 pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
                  main: Path) {
     let cx = default_context(sysroot);
-    let subroot = root.clone();
-    let submain = main.clone();
-    do cx.workcache_context.with_prep(name) |prep| {
-        let pkg_src = PkgSrc {
-            workspace: subroot.clone(),
-            start_dir: subroot.push("src").push(name),
-            id: PkgId{ version: version.clone(), ..PkgId::new(name)},
-            libs: ~[],
-            mains: ~[mk_crate(submain.clone())],
-            tests: ~[],
-            benchs: ~[]
-        };
-        pkg_src.declare_inputs(prep);
-        let subsrc = pkg_src.clone();
-        let subcx = cx.clone();
-        do prep.exec |exec| {
-            subsrc.clone().build(exec, &subcx.clone(), ~[]);
-        }
-    }
+    let pkg_src = PkgSrc {
+        workspace: root.clone(),
+        start_dir: root.push("src").push(name),
+        id: PkgId{ version: version, ..PkgId::new(name)},
+        libs: ~[],
+        // n.b. This assumes the package only has one crate
+        mains: ~[mk_crate(main)],
+        tests: ~[],
+        benchs: ~[]
+    };
+
+    pkg_src.build(&cx, ~[]);
 }
 
 pub fn install_pkg(sysroot: Path, workspace: Path, name: ~str, version: Version) {
     let cx = default_context(sysroot);
     let pkgid = PkgId{ version: version, ..PkgId::new(name)};
-    cx.install(PkgSrc::new(workspace, false, pkgid));
+    cx.install(PkgSrc::new(workspace, false, pkgid), &Everything);
 }
 
 fn mk_crate(p: Path) -> Crate {
diff --git a/src/librustpkg/exit_codes.rs b/src/librustpkg/exit_codes.rs
new file mode 100644
index 00000000000..484f6bdcaec
--- /dev/null
+++ b/src/librustpkg/exit_codes.rs
@@ -0,0 +1,11 @@
+// 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 static copy_failed_code: int = 65;
diff --git a/src/librustpkg/package_id.rs b/src/librustpkg/package_id.rs
index bc2fcdd7fe9..52b986cb6e7 100644
--- a/src/librustpkg/package_id.rs
+++ b/src/librustpkg/package_id.rs
@@ -108,6 +108,12 @@ impl PkgId {
         }
     }
 
+    // This is the workcache function name for the *installed*
+    // binaries for this package (as opposed to the built ones,
+    // which are per-crate).
+    pub fn install_tag(&self) -> ~str {
+        fmt!("install(%s)", self.to_str())
+    }
 }
 
 struct Prefixes {
diff --git a/src/librustpkg/package_source.rs b/src/librustpkg/package_source.rs
index b5ded6f3faf..4bf647b011d 100644
--- a/src/librustpkg/package_source.rs
+++ b/src/librustpkg/package_source.rs
@@ -22,6 +22,7 @@ use path_util::{find_dir_using_rust_path_hack, default_workspace, make_dir_rwx_r
 use util::compile_crate;
 use workspace::is_workspace;
 use workcache_support;
+use workcache_support::crate_tag;
 use extra::workcache;
 
 // An enumeration of the unpacked source of a package workspace.
@@ -231,7 +232,7 @@ impl PkgSrc {
         p.filestem().map_default(false, |p| { p == &self.id.short_name.as_slice() })
     }
 
-    fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
+    pub fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
         assert!(p.components.len() > prefix);
         let mut sub = Path("");
         for c in p.components.slice(prefix, p.components.len()).iter() {
@@ -286,7 +287,6 @@ impl PkgSrc {
 
     fn build_crates(&self,
                     ctx: &BuildContext,
-                    exec: &mut workcache::Exec,
                     destination_dir: &Path,
                     crates: &[Crate],
                     cfgs: &[~str],
@@ -297,25 +297,40 @@ impl PkgSrc {
             let path_str = path.to_str();
             let cfgs = crate.cfgs + cfgs;
 
-            let result =
-                // compile_crate should return the path of the output artifact
-                compile_crate(ctx,
-                              exec,
-                              &self.id,
-                              &path,
-                              destination_dir,
-                              crate.flags,
-                              cfgs,
-                              false,
-                              what).to_str();
-            debug!("Result of compiling %s was %s", path_str, result);
+            do ctx.workcache_context.with_prep(crate_tag(&path)) |prep| {
+                debug!("Building crate %s, declaring it as an input", path.to_str());
+                prep.declare_input("file", path.to_str(),
+                                   workcache_support::digest_file_with_date(&path));
+                let subpath = path.clone();
+                let subcfgs = cfgs.clone();
+                let subpath_str = path_str.clone();
+                let subcx = ctx.clone();
+                let id = self.id.clone();
+                let sub_dir = destination_dir.clone();
+                let sub_flags = crate.flags.clone();
+                do prep.exec |exec| {
+                    let result = compile_crate(&subcx,
+                                               exec,
+                                               &id,
+                                               &subpath,
+                                               &sub_dir,
+                                               sub_flags,
+                                               subcfgs,
+                                               false,
+                                               what).to_str();
+                    debug!("Result of compiling %s was %s", subpath_str, result);
+                    result
+                }
+            };
         }
     }
 
     /// Declare all the crate files in the package source as inputs
+    /// (to the package)
     pub fn declare_inputs(&self, prep: &mut workcache::Prep) {
         let to_do = ~[self.libs.clone(), self.mains.clone(),
                       self.tests.clone(), self.benchs.clone()];
+        debug!("In declare inputs, self = %s", self.to_str());
         for cs in to_do.iter() {
             for c in cs.iter() {
                 let path = self.start_dir.push_rel(&c.file).normalize();
@@ -330,7 +345,6 @@ impl PkgSrc {
     // It would be better if build returned a Path, but then Path would have to derive
     // Encodable.
     pub fn build(&self,
-                 exec: &mut workcache::Exec,
                  build_context: &BuildContext,
                  cfgs: ~[~str]) -> ~str {
         use conditions::not_a_workspace::cond;
@@ -360,13 +374,23 @@ impl PkgSrc {
         let benchs = self.benchs.clone();
         debug!("Building libs in %s, destination = %s",
                destination_workspace.to_str(), destination_workspace.to_str());
-        self.build_crates(build_context, exec, &destination_workspace, libs, cfgs, Lib);
+        self.build_crates(build_context, &destination_workspace, libs, cfgs, Lib);
         debug!("Building mains");
-        self.build_crates(build_context, exec, &destination_workspace, mains, cfgs, Main);
+        self.build_crates(build_context, &destination_workspace, mains, cfgs, Main);
         debug!("Building tests");
-        self.build_crates(build_context, exec, &destination_workspace, tests, cfgs, Test);
+        self.build_crates(build_context, &destination_workspace, tests, cfgs, Test);
         debug!("Building benches");
-        self.build_crates(build_context, exec, &destination_workspace, benchs, cfgs, Bench);
+        self.build_crates(build_context, &destination_workspace, benchs, cfgs, Bench);
         destination_workspace.to_str()
     }
+
+    /// Debugging
+    pub fn dump_crates(&self) {
+        let crate_sets = [&self.libs, &self.mains, &self.tests, &self.benchs];
+        for crate_set in crate_sets.iter() {
+            for c in crate_set.iter() {
+                debug!("Built crate: %s", c.file.to_str())
+            }
+        }
+    }
 }
diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs
index eef1dcabfd0..7cd30c7af9e 100644
--- a/src/librustpkg/rustpkg.rs
+++ b/src/librustpkg/rustpkg.rs
@@ -22,11 +22,10 @@ extern mod extra;
 extern mod rustc;
 extern mod syntax;
 
-use std::{io, os, result, run, str};
+use std::{io, os, result, run, str, task};
 pub use std::path::Path;
 
 use extra::workcache;
-use extra::arc::RWArc;
 use rustc::driver::{driver, session};
 use rustc::metadata::filesearch;
 use rustc::metadata::filesearch::rust_path;
@@ -45,12 +44,16 @@ use context::{Context, BuildContext,
                        LLVMAssemble, LLVMCompileBitcode};
 use package_id::PkgId;
 use package_source::PkgSrc;
-use workcache_support::{discover_outputs, digest_only_date};
+use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
+// use workcache_support::{discover_outputs, digest_only_date};
+use workcache_support::digest_only_date;
+use exit_codes::copy_failed_code;
 
 pub mod api;
 mod conditions;
 mod context;
 mod crate;
+mod exit_codes;
 mod installed_packages;
 mod messages;
 mod package_id;
@@ -172,40 +175,26 @@ impl<'self> PkgScript<'self> {
 pub trait CtxMethods {
     fn run(&self, cmd: &str, args: ~[~str]);
     fn do_cmd(&self, _cmd: &str, _pkgname: &str);
-    fn build_from_src(&self, pkg_src: PkgSrc);
     /// Returns the destination workspace
-    fn build(&self, exec: &mut workcache::Exec, pkg_src: PkgSrc) -> Path;
+    fn build(&self, pkg_src: &mut PkgSrc, what: &WhatToBuild) -> Path;
     fn clean(&self, workspace: &Path, id: &PkgId);
     fn info(&self);
     /// Returns a pair. First component is a list of installed paths,
     /// second is a list of declared and discovered inputs
-    fn install(&self, src: PkgSrc) -> (~[Path], ~[(~str, ~str)]);
+    fn install(&self, src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]);
     /// Returns a list of installed files
     fn install_no_build(&self,
                         source_workspace: &Path,
                         target_workspace: &Path,
-                        id: &PkgId) -> ~[Path];
+                        id: &PkgId) -> ~[~str];
     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>);
+    fn init(&self);
 }
 
 impl CtxMethods for BuildContext {
-    fn build_from_src(&self, pkg_src: PkgSrc) {
-        let tag = pkg_src.id.to_str();
-        debug!("package source = %s", pkg_src.to_str());
-        do self.workcache_context.with_prep(tag) |prep| {
-            let subsrc = pkg_src.clone();
-            let subself = self.clone();
-            declare_package_script_dependency(prep, &subsrc);
-            pkg_src.declare_inputs(prep);
-            do prep.exec |exec| {
-                subself.build(exec, subsrc.clone());
-            }
-        }
-    }
-
     fn run(&self, cmd: &str, args: ~[~str]) {
         match cmd {
             "build" => {
@@ -214,11 +203,13 @@ impl CtxMethods for BuildContext {
                         None if self.context.use_rust_path_hack => {
                             let cwd = os::getcwd();
                             let pkgid = PkgId::new(cwd.components[cwd.components.len() - 1]);
-                            self.build_from_src(PkgSrc::new(cwd, true, pkgid));
+                            let mut pkg_src = PkgSrc::new(cwd, true, pkgid);
+                            self.build(&mut pkg_src, &Everything);
                         }
                         None => { usage::build(); return; }
                         Some((ws, pkgid)) => {
-                            self.build_from_src(PkgSrc::new(ws, false, pkgid));
+                            let mut pkg_src = PkgSrc::new(ws, false, pkgid);
+                            self.build(&mut pkg_src, &Everything);
                         }
                     }
                 }
@@ -229,8 +220,8 @@ impl CtxMethods for BuildContext {
                     do each_pkg_parent_workspace(&self.context, &pkgid) |workspace| {
                         debug!("found pkg %s in workspace %s, trying to build",
                                pkgid.to_str(), workspace.to_str());
-                        let pkg_src = PkgSrc::new(workspace.clone(), false, pkgid.clone());
-                        self.build_from_src(pkg_src);
+                        let mut pkg_src = PkgSrc::new(workspace.clone(), false, pkgid.clone());
+                        self.build(&mut pkg_src, &Everything);
                         true
                     };
                 }
@@ -270,12 +261,12 @@ impl CtxMethods for BuildContext {
                             let cwd = os::getcwd();
                             let inferred_pkgid =
                                 PkgId::new(cwd.components[cwd.components.len() - 1]);
-                            self.install(PkgSrc::new(cwd, true, inferred_pkgid));
+                            self.install(PkgSrc::new(cwd, true, inferred_pkgid), &Everything);
                         }
                         None  => { usage::install(); return; }
                         Some((ws, pkgid))                => {
                             let pkg_src = PkgSrc::new(ws, false, pkgid);
-                            self.install(pkg_src);
+                            self.install(pkg_src, &Everything);
                       }
                   }
                 }
@@ -290,14 +281,14 @@ impl CtxMethods for BuildContext {
                         let rp = rust_path();
                         assert!(!rp.is_empty());
                         let src = PkgSrc::new(rp[0].clone(), false, pkgid.clone());
-                        self.install(src);
+                        self.install(src, &Everything);
                     }
                     else {
                         for workspace in workspaces.iter() {
                             let src = PkgSrc::new(workspace.clone(),
                                                   self.context.use_rust_path_hack,
                                                   pkgid.clone());
-                            self.install(src);
+                            self.install(src, &Everything);
                         };
                     }
                 }
@@ -319,6 +310,13 @@ impl CtxMethods for BuildContext {
             "test" => {
                 self.test();
             }
+            "init" => {
+                if args.len() != 0 {
+                    return usage::init();
+                } else {
+                    self.init();
+                }
+            }
             "uninstall" => {
                 if args.len() < 1 {
                     return usage::uninstall();
@@ -358,7 +356,9 @@ impl CtxMethods for BuildContext {
 
     /// Returns the destination workspace
     /// In the case of a custom build, we don't know, so we just return the source workspace
-    fn build(&self, exec: &mut workcache::Exec, mut pkg_src: PkgSrc) -> Path {
+    /// what_to_build says: "Just build the lib.rs file in one subdirectory,
+    /// don't walk anything recursively." Or else, everything.
+    fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) -> Path {
         let workspace = pkg_src.workspace.clone();
         let pkgid = pkg_src.id.clone();
 
@@ -376,7 +376,7 @@ impl CtxMethods for BuildContext {
             let default_ws = default_workspace();
             debug!("Calling build recursively with %? and %?", default_ws.to_str(),
                    pkgid.to_str());
-            return self.build(exec, PkgSrc::new(default_ws, false, pkgid.clone()));
+            return self.build(&mut PkgSrc::new(default_ws, false, pkgid.clone()), what_to_build);
         }
 
         // Is there custom build logic? If so, use it
@@ -387,12 +387,21 @@ impl CtxMethods for BuildContext {
         let cfgs = match pkg_src.package_script_option() {
             Some(package_script_path) => {
                 let sysroot = self.sysroot_to_use();
-                let (cfgs, hook_result) = {
-                    let pscript = PkgScript::parse(@sysroot.clone(),
-                                                   package_script_path.clone(),
-                                                   &workspace.clone(),
-                                                   &pkgid);
-                    pscript.run_custom(exec, &sysroot)
+                let (cfgs, hook_result) =
+                    do self.workcache_context.with_prep(package_script_path.to_str()) |prep| {
+                    let sub_sysroot = sysroot.clone();
+                    let package_script_path_clone = package_script_path.clone();
+                    let sub_ws = workspace.clone();
+                    let sub_id = pkgid.clone();
+                    declare_package_script_dependency(prep, &*pkg_src);
+                    do prep.exec |exec| {
+                        let pscript = PkgScript::parse(@sub_sysroot.clone(),
+                                                       package_script_path_clone.clone(),
+                                                       &sub_ws,
+                                                       &sub_id);
+
+                        pscript.run_custom(exec, &sub_sysroot)
+                    }
                 };
                 debug!("Command return code = %?", hook_result);
                 if hook_result != 0 {
@@ -411,10 +420,31 @@ impl CtxMethods for BuildContext {
         // If there was a package script, it should have finished
         // the build already. Otherwise...
         if !custom {
-            // Find crates inside the workspace
-            pkg_src.find_crates();
+            match what_to_build {
+                // Find crates inside the workspace
+                &Everything => pkg_src.find_crates(),
+                // Don't infer any crates -- just build the one that was requested
+                &JustOne(ref p) => {
+                    // We expect that p is relative to the package source's start directory,
+                    // so check that assumption
+                    debug!("JustOne: p = %s", p.to_str());
+                    assert!(os::path_exists(&pkg_src.start_dir.push_rel(p)));
+                    if is_lib(p) {
+                        PkgSrc::push_crate(&mut pkg_src.libs, 0, p);
+                    } else if is_main(p) {
+                        PkgSrc::push_crate(&mut pkg_src.mains, 0, p);
+                    } else if is_test(p) {
+                        PkgSrc::push_crate(&mut pkg_src.tests, 0, p);
+                    } else if is_bench(p) {
+                        PkgSrc::push_crate(&mut pkg_src.benchs, 0, p);
+                    } else {
+                        warn(fmt!("Not building any crates for dependency %s", p.to_str()));
+                        return workspace.clone();
+                    }
+                }
+            }
             // Build it!
-            let rs_path = pkg_src.build(exec, self, cfgs);
+            let rs_path = pkg_src.build(self, cfgs);
             Path(rs_path)
         }
         else {
@@ -444,56 +474,54 @@ impl CtxMethods for BuildContext {
         fail!("info not yet implemented");
     }
 
-    fn install(&self, pkg_src: PkgSrc) -> (~[Path], ~[(~str, ~str)]) {
-
-        let id = &pkg_src.id;
-
-        let installed_files = RWArc::new(~[]);
-        let inputs = RWArc::new(~[]);
-        // FIXME #7402: Use RUST_PATH to determine target dir
-        self.workcache_context.with_prep(id.to_str(), |p| pkg_src.declare_inputs(p));
-        do self.workcache_context.with_prep(id.to_str()) |prep| {
-            let sub_inputs = inputs.clone();
-            let sub_files  = installed_files.clone();
-            let subsrc = pkg_src.clone();
-            let subself = self.clone();
-            let id_str = id.to_str();
-            let sub_id = id.clone();
-            sub_inputs.write(|r| *r = prep.lookup_declared_inputs().map(|v|
-                                          { (~"file", (*v).clone()) }));
-            do prep.exec |exec| {
-                let destination_workspace = subself.build(exec, subsrc.clone()).to_str();
-                // See #7402: This still isn't quite right yet; we want to
-                // install to the first workspace in the RUST_PATH if there's
-                // a non-default RUST_PATH. This code installs to the same
-                // workspace the package was built in.
-                let actual_workspace = if path_util::user_set_rust_path() {
-                    default_workspace()
-                }
-                else {
-                    Path(destination_workspace)
-                };
-                debug!("install: destination workspace = %s, id = %s, installing to %s",
-                       destination_workspace, id_str, actual_workspace.to_str());
-                let result = subself.install_no_build(&Path(destination_workspace),
-                                                      &actual_workspace,
-                                                      &sub_id);
-                debug!("install: id = %s, about to call discover_outputs, %?",
-                       id_str, result.to_str());
-
-                discover_outputs(exec, result.clone());
-                sub_files.write(|r| { *r = result.clone(); });
-                sub_inputs.write(|r| { *r = *r + exec.lookup_discovered_inputs() });
-                note(fmt!("Installed package %s to %s", id_str, actual_workspace.to_str()));
+    fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str, ~str)]) {
+
+        let id = pkg_src.id.clone();
+
+        let mut installed_files = ~[];
+        let inputs = ~[];
+
+        // workcache only knows about *crates*. Building a package
+        // just means inferring all the crates in it, then building each one.
+        let destination_workspace = self.build(&mut pkg_src, what).to_str();
+
+        let to_do = ~[pkg_src.libs.clone(), pkg_src.mains.clone(),
+                      pkg_src.tests.clone(), pkg_src.benchs.clone()];
+        debug!("In declare inputs for %s", id.to_str());
+        for cs in to_do.iter() {
+            for c in cs.iter() {
+                let path = pkg_src.start_dir.push_rel(&c.file).normalize();
+                debug!("Recording input: %s", path.to_str());
+                installed_files.push(path);
             }
+        }
+        // See #7402: This still isn't quite right yet; we want to
+        // install to the first workspace in the RUST_PATH if there's
+        // a non-default RUST_PATH. This code installs to the same
+        // workspace the package was built in.
+        let actual_workspace = if path_util::user_set_rust_path() {
+            default_workspace()
+        }
+            else {
+            Path(destination_workspace)
         };
-        (installed_files.unwrap(), inputs.unwrap())
+        debug!("install: destination workspace = %s, id = %s, installing to %s",
+               destination_workspace, id.to_str(), actual_workspace.to_str());
+        let result = self.install_no_build(&Path(destination_workspace),
+                                           &actual_workspace,
+                                           &id).map(|s| Path(*s));
+        debug!("install: id = %s, about to call discover_outputs, %?",
+               id.to_str(), result.to_str());
+        installed_files = installed_files + result;
+        note(fmt!("Installed package %s to %s", id.to_str(), actual_workspace.to_str()));
+        (installed_files, inputs)
     }
 
+    // again, working around lack of Encodable for Path
     fn install_no_build(&self,
                         source_workspace: &Path,
                         target_workspace: &Path,
-                        id: &PkgId) -> ~[Path] {
+                        id: &PkgId) -> ~[~str] {
         use conditions::copy_failed::cond;
 
         // Now copy stuff into the install dirs
@@ -503,32 +531,59 @@ impl CtxMethods for BuildContext {
         let target_lib = maybe_library.map(|_p| target_library_in_workspace(id, target_workspace));
 
         debug!("target_exec = %s target_lib = %? \
-                maybe_executable = %? maybe_library = %?",
+               maybe_executable = %? maybe_library = %?",
                target_exec.to_str(), target_lib,
                maybe_executable, maybe_library);
 
-        let mut outputs = ~[];
-
-        for exec in maybe_executable.iter() {
-            debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str());
-            if !(os::mkdir_recursive(&target_exec.dir_path(), U_RWX) &&
-                 os::copy_file(exec, &target_exec)) {
-                cond.raise(((*exec).clone(), target_exec.clone()));
+        do self.workcache_context.with_prep(id.install_tag()) |prep| {
+            for ee in maybe_executable.iter() {
+                prep.declare_input("binary",
+                                   ee.to_str(),
+                                   workcache_support::digest_only_date(ee));
             }
-            outputs.push(target_exec.clone());
-        }
-        for lib in maybe_library.iter() {
-            let target_lib = target_lib.clone().expect(fmt!("I built %s but apparently \
-                                                didn't install it!", lib.to_str()));
-            let target_lib = target_lib.pop().push(lib.filename().expect("weird target lib"));
-            debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str());
-            if !(os::mkdir_recursive(&target_lib.dir_path(), U_RWX) &&
-                 os::copy_file(lib, &target_lib)) {
-                cond.raise(((*lib).clone(), target_lib.clone()));
+            for ll in maybe_library.iter() {
+                prep.declare_input("binary",
+                                   ll.to_str(),
+                                   workcache_support::digest_only_date(ll));
+            }
+            let subex = maybe_executable.clone();
+            let sublib = maybe_library.clone();
+            let sub_target_ex = target_exec.clone();
+            let sub_target_lib = target_lib.clone();
+
+            do prep.exec |exe_thing| {
+                let mut outputs = ~[];
+
+                for exec in subex.iter() {
+                    debug!("Copying: %s -> %s", exec.to_str(), sub_target_ex.to_str());
+                    if !(os::mkdir_recursive(&sub_target_ex.dir_path(), U_RWX) &&
+                         os::copy_file(exec, &sub_target_ex)) {
+                        cond.raise(((*exec).clone(), sub_target_ex.clone()));
+                    }
+                    exe_thing.discover_output("binary",
+                        sub_target_ex.to_str(),
+                        workcache_support::digest_only_date(&sub_target_ex));
+                    outputs.push(sub_target_ex.to_str());
+                }
+                for lib in sublib.iter() {
+                    let target_lib = sub_target_lib
+                        .clone().expect(fmt!("I built %s but apparently \
+                                             didn't install it!", lib.to_str()));
+                    let target_lib = target_lib
+                        .pop().push(lib.filename().expect("weird target lib"));
+                    debug!("Copying: %s -> %s", lib.to_str(), sub_target_lib.to_str());
+                    if !(os::mkdir_recursive(&target_lib.dir_path(), U_RWX) &&
+                         os::copy_file(lib, &target_lib)) {
+                        cond.raise(((*lib).clone(), target_lib.clone()));
+                    }
+                    exe_thing.discover_output("binary",
+                                              target_lib.to_str(),
+                                              workcache_support::digest_only_date(&target_lib));
+                    outputs.push(target_lib.to_str());
+                }
+                outputs
             }
-            outputs.push(target_lib.clone());
         }
-        outputs
     }
 
     fn prefer(&self, _id: &str, _vers: Option<~str>)  {
@@ -540,6 +595,13 @@ impl CtxMethods for BuildContext {
         fail!("test not yet implemented");
     }
 
+    fn init(&self) {
+        os::mkdir_recursive(&Path("src"),   U_RWX);
+        os::mkdir_recursive(&Path("lib"),   U_RWX);
+        os::mkdir_recursive(&Path("bin"),   U_RWX);
+        os::mkdir_recursive(&Path("build"), U_RWX);
+    }
+
     fn uninstall(&self, _id: &str, _vers: Option<~str>)  {
         fail!("uninstall not yet implemented");
     }
@@ -688,6 +750,7 @@ pub fn main_args(args: &[~str]) {
                     ~"list"    => usage::list(),
                     ~"prefer" => usage::prefer(),
                     ~"test" => usage::test(),
+                    ~"init" => usage::init(),
                     ~"uninstall" => usage::uninstall(),
                     ~"unprefer" => usage::unprefer(),
                     _ => usage::general()
@@ -710,15 +773,27 @@ pub fn main_args(args: &[~str]) {
 
     debug!("Using sysroot: %s", sroot.to_str());
     debug!("Will store workcache in %s", default_workspace().to_str());
-    BuildContext {
-        context: Context {
-        cfgs: cfgs,
-        rustc_flags: rustc_flags,
-        use_rust_path_hack: use_rust_path_hack,
-        sysroot: sroot, // Currently, only tests override this
-    },
-        workcache_context: api::default_context(default_workspace()).workcache_context
-    }.run(*cmd, remaining_args)
+
+    let rm_args = remaining_args.clone();
+    let sub_cmd = cmd.clone();
+    // Wrap the rest in task::try in case of a condition failure in a task
+    let result = do task::try {
+        BuildContext {
+            context: Context {
+                cfgs: cfgs.clone(),
+                rustc_flags: rustc_flags.clone(),
+                use_rust_path_hack: use_rust_path_hack,
+                sysroot: sroot.clone(), // Currently, only tests override this
+            },
+            workcache_context: api::default_context(default_workspace()).workcache_context
+        }.run(sub_cmd, rm_args.clone())
+    };
+    // FIXME #9262: This is using the same error code for all errors,
+    // and at least one test case succeeds if rustpkg returns copy_failed_code,
+    // when actually, it might set the exit code for that even if a different
+    // unhandled condition got raised.
+    if result.is_err() { os::set_exit_status(copy_failed_code); }
+
 }
 
 /**
diff --git a/src/librustpkg/target.rs b/src/librustpkg/target.rs
index 03c2f5a4fe4..9d3ad1f39a7 100644
--- a/src/librustpkg/target.rs
+++ b/src/librustpkg/target.rs
@@ -16,8 +16,45 @@ pub enum OutputType { Main, Lib, Bench, Test }
 
 #[deriving(Eq)]
 pub enum Target {
-    // In-place build
+    /// In-place build
     Build,
-    // Install to bin/ or lib/ dir
+    /// Install to bin/ or lib/ dir
     Install
 }
+
+#[deriving(Eq, Clone)]
+pub enum WhatToBuild {
+    /// Build just one lib.rs file in `path`, which is relative to the active workspace's src/ dir
+    JustOne(Path),
+    /// Build everything
+    Everything
+}
+
+pub fn is_lib(p: &Path) -> bool {
+    file_is(p, "lib")
+}
+
+pub fn is_main(p: &Path) -> bool {
+    file_is(p, "main")
+}
+
+pub fn is_test(p: &Path) -> bool {
+    file_is(p, "test")
+}
+
+pub fn is_bench(p: &Path) -> bool {
+    file_is(p, "bench")
+}
+
+fn file_is(p: &Path, stem: &str) -> bool {
+    match p.filestem() {
+        Some(s) if s == stem => true,
+        _ => false
+    }
+}
+
+pub fn lib_name_of(p: &Path) -> Path {
+    p.push("lib.rs")
+}
+
+pub static lib_crate_filename: &'static str = "lib.rs";
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index 83110e22ed5..918cc366799 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -34,11 +34,7 @@ use rustc::driver::driver::{build_session, build_session_options, host_triple, o
 use syntax::diagnostic;
 use target::*;
 use package_source::PkgSrc;
-
-/// Returns the last-modified date as an Option
-fn datestamp(p: &Path) -> Option<libc::time_t> {
-    p.stat().map(|stat| stat.st_mtime)
-}
+use util::datestamp;
 
 fn fake_ctxt(sysroot: Path, workspace: &Path) -> BuildContext {
     let context = workcache::Context::new(
@@ -224,18 +220,26 @@ fn rustpkg_exec() -> Path {
 }
 
 fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
-    command_line_test_with_env(args, cwd, None).expect("Command line test failed")
+    match command_line_test_with_env(args, cwd, None) {
+        Success(r) => r,
+        _ => fail!("Command line test failed")
+    }
 }
 
-fn command_line_test_partial(args: &[~str], cwd: &Path) -> Option<ProcessOutput> {
+fn command_line_test_partial(args: &[~str], cwd: &Path) -> ProcessResult {
     command_line_test_with_env(args, cwd, None)
 }
 
+enum ProcessResult {
+    Success(ProcessOutput),
+    Fail(int) // exit code
+}
+
 /// Runs `rustpkg` (based on the directory that this executable was
 /// invoked from) with the given arguments, in the given working directory.
 /// Returns the process's output.
 fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
-    -> Option<ProcessOutput> {
+    -> ProcessResult {
     let cmd = rustpkg_exec().to_str();
     let env_str = match env {
         Some(ref pairs) => pairs.map(|&(ref k, ref v)| { fmt!("%s=%s", *k, *v) }).connect(","),
@@ -266,10 +270,10 @@ to make sure the command succeeded
         debug!("Command %s %? failed with exit code %?; its output was {{{ %s }}}",
               cmd, args, output.status,
               str::from_utf8(output.output) + str::from_utf8(output.error));
-        None
+        Fail(output.status)
     }
     else {
-        Some(output)
+        Success(output)
     }
 }
 
@@ -410,8 +414,11 @@ fn command_line_test_output(args: &[~str]) -> ~[~str] {
 
 fn command_line_test_output_with_env(args: &[~str], env: ~[(~str, ~str)]) -> ~[~str] {
     let mut result = ~[];
-    let p_output = command_line_test_with_env(args,
-        &os::getcwd(), Some(env)).expect("Command-line test failed");
+    let p_output = match command_line_test_with_env(args,
+        &os::getcwd(), Some(env)) {
+        Fail(_) => fail!("Command-line test failed"),
+        Success(r) => r
+    };
     let test_output = str::from_utf8(p_output.output);
     for s in test_output.split_iter('\n') {
         result.push(s.to_owned());
@@ -420,9 +427,9 @@ fn command_line_test_output_with_env(args: &[~str], env: ~[(~str, ~str)]) -> ~[~
 }
 
 // assumes short_name and path are one and the same -- I should fix
-fn lib_output_file_name(workspace: &Path, parent: &str, short_name: &str) -> Path {
-    debug!("lib_output_file_name: given %s and parent %s and short name %s",
-           workspace.to_str(), parent, short_name);
+fn lib_output_file_name(workspace: &Path, short_name: &str) -> Path {
+    debug!("lib_output_file_name: given %s and short name %s",
+           workspace.to_str(), short_name);
     library_in_workspace(&Path(short_name),
                          short_name,
                          Build,
@@ -450,19 +457,18 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
 }
 
 /// Add a comment at the end
-fn frob_source_file(workspace: &Path, pkgid: &PkgId) {
+fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) {
     use conditions::bad_path::cond;
     let pkg_src_dir = workspace.push_many([~"src", pkgid.to_str()]);
-    let contents = os::list_dir_path(&pkg_src_dir);
     let mut maybe_p = None;
-    for p in contents.iter() {
-        if p.filetype() == Some(".rs") {
-            maybe_p = Some(p);
-            break;
-        }
+    let maybe_file = pkg_src_dir.push(filename);
+    debug!("Trying to frob %s -- %s", pkg_src_dir.to_str(), filename);
+    if os::path_exists(&maybe_file) {
+        maybe_p = Some(maybe_file);
     }
+    debug!("Frobbed? %?", maybe_p);
     match maybe_p {
-        Some(p) => {
+        Some(ref p) => {
             let w = io::file_writer(p, &[io::Append]);
             match w {
                 Err(s) => { let _ = cond.raise((p.clone(), fmt!("Bad path: %s", s))); }
@@ -499,7 +505,7 @@ fn test_install_valid() {
     debug!("temp_workspace = %s", temp_workspace.to_str());
     // should have test, bench, lib, and main
     let src = PkgSrc::new(temp_workspace.clone(), false, temp_pkg_id.clone());
-    ctxt.install(src);
+    ctxt.install(src, &Everything);
     // Check that all files exist
     let exec = target_executable_in_workspace(&temp_pkg_id, &temp_workspace);
     debug!("exec = %s", exec.to_str());
@@ -528,7 +534,7 @@ fn test_install_invalid() {
     // Uses task::try because of #9001
     let result = do task::try {
         let pkg_src = PkgSrc::new(temp_workspace.clone(), false, pkgid.clone());
-        ctxt.install(pkg_src);
+        ctxt.install(pkg_src, &Everything);
     };
     // Not the best test -- doesn't test that we failed in the right way.
     // Best we can do for now.
@@ -944,20 +950,23 @@ fn no_rebuilding_dep() {
     let dep_id = PkgId::new("bar");
     let workspace = create_local_package_with_dep(&p_id, &dep_id);
     command_line_test([~"build", ~"foo"], &workspace);
-    let bar_date_1 = datestamp(&lib_output_file_name(&workspace,
-                                                  ".rust",
-                                                  "bar"));
-    let foo_date_1 = datestamp(&output_file_name(&workspace, ~"foo"));
+    let bar_lib = lib_output_file_name(&workspace, "bar");
+    let bar_date_1 = datestamp(&bar_lib);
+
+    frob_source_file(&workspace, &p_id, "main.rs");
+
+    // Now make `bar` read-only so that subsequent rebuilds of it will fail
+    assert!(chmod_read_only(&bar_lib));
+
+    match command_line_test_partial([~"build", ~"foo"], &workspace) {
+        Success(*) => (), // ok
+        Fail(status) if status == 65 => fail!("no_rebuilding_dep failed: it tried to rebuild bar"),
+        Fail(_) => fail!("no_rebuilding_dep failed for some other reason")
+    }
 
-    frob_source_file(&workspace, &p_id);
-    command_line_test([~"build", ~"foo"], &workspace);
     let bar_date_2 = datestamp(&lib_output_file_name(&workspace,
-                                                  ".rust",
-                                                  "bar"));
-    let foo_date_2 = datestamp(&output_file_name(&workspace, ~"foo"));
+                                                   "bar"));
     assert_eq!(bar_date_1, bar_date_2);
-    assert!(foo_date_1 < foo_date_2);
-    assert!(foo_date_1 > bar_date_1);
 }
 
 #[test]
@@ -966,7 +975,7 @@ fn do_rebuild_dep_dates_change() {
     let dep_id = PkgId::new("bar");
     let workspace = create_local_package_with_dep(&p_id, &dep_id);
     command_line_test([~"build", ~"foo"], &workspace);
-    let bar_lib_name = lib_output_file_name(&workspace, "build", "bar");
+    let bar_lib_name = lib_output_file_name(&workspace, "bar");
     let bar_date = datestamp(&bar_lib_name);
     debug!("Datestamp on %s is %?", bar_lib_name.to_str(), bar_date);
     touch_source_file(&workspace, &dep_id);
@@ -982,11 +991,11 @@ fn do_rebuild_dep_only_contents_change() {
     let dep_id = PkgId::new("bar");
     let workspace = create_local_package_with_dep(&p_id, &dep_id);
     command_line_test([~"build", ~"foo"], &workspace);
-    let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
-    frob_source_file(&workspace, &dep_id);
+    let bar_date = datestamp(&lib_output_file_name(&workspace, "bar"));
+    frob_source_file(&workspace, &dep_id, "lib.rs");
     // should adjust the datestamp
     command_line_test([~"build", ~"foo"], &workspace);
-    let new_bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
+    let new_bar_date = datestamp(&lib_output_file_name(&workspace, "bar"));
     assert!(new_bar_date > bar_date);
 }
 
@@ -1308,7 +1317,6 @@ fn rust_path_hack_build_no_arg() {
 }
 
 #[test]
-#[ignore (reason = "#7402 not yet implemented")]
 fn rust_path_install_target() {
     let dir_for_path = mkdtemp(&os::tmpdir(),
         "source_workspace").expect("rust_path_install_target failed");
@@ -1463,10 +1471,13 @@ fn test_cfg_fail() {
     let workspace = create_local_package(&p_id);
     writeFile(&workspace.push_many(["src", "foo-0.1", "main.rs"]),
                "#[cfg(quux)] fn main() {}");
-    assert!(command_line_test_partial([test_sysroot().to_str(),
+    match command_line_test_partial([test_sysroot().to_str(),
                        ~"build",
                        ~"foo"],
-                      &workspace).is_none());
+                      &workspace) {
+        Success(*) => fail!("test_cfg_fail failed"),
+        _          => ()
+    }
 }
 
 
@@ -1679,6 +1690,21 @@ fn test_target_specific_install_dir() {
     assert_executable_exists(&workspace, "foo");
 }
 
+#[test]
+fn test_dependencies_terminate() {
+ //   let a_id = PkgId::new("a");
+    let b_id = PkgId::new("b");
+//    let workspace = create_local_package_with_dep(&b_id, &a_id);
+    let workspace = create_local_package(&b_id);
+    let b_dir = workspace.push_many([~"src", ~"b-0.1"]);
+  //  writeFile(&b_dir.push("lib.rs"), "extern mod a; pub fn f() {}");
+    let b_subdir = b_dir.push("test");
+    assert!(os::mkdir_recursive(&b_subdir, U_RWX));
+    writeFile(&b_subdir.push("test.rs"),
+              "extern mod b; use b::f; #[test] fn g() { f() }");
+    command_line_test([~"install", ~"b"], &workspace);
+}
+
 /// Returns true if p exists and is executable
 fn is_executable(p: &Path) -> bool {
     use std::libc::consts::os::posix88::{S_IXUSR};
@@ -1688,3 +1714,25 @@ fn is_executable(p: &Path) -> bool {
         Some(mode) => mode & S_IXUSR as uint == S_IXUSR as uint
     }
 }
+
+#[cfg(target_os = "win32")]
+fn chmod_read_only(p: &Path) -> bool {
+    #[fixed_stack_segment];
+    unsafe {
+        do p.to_str().with_c_str |src_buf| {
+            libc::chmod(src_buf, libc::consts::os::posix88::S_IRUSR as c_int) == 0 as libc::c_int
+        }
+    }
+}
+
+#[cfg(not(target_os = "win32"))]
+fn chmod_read_only(p: &Path) -> bool {
+    #[fixed_stack_segment];
+    unsafe {
+        do p.to_str().with_c_str |src_buf| {
+            libc::chmod(src_buf,
+                        libc::consts::os::posix88::S_IRUSR as libc::mode_t) == 0
+                as libc::c_int
+        }
+    }
+}
diff --git a/src/librustpkg/usage.rs b/src/librustpkg/usage.rs
index dae949541b3..c0601818f37 100644
--- a/src/librustpkg/usage.rs
+++ b/src/librustpkg/usage.rs
@@ -148,3 +148,10 @@ and exit code will be redirected.
 Options:
     -c, --cfg      Pass a cfg flag to the package script");
 }
+
+pub fn init() {
+    io::println("rustpkg init name
+
+This makes a new workspace for working on a project named name.
+");
+}
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 71c4760f28d..64f76dcdc60 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::libc;
 use std::os;
 use extra::workcache;
 use rustc::driver::{driver, session};
@@ -26,14 +27,14 @@ use workspace::pkg_parent_workspaces;
 use path_util::{installed_library_in_workspace, U_RWX, rust_path, system_library, target_build_dir};
 use messages::error;
 
-pub use target::{OutputType, Main, Lib, Bench, Test};
+pub use target::{OutputType, Main, Lib, Bench, Test, JustOne, lib_name_of, lib_crate_filename};
 use workcache_support::{digest_file_with_date, digest_only_date};
 
 // It would be nice to have the list of commands in just one place -- for example,
 // you could update the match in rustpkg.rc but forget to update this list. I think
 // that should be fixed.
 static COMMANDS: &'static [&'static str] =
-    &["build", "clean", "do", "info", "install", "list", "prefer", "test", "uninstall",
+    &["build", "clean", "do", "info", "init", "install", "list", "prefer", "test", "uninstall",
       "unprefer"];
 
 
@@ -171,6 +172,8 @@ pub fn compile_input(context: &BuildContext,
     // not sure if we should support anything else
 
     let out_dir = target_build_dir(workspace).push_rel(&pkg_id.path);
+    // Make the output directory if it doesn't exist already
+    assert!(os::mkdir_recursive(&out_dir, U_RWX));
 
     let binary = os::args()[0].to_managed();
 
@@ -220,7 +223,7 @@ pub fn compile_input(context: &BuildContext,
         optimize: if opt { session::Aggressive } else { session::No },
         test: what == Test || what == Bench,
         maybe_sysroot: Some(sysroot_to_use),
-        addl_lib_search_paths: @mut (~[out_dir.clone()]),
+        addl_lib_search_paths: @mut (~[]),
         output_type: output_type,
         .. (*driver::build_session_options(binary, &matches, diagnostic::emit)).clone()
     };
@@ -329,6 +332,9 @@ pub fn compile_crate_from_input(input: &Path,
     // Register dependency on the source file
     exec.discover_input("file", input.to_str(), digest_file_with_date(input));
 
+    debug!("Built %s, date = %?", outputs.out_filename.to_str(),
+           datestamp(&outputs.out_filename));
+
     Some(outputs.out_filename)
 }
 
@@ -409,7 +415,8 @@ pub fn find_and_install_dependencies(context: &BuildContext,
                             workspaces[0]
                         };
                         let (outputs_disc, inputs_disc) =
-                            context.install(PkgSrc::new(dep_workspace.clone(), false, pkg_id));
+                            context.install(PkgSrc::new(dep_workspace.clone(),
+                                false, pkg_id), &JustOne(Path(lib_crate_filename)));
                         debug!("Installed %s, returned %? dependencies and \
                                %? transitive dependencies",
                                lib_name, outputs_disc.len(), inputs_disc.len());
@@ -435,10 +442,11 @@ pub fn find_and_install_dependencies(context: &BuildContext,
                         debug!("Adding additional search path: %s", lib_name);
                         let installed_library =
                             installed_library_in_workspace(&Path(lib_name), &dep_workspace)
-                                .expect( fmt!("rustpkg failed to install dependency %s",
+                                .expect(fmt!("rustpkg failed to install dependency %s",
                                               lib_name));
                         let install_dir = installed_library.pop();
-                        debug!("Installed %s into %s", lib_name, install_dir.to_str());
+                        debug!("Installed %s into %s [%?]", lib_name, install_dir.to_str(),
+                               datestamp(&installed_library));
                         save(install_dir);
                     }
                 }}
@@ -449,37 +457,6 @@ pub fn find_and_install_dependencies(context: &BuildContext,
     };
 }
 
-#[cfg(windows)]
-pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
-    #[fixed_stack_segment]; #[inline(never)];
-
-    /* FIXME (#1768): Investigate how to do this on win32
-       Node wraps symlinks by having a .bat,
-       but that won't work with minGW. */
-
-    false
-}
-
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "android")]
-#[cfg(target_os = "freebsd")]
-#[cfg(target_os = "macos")]
-pub fn link_exe(src: &Path, dest: &Path) -> bool {
-    #[fixed_stack_segment]; #[inline(never)];
-
-    use std::c_str::ToCStr;
-    use std::libc;
-
-    unsafe {
-        do src.with_c_str |src_buf| {
-            do dest.with_c_str |dest_buf| {
-                libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
-                    libc::chmod(dest_buf, 755) == 0 as libc::c_int
-            }
-        }
-    }
-}
-
 pub fn mk_string_lit(s: @str) -> ast::lit {
     Spanned {
         node: ast::lit_str(s),
@@ -516,3 +493,12 @@ pub fn option_to_vec<T>(x: Option<T>) -> ~[T] {
 // tjc: cheesy
 fn debug_flags() -> ~[~str] { ~[] }
 // static DEBUG_FLAGS: ~[~str] = ~[~"-Z", ~"time-passes"];
+
+
+/// Returns the last-modified date as an Option
+pub fn datestamp(p: &Path) -> Option<libc::time_t> {
+    debug!("Scrutinizing datestamp for %s - does it exist? %?", p.to_str(), os::path_exists(p));
+    let out = p.stat().map(|stat| stat.st_mtime);
+    debug!("Date = %?", out);
+    out.map(|t| { *t as libc::time_t })
+}
diff --git a/src/librustpkg/workcache_support.rs b/src/librustpkg/workcache_support.rs
index e2416782d98..daf35c988c8 100644
--- a/src/librustpkg/workcache_support.rs
+++ b/src/librustpkg/workcache_support.rs
@@ -56,3 +56,8 @@ pub fn discover_outputs(e: &mut workcache::Exec, outputs: ~[Path]) {
         e.discover_output("binary", p.to_str(), digest_only_date(p));
     }
 }
+
+/// Returns the function name for building a crate
+pub fn crate_tag(p: &Path) -> ~str {
+    p.to_str() // implicitly, it's "build(p)"...
+}
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index 75598b300a3..67b5aff8466 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -30,9 +30,7 @@ pub enum NullByteResolution {
 
 condition! {
     // This should be &[u8] but there's a lifetime issue (#5370).
-    // NOTE: this super::NullByteResolution should be NullByteResolution
-    // Change this next time the snapshot is updated.
-    pub null_byte: (~[u8]) -> super::NullByteResolution;
+    pub null_byte: (~[u8]) -> NullByteResolution;
 }
 
 /// The representation of a C String.
diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs
index 790dc886c04..a5a2def450e 100644
--- a/src/libstd/libc.rs
+++ b/src/libstd/libc.rs
@@ -294,7 +294,6 @@ pub mod types {
                 pub type ssize_t = i32;
             }
             #[cfg(target_arch = "x86")]
-            #[cfg(target_arch = "mips")]
             pub mod posix01 {
                 use libc::types::os::arch::c95::{c_short, c_long, time_t};
                 use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
@@ -305,7 +304,6 @@ pub mod types {
                 pub type blksize_t = i32;
                 pub type blkcnt_t = i32;
 
-                #[cfg(target_arch = "x86")]
                 pub struct stat {
                     st_dev: dev_t,
                     __pad1: c_short,
@@ -328,30 +326,6 @@ pub mod types {
                     __unused4: c_long,
                     __unused5: c_long,
                 }
-
-                #[cfg(target_arch = "mips")]
-                pub struct stat {
-                    st_dev: c_ulong,
-                    st_pad1: [c_long, ..3],
-                    st_ino: ino_t,
-                    st_mode: mode_t,
-                    st_nlink: nlink_t,
-                    st_uid: uid_t,
-                    st_gid: gid_t,
-                    st_rdev: c_ulong,
-                    st_pad2: [c_long, ..2],
-                    st_size: off_t,
-                    st_pad3: c_long,
-                    st_atime: time_t,
-                    st_atime_nsec: c_long,
-                    st_mtime: time_t,
-                    st_mtime_nsec: c_long,
-                    st_ctime: time_t,
-                    st_ctime_nsec: c_long,
-                    st_blksize: blksize_t,
-                    st_blocks: blkcnt_t,
-                    st_pad5: [c_long, ..14],
-                }
             }
             #[cfg(target_arch = "arm")]
             pub mod posix01 {
@@ -385,6 +359,40 @@ pub mod types {
                     st_ino: c_ulonglong
                 }
             }
+            #[cfg(target_arch = "mips")]
+            pub mod posix01 {
+                use libc::types::os::arch::c95::{c_long, c_ulong, time_t};
+                use libc::types::os::arch::posix88::{gid_t, ino_t};
+                use libc::types::os::arch::posix88::{mode_t, off_t};
+                use libc::types::os::arch::posix88::{uid_t};
+
+                pub type nlink_t = u32;
+                pub type blksize_t = i32;
+                pub type blkcnt_t = i32;
+
+                pub struct stat {
+                    st_dev: c_ulong,
+                    st_pad1: [c_long, ..3],
+                    st_ino: ino_t,
+                    st_mode: mode_t,
+                    st_nlink: nlink_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    st_rdev: c_ulong,
+                    st_pad2: [c_long, ..2],
+                    st_size: off_t,
+                    st_pad3: c_long,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    st_blksize: blksize_t,
+                    st_blocks: blkcnt_t,
+                    st_pad5: [c_long, ..14],
+                }
+            }
             pub mod posix08 {}
             pub mod bsd44 {}
             pub mod extra {}
@@ -1633,6 +1641,111 @@ pub mod consts {
             pub static EPIPE : c_int = 32;
             pub static EDOM : c_int = 33;
             pub static ERANGE : c_int = 34;
+
+            pub static ENOMSG: c_int = 35;
+            pub static EIDRM: c_int = 36;
+            pub static ECHRNG: c_int = 37;
+            pub static EL2NSYNC: c_int = 38;
+            pub static EL3HLT: c_int = 39;
+            pub static EL3RST: c_int = 40;
+            pub static ELNRNG: c_int = 41;
+            pub static EUNATCH: c_int = 42;
+            pub static ENOCSI: c_int = 43;
+            pub static EL2HLT: c_int = 44;
+            pub static EDEADLK: c_int = 45;
+            pub static ENOLCK: c_int = 46;
+            pub static EBADE: c_int = 50;
+            pub static EBADR: c_int = 51;
+            pub static EXFULL: c_int = 52;
+            pub static ENOANO: c_int = 53;
+            pub static EBADRQC: c_int = 54;
+            pub static EBADSLT: c_int = 55;
+            pub static EDEADLOCK: c_int = 56;
+            pub static EBFONT: c_int = 59;
+            pub static ENOSTR: c_int = 60;
+            pub static ENODATA: c_int = 61;
+            pub static ETIME: c_int = 62;
+            pub static ENOSR: c_int = 63;
+            pub static ENONET: c_int = 64;
+            pub static ENOPKG: c_int = 65;
+            pub static EREMOTE: c_int = 66;
+            pub static ENOLINK: c_int = 67;
+            pub static EADV: c_int = 68;
+            pub static ESRMNT: c_int = 69;
+            pub static ECOMM: c_int = 70;
+            pub static EPROTO: c_int = 71;
+            pub static EDOTDOT: c_int = 73;
+            pub static EMULTIHOP: c_int = 74;
+            pub static EBADMSG: c_int = 77;
+            pub static ENAMETOOLONG: c_int = 78;
+            pub static EOVERFLOW: c_int = 79;
+            pub static ENOTUNIQ: c_int = 80;
+            pub static EBADFD: c_int = 81;
+            pub static EREMCHG: c_int = 82;
+            pub static ELIBACC: c_int = 83;
+            pub static ELIBBAD: c_int = 84;
+            pub static ELIBSCN: c_int = 95;
+            pub static ELIBMAX: c_int = 86;
+            pub static ELIBEXEC: c_int = 87;
+            pub static EILSEQ: c_int = 88;
+            pub static ENOSYS: c_int = 89;
+            pub static ELOOP: c_int = 90;
+            pub static ERESTART: c_int = 91;
+            pub static ESTRPIPE: c_int = 92;
+            pub static ENOTEMPTY: c_int = 93;
+            pub static EUSERS: c_int = 94;
+            pub static ENOTSOCK: c_int = 95;
+            pub static EDESTADDRREQ: c_int = 96;
+            pub static EMSGSIZE: c_int = 97;
+            pub static EPROTOTYPE: c_int = 98;
+            pub static ENOPROTOOPT: c_int = 99;
+            pub static EPROTONOSUPPORT: c_int = 120;
+            pub static ESOCKTNOSUPPORT: c_int = 121;
+            pub static EOPNOTSUPP: c_int = 122;
+            pub static EPFNOSUPPORT: c_int = 123;
+            pub static EAFNOSUPPORT: c_int = 124;
+            pub static EADDRINUSE: c_int = 125;
+            pub static EADDRNOTAVAIL: c_int = 126;
+            pub static ENETDOWN: c_int = 127;
+            pub static ENETUNREACH: c_int = 128;
+            pub static ENETRESET: c_int = 129;
+            pub static ECONNABORTED: c_int = 130;
+            pub static ECONNRESET: c_int = 131;
+            pub static ENOBUFS: c_int = 132;
+            pub static EISCONN: c_int = 133;
+            pub static ENOTCONN: c_int = 134;
+            pub static EUCLEAN: c_int = 135;
+            pub static ENOTNAM: c_int = 137;
+            pub static ENAVAIL: c_int = 138;
+            pub static EISNAM: c_int = 139;
+            pub static EREMOTEIO: c_int = 140;
+            pub static ESHUTDOWN: c_int = 143;
+            pub static ETOOMANYREFS: c_int = 144;
+            pub static ETIMEDOUT: c_int = 145;
+            pub static ECONNREFUSED: c_int = 146;
+            pub static EHOSTDOWN: c_int = 147;
+            pub static EHOSTUNREACH: c_int = 148;
+            pub static EWOULDBLOCK: c_int = EAGAIN;
+            pub static EALREADY: c_int = 149;
+            pub static EINPROGRESS: c_int = 150;
+            pub static ESTALE: c_int = 151;
+            pub static ECANCELED: c_int = 158;
+
+            pub static ENOMEDIUM: c_int = 159;
+            pub static EMEDIUMTYPE: c_int = 160;
+            pub static ENOKEY: c_int = 161;
+            pub static EKEYEXPIRED: c_int = 162;
+            pub static EKEYREVOKED: c_int = 163;
+            pub static EKEYREJECTED: c_int = 164;
+
+            pub static EOWNERDEAD: c_int = 165;
+            pub static ENOTRECOVERABLE: c_int = 166;
+
+            pub static ERFKILL: c_int = 167;
+
+            pub static EHWPOISON: c_int = 168;
+
+            pub static EDQUOT: c_int = 1133;
         }
         pub mod posix01 {
             use libc::types::os::arch::c95::c_int;
diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs
index b39b3102a34..1a463a499cb 100644
--- a/src/libstd/logging.rs
+++ b/src/libstd/logging.rs
@@ -37,17 +37,6 @@ pub fn console_off() {
     rt::logging::console_off();
 }
 
-#[cfg(not(test), stage0)]
-#[lang="log_type"]
-#[allow(missing_doc)]
-pub fn log_type<T>(_level: u32, object: &T) {
-    use sys;
-
-    // XXX: Bad allocation
-    let msg = sys::log_str(object);
-    newsched_log_str(msg);
-}
-
 fn newsched_log_str(msg: ~str) {
     use rt::task::Task;
     use rt::local::Local;
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs
index 0addcce3eb6..1bb488d0278 100644
--- a/src/libstd/num/f32.rs
+++ b/src/libstd/num/f32.rs
@@ -823,39 +823,6 @@ impl num::ToStrRadix for f32 {
 }
 
 ///
-/// Convert a string in base 10 to a float.
-/// Accepts a optional decimal exponent.
-///
-/// This function accepts strings such as
-///
-/// * '3.14'
-/// * '+3.14', equivalent to '3.14'
-/// * '-3.14'
-/// * '2.5E10', or equivalently, '2.5e10'
-/// * '2.5E-10'
-/// * '.' (understood as 0)
-/// * '5.'
-/// * '.5', or, equivalently,  '0.5'
-/// * '+inf', 'inf', '-inf', 'NaN'
-///
-/// Leading and trailing whitespace represent an error.
-///
-/// # Arguments
-///
-/// * num - A string
-///
-/// # Return value
-///
-/// `none` if the string did not represent a valid number.  Otherwise,
-/// `Some(n)` where `n` is the floating-point number represented by `num`.
-///
-#[inline]
-pub fn from_str(num: &str) -> Option<f32> {
-    strconv::from_str_common(num, 10u, true, true, true,
-                             strconv::ExpDec, false, false)
-}
-
-///
 /// Convert a string in base 16 to a float.
 /// Accepts a optional binary exponent.
 ///
@@ -888,40 +855,65 @@ pub fn from_str_hex(num: &str) -> Option<f32> {
                              strconv::ExpBin, false, false)
 }
 
-///
-/// Convert a string in an given base to a float.
-///
-/// Due to possible conflicts, this function does **not** accept
-/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
-/// does it recognize exponents of any kind.
-///
-/// Leading and trailing whitespace represent an error.
-///
-/// # Arguments
-///
-/// * num - A string
-/// * radix - The base to use. Must lie in the range [2 .. 36]
-///
-/// # Return value
-///
-/// `none` if the string did not represent a valid number. Otherwise,
-/// `Some(n)` where `n` is the floating-point number represented by `num`.
-///
-#[inline]
-pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> {
-    strconv::from_str_common(num, rdx, true, true, false,
-                             strconv::ExpNone, false, false)
-}
-
 impl FromStr for f32 {
+    ///
+    /// Convert a string in base 10 to a float.
+    /// Accepts a optional decimal exponent.
+    ///
+    /// This function accepts strings such as
+    ///
+    /// * '3.14'
+    /// * '+3.14', equivalent to '3.14'
+    /// * '-3.14'
+    /// * '2.5E10', or equivalently, '2.5e10'
+    /// * '2.5E-10'
+    /// * '.' (understood as 0)
+    /// * '5.'
+    /// * '.5', or, equivalently,  '0.5'
+    /// * '+inf', 'inf', '-inf', 'NaN'
+    ///
+    /// Leading and trailing whitespace represent an error.
+    ///
+    /// # Arguments
+    ///
+    /// * num - A string
+    ///
+    /// # Return value
+    ///
+    /// `none` if the string did not represent a valid number.  Otherwise,
+    /// `Some(n)` where `n` is the floating-point number represented by `num`.
+    ///
     #[inline]
-    fn from_str(val: &str) -> Option<f32> { from_str(val) }
+    fn from_str(val: &str) -> Option<f32> {
+        strconv::from_str_common(val, 10u, true, true, true,
+                                 strconv::ExpDec, false, false)
+    }
 }
 
 impl num::FromStrRadix for f32 {
+    ///
+    /// Convert a string in an given base to a float.
+    ///
+    /// Due to possible conflicts, this function does **not** accept
+    /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+    /// does it recognize exponents of any kind.
+    ///
+    /// Leading and trailing whitespace represent an error.
+    ///
+    /// # Arguments
+    ///
+    /// * num - A string
+    /// * radix - The base to use. Must lie in the range [2 .. 36]
+    ///
+    /// # Return value
+    ///
+    /// `none` if the string did not represent a valid number. Otherwise,
+    /// `Some(n)` where `n` is the floating-point number represented by `num`.
+    ///
     #[inline]
     fn from_str_radix(val: &str, rdx: uint) -> Option<f32> {
-        from_str_radix(val, rdx)
+        strconv::from_str_common(val, rdx, true, true, false,
+                                 strconv::ExpNone, false, false)
     }
 }
 
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs
index b0675278238..604eac0a0a7 100644
--- a/src/libstd/num/f64.rs
+++ b/src/libstd/num/f64.rs
@@ -870,39 +870,6 @@ impl num::ToStrRadix for f64 {
 }
 
 ///
-/// Convert a string in base 10 to a float.
-/// Accepts a optional decimal exponent.
-///
-/// This function accepts strings such as
-///
-/// * '3.14'
-/// * '+3.14', equivalent to '3.14'
-/// * '-3.14'
-/// * '2.5E10', or equivalently, '2.5e10'
-/// * '2.5E-10'
-/// * '.' (understood as 0)
-/// * '5.'
-/// * '.5', or, equivalently,  '0.5'
-/// * '+inf', 'inf', '-inf', 'NaN'
-///
-/// Leading and trailing whitespace represent an error.
-///
-/// # Arguments
-///
-/// * num - A string
-///
-/// # Return value
-///
-/// `none` if the string did not represent a valid number.  Otherwise,
-/// `Some(n)` where `n` is the floating-point number represented by `num`.
-///
-#[inline]
-pub fn from_str(num: &str) -> Option<f64> {
-    strconv::from_str_common(num, 10u, true, true, true,
-                             strconv::ExpDec, false, false)
-}
-
-///
 /// Convert a string in base 16 to a float.
 /// Accepts a optional binary exponent.
 ///
@@ -935,40 +902,65 @@ pub fn from_str_hex(num: &str) -> Option<f64> {
                              strconv::ExpBin, false, false)
 }
 
-///
-/// Convert a string in an given base to a float.
-///
-/// Due to possible conflicts, this function does **not** accept
-/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
-/// does it recognize exponents of any kind.
-///
-/// Leading and trailing whitespace represent an error.
-///
-/// # Arguments
-///
-/// * num - A string
-/// * radix - The base to use. Must lie in the range [2 .. 36]
-///
-/// # Return value
-///
-/// `none` if the string did not represent a valid number. Otherwise,
-/// `Some(n)` where `n` is the floating-point number represented by `num`.
-///
-#[inline]
-pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
-    strconv::from_str_common(num, rdx, true, true, false,
-                             strconv::ExpNone, false, false)
-}
-
 impl FromStr for f64 {
+    ///
+    /// Convert a string in base 10 to a float.
+    /// Accepts a optional decimal exponent.
+    ///
+    /// This function accepts strings such as
+    ///
+    /// * '3.14'
+    /// * '+3.14', equivalent to '3.14'
+    /// * '-3.14'
+    /// * '2.5E10', or equivalently, '2.5e10'
+    /// * '2.5E-10'
+    /// * '.' (understood as 0)
+    /// * '5.'
+    /// * '.5', or, equivalently,  '0.5'
+    /// * '+inf', 'inf', '-inf', 'NaN'
+    ///
+    /// Leading and trailing whitespace represent an error.
+    ///
+    /// # Arguments
+    ///
+    /// * num - A string
+    ///
+    /// # Return value
+    ///
+    /// `none` if the string did not represent a valid number.  Otherwise,
+    /// `Some(n)` where `n` is the floating-point number represented by `num`.
+    ///
     #[inline]
-    fn from_str(val: &str) -> Option<f64> { from_str(val) }
+    fn from_str(val: &str) -> Option<f64> {
+        strconv::from_str_common(val, 10u, true, true, true,
+                                 strconv::ExpDec, false, false)
+    }
 }
 
 impl num::FromStrRadix for f64 {
+    ///
+    /// Convert a string in an given base to a float.
+    ///
+    /// Due to possible conflicts, this function does **not** accept
+    /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+    /// does it recognize exponents of any kind.
+    ///
+    /// Leading and trailing whitespace represent an error.
+    ///
+    /// # Arguments
+    ///
+    /// * num - A string
+    /// * radix - The base to use. Must lie in the range [2 .. 36]
+    ///
+    /// # Return value
+    ///
+    /// `none` if the string did not represent a valid number. Otherwise,
+    /// `Some(n)` where `n` is the floating-point number represented by `num`.
+    ///
     #[inline]
     fn from_str_radix(val: &str, rdx: uint) -> Option<f64> {
-        from_str_radix(val, rdx)
+        strconv::from_str_common(val, rdx, true, true, false,
+                                 strconv::ExpNone, false, false)
     }
 }
 
diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs
index 3952f5478f7..b86422edc03 100644
--- a/src/libstd/num/float.rs
+++ b/src/libstd/num/float.rs
@@ -188,39 +188,6 @@ impl num::ToStrRadix for float {
 }
 
 ///
-/// Convert a string in base 10 to a float.
-/// Accepts a optional decimal exponent.
-///
-/// This function accepts strings such as
-///
-/// * '3.14'
-/// * '+3.14', equivalent to '3.14'
-/// * '-3.14'
-/// * '2.5E10', or equivalently, '2.5e10'
-/// * '2.5E-10'
-/// * '.' (understood as 0)
-/// * '5.'
-/// * '.5', or, equivalently,  '0.5'
-/// * '+inf', 'inf', '-inf', 'NaN'
-///
-/// Leading and trailing whitespace represent an error.
-///
-/// # Arguments
-///
-/// * num - A string
-///
-/// # Return value
-///
-/// `none` if the string did not represent a valid number.  Otherwise,
-/// `Some(n)` where `n` is the floating-point number represented by `num`.
-///
-#[inline]
-pub fn from_str(num: &str) -> Option<float> {
-    strconv::from_str_common(num, 10u, true, true, true,
-                             strconv::ExpDec, false, false)
-}
-
-///
 /// Convert a string in base 16 to a float.
 /// Accepts a optional binary exponent.
 ///
@@ -253,40 +220,65 @@ pub fn from_str_hex(num: &str) -> Option<float> {
                              strconv::ExpBin, false, false)
 }
 
-///
-/// Convert a string in an given base to a float.
-///
-/// Due to possible conflicts, this function does **not** accept
-/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
-/// does it recognize exponents of any kind.
-///
-/// Leading and trailing whitespace represent an error.
-///
-/// # Arguments
-///
-/// * num - A string
-/// * radix - The base to use. Must lie in the range [2 .. 36]
-///
-/// # Return value
-///
-/// `none` if the string did not represent a valid number. Otherwise,
-/// `Some(n)` where `n` is the floating-point number represented by `num`.
-///
-#[inline]
-pub fn from_str_radix(num: &str, radix: uint) -> Option<float> {
-    strconv::from_str_common(num, radix, true, true, false,
-                             strconv::ExpNone, false, false)
-}
-
 impl FromStr for float {
+    ///
+    /// Convert a string in base 10 to a float.
+    /// Accepts a optional decimal exponent.
+    ///
+    /// This function accepts strings such as
+    ///
+    /// * '3.14'
+    /// * '+3.14', equivalent to '3.14'
+    /// * '-3.14'
+    /// * '2.5E10', or equivalently, '2.5e10'
+    /// * '2.5E-10'
+    /// * '.' (understood as 0)
+    /// * '5.'
+    /// * '.5', or, equivalently,  '0.5'
+    /// * '+inf', 'inf', '-inf', 'NaN'
+    ///
+    /// Leading and trailing whitespace represent an error.
+    ///
+    /// # Arguments
+    ///
+    /// * num - A string
+    ///
+    /// # Return value
+    ///
+    /// `none` if the string did not represent a valid number.  Otherwise,
+    /// `Some(n)` where `n` is the floating-point number represented by `num`.
+    ///
     #[inline]
-    fn from_str(val: &str) -> Option<float> { from_str(val) }
+    fn from_str(val: &str) -> Option<float> {
+        strconv::from_str_common(val, 10u, true, true, true,
+                                 strconv::ExpDec, false, false)
+    }
 }
 
 impl num::FromStrRadix for float {
+    ///
+    /// Convert a string in an given base to a float.
+    ///
+    /// Due to possible conflicts, this function does **not** accept
+    /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+    /// does it recognize exponents of any kind.
+    ///
+    /// Leading and trailing whitespace represent an error.
+    ///
+    /// # Arguments
+    ///
+    /// * num - A string
+    /// * radix - The base to use. Must lie in the range [2 .. 36]
+    ///
+    /// # Return value
+    ///
+    /// `none` if the string did not represent a valid number. Otherwise,
+    /// `Some(n)` where `n` is the floating-point number represented by `num`.
+    ///
     #[inline]
     fn from_str_radix(val: &str, radix: uint) -> Option<float> {
-        from_str_radix(val, radix)
+        strconv::from_str_common(val, radix, true, true, false,
+                                 strconv::ExpNone, false, false)
     }
 }
 
@@ -1316,49 +1308,49 @@ mod tests {
 
     #[test]
     pub fn test_from_str() {
-        assert_eq!(from_str("3"), Some(3.));
-        assert_eq!(from_str("3.14"), Some(3.14));
-        assert_eq!(from_str("+3.14"), Some(3.14));
-        assert_eq!(from_str("-3.14"), Some(-3.14));
-        assert_eq!(from_str("2.5E10"), Some(25000000000.));
-        assert_eq!(from_str("2.5e10"), Some(25000000000.));
-        assert_eq!(from_str("25000000000.E-10"), Some(2.5));
-        assert_eq!(from_str("."), Some(0.));
-        assert_eq!(from_str(".e1"), Some(0.));
-        assert_eq!(from_str(".e-1"), Some(0.));
-        assert_eq!(from_str("5."), Some(5.));
-        assert_eq!(from_str(".5"), Some(0.5));
-        assert_eq!(from_str("0.5"), Some(0.5));
-        assert_eq!(from_str("-.5"), Some(-0.5));
-        assert_eq!(from_str("-5"), Some(-5.));
-        assert_eq!(from_str("inf"), Some(infinity));
-        assert_eq!(from_str("+inf"), Some(infinity));
-        assert_eq!(from_str("-inf"), Some(neg_infinity));
+        assert_eq!(from_str::<float>("3"), Some(3.));
+        assert_eq!(from_str::<float>("3.14"), Some(3.14));
+        assert_eq!(from_str::<float>("+3.14"), Some(3.14));
+        assert_eq!(from_str::<float>("-3.14"), Some(-3.14));
+        assert_eq!(from_str::<float>("2.5E10"), Some(25000000000.));
+        assert_eq!(from_str::<float>("2.5e10"), Some(25000000000.));
+        assert_eq!(from_str::<float>("25000000000.E-10"), Some(2.5));
+        assert_eq!(from_str::<float>("."), Some(0.));
+        assert_eq!(from_str::<float>(".e1"), Some(0.));
+        assert_eq!(from_str::<float>(".e-1"), Some(0.));
+        assert_eq!(from_str::<float>("5."), Some(5.));
+        assert_eq!(from_str::<float>(".5"), Some(0.5));
+        assert_eq!(from_str::<float>("0.5"), Some(0.5));
+        assert_eq!(from_str::<float>("-.5"), Some(-0.5));
+        assert_eq!(from_str::<float>("-5"), Some(-5.));
+        assert_eq!(from_str::<float>("inf"), Some(infinity));
+        assert_eq!(from_str::<float>("+inf"), Some(infinity));
+        assert_eq!(from_str::<float>("-inf"), Some(neg_infinity));
         // note: NaN != NaN, hence this slightly complex test
-        match from_str("NaN") {
+        match from_str::<float>("NaN") {
             Some(f) => assert!(f.is_NaN()),
             None => fail!()
         }
         // note: -0 == 0, hence these slightly more complex tests
-        match from_str("-0") {
+        match from_str::<float>("-0") {
             Some(v) if v.is_zero() => assert!(v.is_negative()),
             _ => fail!()
         }
-        match from_str("0") {
+        match from_str::<float>("0") {
             Some(v) if v.is_zero() => assert!(v.is_positive()),
             _ => fail!()
         }
 
-        assert!(from_str("").is_none());
-        assert!(from_str("x").is_none());
-        assert!(from_str(" ").is_none());
-        assert!(from_str("   ").is_none());
-        assert!(from_str("e").is_none());
-        assert!(from_str("E").is_none());
-        assert!(from_str("E1").is_none());
-        assert!(from_str("1e1e1").is_none());
-        assert!(from_str("1e1.1").is_none());
-        assert!(from_str("1e1-1").is_none());
+        assert!(from_str::<float>("").is_none());
+        assert!(from_str::<float>("x").is_none());
+        assert!(from_str::<float>(" ").is_none());
+        assert!(from_str::<float>("   ").is_none());
+        assert!(from_str::<float>("e").is_none());
+        assert!(from_str::<float>("E").is_none());
+        assert!(from_str::<float>("E1").is_none());
+        assert!(from_str::<float>("1e1e1").is_none());
+        assert!(from_str::<float>("1e1.1").is_none());
+        assert!(from_str::<float>("1e1-1").is_none());
     }
 
     #[test]
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 6fe6a1e47e9..1dc1d1d6776 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -148,18 +148,6 @@ pub mod win32 {
     }
 }
 
-#[cfg(stage0)]
-mod macro_hack {
-#[macro_escape];
-macro_rules! externfn(
-    (fn $name:ident ()) => (
-        extern {
-            fn $name();
-        }
-    )
-)
-}
-
 /*
 Accessing environment variables is not generally threadsafe.
 Serialize access through a global lock.
@@ -196,16 +184,7 @@ pub fn env() -> ~[(~str,~str)] {
             if (ch as uint == 0) {
                 fail!("os::env() failure getting env string from OS: %s", os::last_os_error());
             }
-            let mut curr_ptr: uint = ch as uint;
-            let mut result = ~[];
-            while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
-                let env_pair = str::raw::from_c_str(
-                    curr_ptr as *libc::c_char);
-                result.push(env_pair);
-                curr_ptr +=
-                    libc::strlen(curr_ptr as *libc::c_char) as uint
-                    + 1;
-            }
+            let result = str::raw::from_c_multistring(ch as *libc::c_char, None);
             FreeEnvironmentStringsA(ch);
             result
         }
@@ -1668,7 +1647,7 @@ pub mod consts {
     pub use os::consts::arm::*;
 
     #[cfg(target_arch = "mips")]
-    use os::consts::mips::*;
+    pub use os::consts::mips::*;
 
     pub mod unix {
         pub static FAMILY: &'static str = "unix";
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index 6e90e2a1070..135acb106a1 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -16,31 +16,13 @@ use clone::Clone;
 use cmp::Equiv;
 use iter::{range, Iterator};
 use option::{Option, Some, None};
-#[cfg(stage0)]
-use sys;
 use unstable::intrinsics;
 use util::swap;
 
 #[cfg(not(test))] use cmp::{Eq, Ord};
 
-/// Calculate the offset from a pointer. The count *must* be in bounds or
-/// otherwise the loads of this address are undefined.
-#[inline]
-#[cfg(stage0)]
-pub unsafe fn offset<T>(ptr: *T, count: int) -> *T {
-    (ptr as uint + (count as uint) * sys::size_of::<T>()) as *T
-}
-
-/// Calculate the offset from a mut pointer
-#[inline]
-#[cfg(stage0)]
-pub unsafe fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
-    (ptr as uint + (count as uint) * sys::size_of::<T>()) as *mut T
-}
-
 /// Calculate the offset from a pointer
 #[inline]
-#[cfg(not(stage0))]
 pub unsafe fn offset<T>(ptr: *T, count: int) -> *T {
     intrinsics::offset(ptr, count)
 }
@@ -48,7 +30,6 @@ pub unsafe fn offset<T>(ptr: *T, count: int) -> *T {
 /// Calculate the offset from a mut pointer. The count *must* be in bounds or
 /// otherwise the loads of this address are undefined.
 #[inline]
-#[cfg(not(stage0))]
 pub unsafe fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
     intrinsics::offset(ptr as *T, count) as *mut T
 }
@@ -383,17 +364,7 @@ impl<T> RawPtr<T> for *mut T {
 }
 
 // Equality for pointers
-#[cfg(stage0, not(test))]
-impl<T> Eq for *T {
-    #[inline]
-    fn eq(&self, other: &*T) -> bool {
-        (*self as uint) == (*other as uint)
-    }
-    #[inline]
-    fn ne(&self, other: &*T) -> bool { !self.eq(other) }
-}
-
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
 impl<T> Eq for *T {
     #[inline]
     fn eq(&self, other: &*T) -> bool {
@@ -403,17 +374,7 @@ impl<T> Eq for *T {
     fn ne(&self, other: &*T) -> bool { !self.eq(other) }
 }
 
-#[cfg(stage0, not(test))]
-impl<T> Eq for *mut T {
-    #[inline]
-    fn eq(&self, other: &*mut T) -> bool {
-        (*self as uint) == (*other as uint)
-    }
-    #[inline]
-    fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
-}
-
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
 impl<T> Eq for *mut T {
     #[inline]
     fn eq(&self, other: &*mut T) -> bool {
@@ -480,27 +441,7 @@ mod externfnpointers {
 }
 
 // Comparison for pointers
-#[cfg(stage0, not(test))]
-impl<T> Ord for *T {
-    #[inline]
-    fn lt(&self, other: &*T) -> bool {
-        (*self as uint) < (*other as uint)
-    }
-    #[inline]
-    fn le(&self, other: &*T) -> bool {
-        (*self as uint) <= (*other as uint)
-    }
-    #[inline]
-    fn ge(&self, other: &*T) -> bool {
-        (*self as uint) >= (*other as uint)
-    }
-    #[inline]
-    fn gt(&self, other: &*T) -> bool {
-        (*self as uint) > (*other as uint)
-    }
-}
-
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
 impl<T> Ord for *T {
     #[inline]
     fn lt(&self, other: &*T) -> bool {
@@ -520,27 +461,7 @@ impl<T> Ord for *T {
     }
 }
 
-#[cfg(stage0, not(test))]
-impl<T> Ord for *mut T {
-    #[inline]
-    fn lt(&self, other: &*mut T) -> bool {
-        (*self as uint) < (*other as uint)
-    }
-    #[inline]
-    fn le(&self, other: &*mut T) -> bool {
-        (*self as uint) <= (*other as uint)
-    }
-    #[inline]
-    fn ge(&self, other: &*mut T) -> bool {
-        (*self as uint) >= (*other as uint)
-    }
-    #[inline]
-    fn gt(&self, other: &*mut T) -> bool {
-        (*self as uint) > (*other as uint)
-    }
-}
-
-#[cfg(not(stage0), not(test))]
+#[cfg(not(test))]
 impl<T> Ord for *mut T {
     #[inline]
     fn lt(&self, other: &*mut T) -> bool {
diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs
index 1330096ee36..8ca247edb59 100644
--- a/src/libstd/rand.rs
+++ b/src/libstd/rand.rs
@@ -915,7 +915,7 @@ pub fn seed() -> ~[u8] {
 }
 
 // used to make space in TLS for a random number generator
-static tls_rng_state: local_data::Key<@@mut IsaacRng> = &local_data::Key;
+local_data_key!(tls_rng_state: @@mut IsaacRng)
 
 /**
  * Gives back a lazily initialized task-local random number generator,
diff --git a/src/libstd/reflect_stage0.rs b/src/libstd/reflect_stage0.rs
deleted file mode 100644
index 56e0f83e05c..00000000000
--- a/src/libstd/reflect_stage0.rs
+++ /dev/null
@@ -1,493 +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.
-
-/*!
-
-Runtime type reflection
-
-*/
-
-#[allow(missing_doc)];
-
-use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
-use libc::c_void;
-use sys;
-use unstable::raw;
-
-/**
- * Trait for visitor that wishes to reflect on data. To use this, create a
- * struct that encapsulates the set of pointers you wish to walk through a
- * data structure, and implement both `MovePtr` for it as well as `TyVisitor`;
- * then build a MovePtrAdaptor wrapped around your struct.
- */
-pub trait MovePtr {
-    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void);
-    fn push_ptr(&self);
-    fn pop_ptr(&self);
-}
-
-/// Helper function for alignment calculation.
-#[inline]
-pub fn align(size: uint, align: uint) -> uint {
-    ((size + align) - 1u) & !(align - 1u)
-}
-
-/// Adaptor to wrap around visitors implementing MovePtr.
-pub struct MovePtrAdaptor<V> {
-    inner: V
-}
-pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> {
-    MovePtrAdaptor { inner: v }
-}
-
-impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> {
-    #[inline]
-    pub fn bump(&self, sz: uint) {
-        do self.inner.move_ptr() |p| {
-            ((p as uint) + sz) as *c_void
-        };
-    }
-
-    #[inline]
-    pub fn align(&self, a: uint) {
-        do self.inner.move_ptr() |p| {
-            align(p as uint, a) as *c_void
-        };
-    }
-
-    #[inline]
-    pub fn align_to<T>(&self) {
-        self.align(sys::min_align_of::<T>());
-    }
-
-    #[inline]
-    pub fn bump_past<T>(&self) {
-        self.bump(sys::size_of::<T>());
-    }
-}
-
-/// Abstract type-directed pointer-movement using the MovePtr trait
-impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
-    fn visit_bot(&self) -> bool {
-        self.align_to::<()>();
-        if ! self.inner.visit_bot() { return false; }
-        self.bump_past::<()>();
-        true
-    }
-
-    fn visit_nil(&self) -> bool {
-        self.align_to::<()>();
-        if ! self.inner.visit_nil() { return false; }
-        self.bump_past::<()>();
-        true
-    }
-
-    fn visit_bool(&self) -> bool {
-        self.align_to::<bool>();
-        if ! self.inner.visit_bool() { return false; }
-        self.bump_past::<bool>();
-        true
-    }
-
-    fn visit_int(&self) -> bool {
-        self.align_to::<int>();
-        if ! self.inner.visit_int() { return false; }
-        self.bump_past::<int>();
-        true
-    }
-
-    fn visit_i8(&self) -> bool {
-        self.align_to::<i8>();
-        if ! self.inner.visit_i8() { return false; }
-        self.bump_past::<i8>();
-        true
-    }
-
-    fn visit_i16(&self) -> bool {
-        self.align_to::<i16>();
-        if ! self.inner.visit_i16() { return false; }
-        self.bump_past::<i16>();
-        true
-    }
-
-    fn visit_i32(&self) -> bool {
-        self.align_to::<i32>();
-        if ! self.inner.visit_i32() { return false; }
-        self.bump_past::<i32>();
-        true
-    }
-
-    fn visit_i64(&self) -> bool {
-        self.align_to::<i64>();
-        if ! self.inner.visit_i64() { return false; }
-        self.bump_past::<i64>();
-        true
-    }
-
-    fn visit_uint(&self) -> bool {
-        self.align_to::<uint>();
-        if ! self.inner.visit_uint() { return false; }
-        self.bump_past::<uint>();
-        true
-    }
-
-    fn visit_u8(&self) -> bool {
-        self.align_to::<u8>();
-        if ! self.inner.visit_u8() { return false; }
-        self.bump_past::<u8>();
-        true
-    }
-
-    fn visit_u16(&self) -> bool {
-        self.align_to::<u16>();
-        if ! self.inner.visit_u16() { return false; }
-        self.bump_past::<u16>();
-        true
-    }
-
-    fn visit_u32(&self) -> bool {
-        self.align_to::<u32>();
-        if ! self.inner.visit_u32() { return false; }
-        self.bump_past::<u32>();
-        true
-    }
-
-    fn visit_u64(&self) -> bool {
-        self.align_to::<u64>();
-        if ! self.inner.visit_u64() { return false; }
-        self.bump_past::<u64>();
-        true
-    }
-
-    fn visit_float(&self) -> bool {
-        self.align_to::<float>();
-        if ! self.inner.visit_float() { return false; }
-        self.bump_past::<float>();
-        true
-    }
-
-    fn visit_f32(&self) -> bool {
-        self.align_to::<f32>();
-        if ! self.inner.visit_f32() { return false; }
-        self.bump_past::<f32>();
-        true
-    }
-
-    fn visit_f64(&self) -> bool {
-        self.align_to::<f64>();
-        if ! self.inner.visit_f64() { return false; }
-        self.bump_past::<f64>();
-        true
-    }
-
-    fn visit_char(&self) -> bool {
-        self.align_to::<char>();
-        if ! self.inner.visit_char() { return false; }
-        self.bump_past::<char>();
-        true
-    }
-
-    fn visit_estr_box(&self) -> bool {
-        self.align_to::<@str>();
-        if ! self.inner.visit_estr_box() { return false; }
-        self.bump_past::<@str>();
-        true
-    }
-
-    fn visit_estr_uniq(&self) -> bool {
-        self.align_to::<~str>();
-        if ! self.inner.visit_estr_uniq() { return false; }
-        self.bump_past::<~str>();
-        true
-    }
-
-    fn visit_estr_slice(&self) -> bool {
-        self.align_to::<&'static str>();
-        if ! self.inner.visit_estr_slice() { return false; }
-        self.bump_past::<&'static str>();
-        true
-    }
-
-    fn visit_estr_fixed(&self, n: uint,
-                        sz: uint,
-                        align: uint) -> bool {
-        self.align(align);
-        if ! self.inner.visit_estr_fixed(n, sz, align) { return false; }
-        self.bump(sz);
-        true
-    }
-
-    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<@u8>();
-        if ! self.inner.visit_box(mtbl, inner) { return false; }
-        self.bump_past::<@u8>();
-        true
-    }
-
-    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~u8>();
-        if ! self.inner.visit_uniq(mtbl, inner) { return false; }
-        self.bump_past::<~u8>();
-        true
-    }
-
-    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~u8>();
-        if ! self.inner.visit_uniq_managed(mtbl, inner) { return false; }
-        self.bump_past::<~u8>();
-        true
-    }
-
-    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<*u8>();
-        if ! self.inner.visit_ptr(mtbl, inner) { return false; }
-        self.bump_past::<*u8>();
-        true
-    }
-
-    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<&'static u8>();
-        if ! self.inner.visit_rptr(mtbl, inner) { return false; }
-        self.bump_past::<&'static u8>();
-        true
-    }
-
-    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<raw::Vec<()>>();
-        if ! self.inner.visit_vec(mtbl, inner) { return false; }
-        true
-    }
-
-    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~[u8]>();
-        if ! self.inner.visit_vec(mtbl, inner) { return false; }
-        self.bump_past::<~[u8]>();
-        true
-    }
-
-    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<@[u8]>();
-        if ! self.inner.visit_evec_box(mtbl, inner) { return false; }
-        self.bump_past::<@[u8]>();
-        true
-    }
-
-    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~[u8]>();
-        if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
-        self.bump_past::<~[u8]>();
-        true
-    }
-
-    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<~[@u8]>();
-        if ! self.inner.visit_evec_uniq_managed(mtbl, inner) { return false; }
-        self.bump_past::<~[@u8]>();
-        true
-    }
-
-    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.align_to::<&'static [u8]>();
-        if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
-        self.bump_past::<&'static [u8]>();
-        true
-    }
-
-    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
-                        mtbl: uint, inner: *TyDesc) -> bool {
-        self.align(align);
-        if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
-            return false;
-        }
-        self.bump(sz);
-        true
-    }
-
-    fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
-        self.align(align);
-        if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; }
-        true
-    }
-
-    fn visit_rec_field(&self, i: uint, name: &str,
-                       mtbl: uint, inner: *TyDesc) -> bool {
-        unsafe { self.align((*inner).align); }
-        if ! self.inner.visit_rec_field(i, name, mtbl, inner) {
-            return false;
-        }
-        unsafe { self.bump((*inner).size); }
-        true
-    }
-
-    fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
-        if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; }
-        true
-    }
-
-    fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
-                      -> bool {
-        self.align(align);
-        if ! self.inner.visit_enter_class(n_fields, sz, align) {
-            return false;
-        }
-        true
-    }
-
-    fn visit_class_field(&self, i: uint, name: &str,
-                         mtbl: uint, inner: *TyDesc) -> bool {
-        unsafe { self.align((*inner).align); }
-        if ! self.inner.visit_class_field(i, name, mtbl, inner) {
-            return false;
-        }
-        unsafe { self.bump((*inner).size); }
-        true
-    }
-
-    fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
-                      -> bool {
-        if ! self.inner.visit_leave_class(n_fields, sz, align) {
-            return false;
-        }
-        true
-    }
-
-    fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
-        self.align(align);
-        if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; }
-        true
-    }
-
-    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
-        unsafe { self.align((*inner).align); }
-        if ! self.inner.visit_tup_field(i, inner) { return false; }
-        unsafe { self.bump((*inner).size); }
-        true
-    }
-
-    fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
-        if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; }
-        true
-    }
-
-    fn visit_enter_fn(&self, purity: uint, proto: uint,
-                      n_inputs: uint, retstyle: uint) -> bool {
-        if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
-            return false
-        }
-        true
-    }
-
-    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool {
-        if ! self.inner.visit_fn_input(i, mode, inner) { return false; }
-        true
-    }
-
-    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool {
-        if ! self.inner.visit_fn_output(retstyle, inner) { return false; }
-        true
-    }
-
-    fn visit_leave_fn(&self, purity: uint, proto: uint,
-                      n_inputs: uint, retstyle: uint) -> bool {
-        if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) {
-            return false;
-        }
-        true
-    }
-
-    fn visit_enter_enum(&self, n_variants: uint,
-                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                        sz: uint, align: uint)
-                     -> bool {
-        self.align(align);
-        if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) {
-            return false;
-        }
-        true
-    }
-
-    fn visit_enter_enum_variant(&self, variant: uint,
-                                disr_val: int,
-                                n_fields: uint,
-                                name: &str) -> bool {
-        if ! self.inner.visit_enter_enum_variant(variant, disr_val,
-                                                 n_fields, name) {
-            return false;
-        }
-        true
-    }
-
-    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool {
-        self.inner.push_ptr();
-        self.bump(offset);
-        if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; }
-        self.inner.pop_ptr();
-        true
-    }
-
-    fn visit_leave_enum_variant(&self, variant: uint,
-                                disr_val: int,
-                                n_fields: uint,
-                                name: &str) -> bool {
-        if ! self.inner.visit_leave_enum_variant(variant, disr_val,
-                                                 n_fields, name) {
-            return false;
-        }
-        true
-    }
-
-    fn visit_leave_enum(&self, n_variants: uint,
-                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                        sz: uint, align: uint) -> bool {
-        if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
-            return false;
-        }
-        self.bump(sz);
-        true
-    }
-
-    fn visit_trait(&self) -> bool {
-        self.align_to::<@TyVisitor>();
-        if ! self.inner.visit_trait() { return false; }
-        self.bump_past::<@TyVisitor>();
-        true
-    }
-
-    fn visit_param(&self, i: uint) -> bool {
-        if ! self.inner.visit_param(i) { return false; }
-        true
-    }
-
-    fn visit_self(&self) -> bool {
-        self.align_to::<&'static u8>();
-        if ! self.inner.visit_self() { return false; }
-        self.align_to::<&'static u8>();
-        true
-    }
-
-    fn visit_type(&self) -> bool {
-        if ! self.inner.visit_type() { return false; }
-        true
-    }
-
-    fn visit_opaque_box(&self) -> bool {
-        self.align_to::<@u8>();
-        if ! self.inner.visit_opaque_box() { return false; }
-        self.bump_past::<@u8>();
-        true
-    }
-
-    fn visit_closure_ptr(&self, ck: uint) -> bool {
-        self.align_to::<@fn()>();
-        if ! self.inner.visit_closure_ptr(ck) { return false; }
-        self.bump_past::<@fn()>();
-        true
-    }
-}
diff --git a/src/libstd/repr_stage0.rs b/src/libstd/repr_stage0.rs
deleted file mode 100644
index cbce2005141..00000000000
--- a/src/libstd/repr_stage0.rs
+++ /dev/null
@@ -1,626 +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.
-
-/*!
-
-More runtime type reflection
-
-*/
-
-#[allow(missing_doc)];
-
-use cast::transmute;
-use char;
-use container::Container;
-use io::{Writer, WriterUtil};
-use iter::Iterator;
-use libc::c_void;
-use option::{Some, None};
-use ptr;
-use reflect;
-use reflect::{MovePtr, align};
-use str::StrSlice;
-use to_str::ToStr;
-use vec::OwnedVector;
-use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
-use unstable::raw;
-
-#[cfg(test)] use io;
-
-/// Helpers
-
-trait EscapedCharWriter {
-    fn write_escaped_char(&self, ch: char);
-}
-
-impl EscapedCharWriter for @Writer {
-    fn write_escaped_char(&self, ch: char) {
-        match ch {
-            '\t' => self.write_str("\\t"),
-            '\r' => self.write_str("\\r"),
-            '\n' => self.write_str("\\n"),
-            '\\' => self.write_str("\\\\"),
-            '\'' => self.write_str("\\'"),
-            '"' => self.write_str("\\\""),
-            '\x20'..'\x7e' => self.write_char(ch),
-            _ => {
-                do char::escape_unicode(ch) |c| {
-                    self.write_char(c);
-                }
-            }
-        }
-    }
-}
-
-/// Representations
-
-trait Repr {
-    fn write_repr(&self, writer: @Writer);
-}
-
-impl Repr for () {
-    fn write_repr(&self, writer: @Writer) { writer.write_str("()"); }
-}
-
-impl Repr for bool {
-    fn write_repr(&self, writer: @Writer) {
-        writer.write_str(if *self { "true" } else { "false" })
-    }
-}
-
-macro_rules! int_repr(($ty:ident) => (impl Repr for $ty {
-    fn write_repr(&self, writer: @Writer) {
-        do ::$ty::to_str_bytes(*self, 10u) |bits| {
-            writer.write(bits);
-        }
-    }
-}))
-
-int_repr!(int)
-int_repr!(i8)
-int_repr!(i16)
-int_repr!(i32)
-int_repr!(i64)
-int_repr!(uint)
-int_repr!(u8)
-int_repr!(u16)
-int_repr!(u32)
-int_repr!(u64)
-
-macro_rules! num_repr(($ty:ident) => (impl Repr for $ty {
-    fn write_repr(&self, writer: @Writer) {
-        let s = self.to_str();
-        writer.write(s.as_bytes());
-    }
-}))
-
-num_repr!(float)
-num_repr!(f32)
-num_repr!(f64)
-
-// New implementation using reflect::MovePtr
-
-enum VariantState {
-    SearchingFor(int),
-    Matched,
-    AlreadyFound
-}
-
-pub struct ReprVisitor {
-    ptr: @mut *c_void,
-    ptr_stk: @mut ~[*c_void],
-    var_stk: @mut ~[VariantState],
-    writer: @Writer
-}
-pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor {
-    ReprVisitor {
-        ptr: @mut ptr,
-        ptr_stk: @mut ~[],
-        var_stk: @mut ~[],
-        writer: writer,
-    }
-}
-
-impl MovePtr for ReprVisitor {
-    #[inline]
-    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) {
-        *self.ptr = adjustment(*self.ptr);
-    }
-    fn push_ptr(&self) {
-        self.ptr_stk.push(*self.ptr);
-    }
-    fn pop_ptr(&self) {
-        *self.ptr = self.ptr_stk.pop();
-    }
-}
-
-impl ReprVisitor {
-    // Various helpers for the TyVisitor impl
-
-    #[inline]
-    pub fn get<T>(&self, f: &fn(&T)) -> bool {
-        unsafe {
-            f(transmute::<*c_void,&T>(*self.ptr));
-        }
-        true
-    }
-
-    #[inline]
-    pub fn visit_inner(&self, inner: *TyDesc) -> bool {
-        self.visit_ptr_inner(*self.ptr, inner)
-    }
-
-    #[inline]
-    pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
-        unsafe {
-            let u = ReprVisitor(ptr, self.writer);
-            let v = reflect::MovePtrAdaptor(u);
-            visit_tydesc(inner, @v as @TyVisitor);
-            true
-        }
-    }
-
-    #[inline]
-    pub fn write<T:Repr>(&self) -> bool {
-        do self.get |v:&T| {
-            v.write_repr(self.writer);
-        }
-    }
-
-    pub fn write_escaped_slice(&self, slice: &str) {
-        self.writer.write_char('"');
-        for ch in slice.iter() {
-            self.writer.write_escaped_char(ch);
-        }
-        self.writer.write_char('"');
-    }
-
-    pub fn write_mut_qualifier(&self, mtbl: uint) {
-        if mtbl == 0 {
-            self.writer.write_str("mut ");
-        } else if mtbl == 1 {
-            // skip, this is ast::m_imm
-        } else {
-            assert_eq!(mtbl, 2);
-            self.writer.write_str("const ");
-        }
-    }
-
-    pub fn write_vec_range(&self,
-                           _mtbl: uint,
-                           ptr: *(),
-                           len: uint,
-                           inner: *TyDesc)
-                           -> bool {
-        let mut p = ptr as *u8;
-        let (sz, al) = unsafe { ((*inner).size, (*inner).align) };
-        self.writer.write_char('[');
-        let mut first = true;
-        let mut left = len;
-        // unit structs have 0 size, and don't loop forever.
-        let dec = if sz == 0 {1} else {sz};
-        while left > 0 {
-            if first {
-                first = false;
-            } else {
-                self.writer.write_str(", ");
-            }
-            self.visit_ptr_inner(p as *c_void, inner);
-            unsafe {
-                p = align(ptr::offset(p, sz as int) as uint, al) as *u8;
-            }
-            left -= dec;
-        }
-        self.writer.write_char(']');
-        true
-    }
-
-    pub fn write_unboxed_vec_repr(&self,
-                                  mtbl: uint,
-                                  v: &raw::Vec<()>,
-                                  inner: *TyDesc)
-                                  -> bool {
-        self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data),
-                             v.fill, inner)
-    }
-}
-
-impl TyVisitor for ReprVisitor {
-    fn visit_bot(&self) -> bool {
-        self.writer.write_str("!");
-        true
-    }
-    fn visit_nil(&self) -> bool { self.write::<()>() }
-    fn visit_bool(&self) -> bool { self.write::<bool>() }
-    fn visit_int(&self) -> bool { self.write::<int>() }
-    fn visit_i8(&self) -> bool { self.write::<i8>() }
-    fn visit_i16(&self) -> bool { self.write::<i16>() }
-    fn visit_i32(&self) -> bool { self.write::<i32>()  }
-    fn visit_i64(&self) -> bool { self.write::<i64>() }
-
-    fn visit_uint(&self) -> bool { self.write::<uint>() }
-    fn visit_u8(&self) -> bool { self.write::<u8>() }
-    fn visit_u16(&self) -> bool { self.write::<u16>() }
-    fn visit_u32(&self) -> bool { self.write::<u32>() }
-    fn visit_u64(&self) -> bool { self.write::<u64>() }
-
-    fn visit_float(&self) -> bool { self.write::<float>() }
-    fn visit_f32(&self) -> bool { self.write::<f32>() }
-    fn visit_f64(&self) -> bool { self.write::<f64>() }
-
-    fn visit_char(&self) -> bool {
-        do self.get::<char> |&ch| {
-            self.writer.write_char('\'');
-            self.writer.write_escaped_char(ch);
-            self.writer.write_char('\'');
-        }
-    }
-
-    fn visit_estr_box(&self) -> bool {
-        do self.get::<@str> |s| {
-            self.writer.write_char('@');
-            self.write_escaped_slice(*s);
-        }
-    }
-    fn visit_estr_uniq(&self) -> bool {
-        do self.get::<~str> |s| {
-            self.writer.write_char('~');
-            self.write_escaped_slice(*s);
-        }
-    }
-    fn visit_estr_slice(&self) -> bool {
-        do self.get::<&str> |s| {
-            self.write_escaped_slice(*s);
-        }
-    }
-
-    // Type no longer exists, vestigial function.
-    fn visit_estr_fixed(&self, _n: uint, _sz: uint,
-                        _align: uint) -> bool { fail!(); }
-
-    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('@');
-        self.write_mut_qualifier(mtbl);
-        do self.get::<&raw::Box<()>> |b| {
-            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            self.visit_ptr_inner(p, inner);
-        }
-    }
-
-    fn visit_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('~');
-        do self.get::<*c_void> |b| {
-            self.visit_ptr_inner(*b, inner);
-        }
-    }
-
-    fn visit_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('~');
-        do self.get::<&raw::Box<()>> |b| {
-            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            self.visit_ptr_inner(p, inner);
-        }
-    }
-
-    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool {
-        do self.get::<*c_void> |p| {
-            self.writer.write_str(fmt!("(0x%x as *())",
-                                       *p as uint));
-        }
-    }
-
-    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        self.writer.write_char('&');
-        self.write_mut_qualifier(mtbl);
-        do self.get::<*c_void> |p| {
-            self.visit_ptr_inner(*p, inner);
-        }
-    }
-
-    // Type no longer exists, vestigial function.
-    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); }
-
-
-    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<raw::Vec<()>> |b| {
-            self.write_unboxed_vec_repr(mtbl, b, inner);
-        }
-    }
-
-    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<&raw::Box<raw::Vec<()>>> |b| {
-            self.writer.write_char('@');
-            self.write_mut_qualifier(mtbl);
-            self.write_unboxed_vec_repr(mtbl, &b.data, inner);
-        }
-    }
-
-    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<&raw::Vec<()>> |b| {
-            self.writer.write_char('~');
-            self.write_unboxed_vec_repr(mtbl, *b, inner);
-        }
-    }
-
-    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<&raw::Box<raw::Vec<()>>> |b| {
-            self.writer.write_char('~');
-            self.write_unboxed_vec_repr(mtbl, &b.data, inner);
-        }
-    }
-
-    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<raw::Slice<()>> |s| {
-            self.writer.write_char('&');
-            self.write_vec_range(mtbl, s.data, s.len, inner);
-        }
-    }
-
-    fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint,
-                        mtbl: uint, inner: *TyDesc) -> bool {
-        do self.get::<()> |b| {
-            self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner);
-        }
-    }
-
-    fn visit_enter_rec(&self, _n_fields: uint,
-                       _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('{');
-        true
-    }
-
-    fn visit_rec_field(&self, i: uint, name: &str,
-                       mtbl: uint, inner: *TyDesc) -> bool {
-        if i != 0 {
-            self.writer.write_str(", ");
-        }
-        self.write_mut_qualifier(mtbl);
-        self.writer.write_str(name);
-        self.writer.write_str(": ");
-        self.visit_inner(inner);
-        true
-    }
-
-    fn visit_leave_rec(&self, _n_fields: uint,
-                       _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('}');
-        true
-    }
-
-    fn visit_enter_class(&self, _n_fields: uint,
-                         _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('{');
-        true
-    }
-    fn visit_class_field(&self, i: uint, name: &str,
-                         mtbl: uint, inner: *TyDesc) -> bool {
-        if i != 0 {
-            self.writer.write_str(", ");
-        }
-        self.write_mut_qualifier(mtbl);
-        self.writer.write_str(name);
-        self.writer.write_str(": ");
-        self.visit_inner(inner);
-        true
-    }
-    fn visit_leave_class(&self, _n_fields: uint,
-                         _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('}');
-        true
-    }
-
-    fn visit_enter_tup(&self, _n_fields: uint,
-                       _sz: uint, _align: uint) -> bool {
-        self.writer.write_char('(');
-        true
-    }
-    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
-        if i != 0 {
-            self.writer.write_str(", ");
-        }
-        self.visit_inner(inner);
-        true
-    }
-    fn visit_leave_tup(&self, _n_fields: uint,
-                       _sz: uint, _align: uint) -> bool {
-        if _n_fields == 1 {
-            self.writer.write_char(',');
-        }
-        self.writer.write_char(')');
-        true
-    }
-
-    fn visit_enter_enum(&self,
-                        _n_variants: uint,
-                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                        _sz: uint,
-                        _align: uint) -> bool {
-        let var_stk: &mut ~[VariantState] = self.var_stk;
-        let disr = unsafe {
-            get_disr(transmute(*self.ptr))
-        };
-        var_stk.push(SearchingFor(disr));
-        true
-    }
-
-    fn visit_enter_enum_variant(&self, _variant: uint,
-                                disr_val: int,
-                                n_fields: uint,
-                                name: &str) -> bool {
-        let mut write = false;
-        match self.var_stk.pop() {
-            SearchingFor(sought) => {
-                if disr_val == sought {
-                    self.var_stk.push(Matched);
-                    write = true;
-                } else {
-                    self.var_stk.push(SearchingFor(sought));
-                }
-            }
-            Matched | AlreadyFound => {
-                self.var_stk.push(AlreadyFound);
-            }
-        }
-
-        if write {
-            self.writer.write_str(name);
-            if n_fields > 0 {
-                self.writer.write_char('(');
-            }
-        }
-        true
-    }
-
-    fn visit_enum_variant_field(&self,
-                                i: uint,
-                                _offset: uint,
-                                inner: *TyDesc)
-                                -> bool {
-        match self.var_stk[self.var_stk.len() - 1] {
-            Matched => {
-                if i != 0 {
-                    self.writer.write_str(", ");
-                }
-                if ! self.visit_inner(inner) {
-                    return false;
-                }
-            }
-            _ => ()
-        }
-        true
-    }
-
-    fn visit_leave_enum_variant(&self, _variant: uint,
-                                _disr_val: int,
-                                n_fields: uint,
-                                _name: &str) -> bool {
-        match self.var_stk[self.var_stk.len() - 1] {
-            Matched => {
-                if n_fields > 0 {
-                    self.writer.write_char(')');
-                }
-            }
-            _ => ()
-        }
-        true
-    }
-
-    fn visit_leave_enum(&self,
-                        _n_variants: uint,
-                        _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                        _sz: uint,
-                        _align: uint)
-                        -> bool {
-        let var_stk: &mut ~[VariantState] = self.var_stk;
-        match var_stk.pop() {
-            SearchingFor(*) => fail!("enum value matched no variant"),
-            _ => true
-        }
-    }
-
-    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
-                      _n_inputs: uint, _retstyle: uint) -> bool { true }
-    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
-        true
-    }
-    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool {
-        true
-    }
-    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
-                      _n_inputs: uint, _retstyle: uint) -> bool { true }
-
-
-    fn visit_trait(&self) -> bool { true }
-    fn visit_param(&self, _i: uint) -> bool { true }
-    fn visit_self(&self) -> bool { true }
-    fn visit_type(&self) -> bool { true }
-
-    fn visit_opaque_box(&self) -> bool {
-        self.writer.write_char('@');
-        do self.get::<&raw::Box<()>> |b| {
-            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
-            self.visit_ptr_inner(p, b.type_desc);
-        }
-    }
-
-    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
-}
-
-pub fn write_repr<T>(writer: @Writer, object: &T) {
-    unsafe {
-        let ptr = ptr::to_unsafe_ptr(object) as *c_void;
-        let tydesc = get_tydesc::<T>();
-        let u = ReprVisitor(ptr, writer);
-        let v = reflect::MovePtrAdaptor(u);
-        visit_tydesc(tydesc, @v as @TyVisitor)
-    }
-}
-
-#[cfg(test)]
-struct P {a: int, b: float}
-
-#[test]
-fn test_repr() {
-
-    fn exact_test<T>(t: &T, e:&str) {
-        let s : &str = io::with_str_writer(|w| write_repr(w, t));
-        if s != e {
-            error!("expected '%s', got '%s'",
-                   e, s);
-        }
-        assert_eq!(s, e);
-    }
-
-    exact_test(&10, "10");
-    exact_test(&true, "true");
-    exact_test(&false, "false");
-    exact_test(&1.234, "1.234");
-    exact_test(&(&"hello"), "\"hello\"");
-    exact_test(&(@"hello"), "@\"hello\"");
-    exact_test(&(~"he\u10f3llo"), "~\"he\\u10f3llo\"");
-
-    exact_test(&(@10), "@10");
-    exact_test(&(@mut 10), "@10"); // FIXME: #4210: incorrect
-    exact_test(&((@mut 10, 2)), "(@mut 10, 2)");
-    exact_test(&(~10), "~10");
-    exact_test(&(&10), "&10");
-    let mut x = 10;
-    exact_test(&(&mut x), "&mut 10");
-    exact_test(&(@mut [1, 2]), "@mut [1, 2]");
-
-    exact_test(&(1,), "(1,)");
-    exact_test(&(@[1,2,3,4,5,6,7,8]),
-               "@[1, 2, 3, 4, 5, 6, 7, 8]");
-    exact_test(&(@[1u8,2u8,3u8,4u8]),
-               "@[1, 2, 3, 4]");
-    exact_test(&(@["hi", "there"]),
-               "@[\"hi\", \"there\"]");
-    exact_test(&(~["hi", "there"]),
-               "~[\"hi\", \"there\"]");
-    exact_test(&(&["hi", "there"]),
-               "&[\"hi\", \"there\"]");
-    exact_test(&(P{a:10, b:1.234}),
-               "{a: 10, b: 1.234}");
-    exact_test(&(@P{a:10, b:1.234}),
-               "@{a: 10, b: 1.234}");
-    exact_test(&(~P{a:10, b:1.234}),
-               "~{a: 10, b: 1.234}");
-    exact_test(&(10_u8, ~"hello"),
-               "(10, ~\"hello\")");
-    exact_test(&(10_u16, ~"hello"),
-               "(10, ~\"hello\")");
-    exact_test(&(10_u32, ~"hello"),
-               "(10, ~\"hello\")");
-    exact_test(&(10_u64, ~"hello"),
-               "(10, ~\"hello\")");
-
-    struct Foo;
-    exact_test(&(~[Foo, Foo, Foo]), "~[{}, {}, {}]");
-}
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
index afa8d3261fc..d8317c34f50 100644
--- a/src/libstd/rt/args.rs
+++ b/src/libstd/rt/args.rs
@@ -117,18 +117,6 @@ mod imp {
         }
     }
 
-    #[cfg(stage0)]
-    mod macro_hack {
-    #[macro_escape];
-    macro_rules! externfn(
-        (fn $name:ident () $(-> $ret_ty:ty),*) => (
-            extern {
-                fn $name() $(-> $ret_ty),*;
-            }
-        )
-    )
-    }
-
     externfn!(fn rust_take_global_args_lock())
     externfn!(fn rust_drop_global_args_lock())
     externfn!(fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>)
diff --git a/src/libstd/rt/io/buffered.rs b/src/libstd/rt/io/buffered.rs
index 579e581d87e..7988f640687 100644
--- a/src/libstd/rt/io/buffered.rs
+++ b/src/libstd/rt/io/buffered.rs
@@ -126,7 +126,7 @@ impl<R: Reader> Decorator<R> for BufferedReader<R> {
 
 /// Wraps a Writer and buffers output to it
 ///
-/// NOTE: `BufferedWriter` will NOT flush its buffer when dropped.
+/// Note that `BufferedWriter` will NOT flush its buffer when dropped.
 pub struct BufferedWriter<W> {
     priv inner: W,
     priv buf: ~[u8],
@@ -204,7 +204,7 @@ impl<W: Reader> Reader for InternalBufferedWriter<W> {
 
 /// Wraps a Stream and buffers input and output to and from it
 ///
-/// NOTE: `BufferedStream` will NOT flush its output buffer when dropped.
+/// Note that `BufferedStream` will NOT flush its output buffer when dropped.
 // FIXME #9155 this should be a newtype struct
 pub struct BufferedStream<S> {
     priv inner: BufferedReader<InternalBufferedWriter<S>>
diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs
index c24f4eb257e..a884961fd1e 100644
--- a/src/libstd/rt/io/file.rs
+++ b/src/libstd/rt/io/file.rs
@@ -8,17 +8,87 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*! Synchronous File I/O
+
+This module provides a set of functions and traits for working
+with regular files & directories on a filesystem.
+
+At the top-level of the module are a set of freestanding functions,
+associated with various filesystem operations. They all operate
+on a `PathLike` object.
+
+All operations in this module, including those as part of `FileStream` et al
+block the task during execution. Most will raise `std::rt::io::{io_error,read_error}`
+conditions in the event of failure.
+
+Also included in this module are the `FileInfo` and `DirectoryInfo` traits. When
+`use`'d alongside a value whose type implements them (A `std::path::Path` impl is
+a part of this module), they expose a set of functions for operations against
+a given file location, depending on whether the path already exists. Whenever
+possible, the `{FileInfo, DirectoryInfo}` preserve the same semantics as their
+free function counterparts.
+*/
+
 use prelude::*;
 use super::support::PathLike;
 use super::{Reader, Writer, Seek};
-use super::{SeekSet, SeekCur, SeekEnd, SeekStyle};
+use super::{SeekStyle,SeekSet, SeekCur, SeekEnd,
+            Open, Read, Write, Create, ReadWrite};
 use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
 use rt::io::{io_error, read_error, EndOfFile,
-             FileMode, FileAccess, Open, Read, Create, ReadWrite};
+            FileMode, FileAccess, FileStat, IoError,
+            PathAlreadyExists, PathDoesntExist,
+            MismatchedFileTypeForOperation, ignore_io_error};
 use rt::local::Local;
-use rt::test::*;
+use option::{Some, None};
+use path::Path;
+use super::super::test::*;
 
 /// Open a file for reading/writing, as indicated by `path`.
+///
+/// # Example
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::support::PathLike;
+///     use std::rt::io::file::open;
+///     use std::rt::io::{FileMode, FileAccess};
+///
+///     let p = &Path("/some/file/path.txt");
+///
+///     do io_error::cond.trap(|_| {
+///         // hoo-boy...
+///     }).inside {
+///         let stream = match open(p, Create, ReadWrite) {
+///             Some(s) => s,
+///             None => fail!("whoops! I'm sure this raised, anyways..");
+///         }
+///         // do some stuff with that stream
+///
+///         // the file stream will be closed at the end of this block
+///     }
+///     // ..
+///
+/// `FileMode` and `FileAccess` provide information about the permissions
+/// context in which a given stream is created. More information about them
+/// can be found in `std::rt::io`'s docs.
+///
+/// Note that, with this function, a `FileStream` is returned regardless of
+/// the access-limitations indicated by `FileAccess` (e.g. calling `write` on a
+/// `FileStream` opened as `ReadOnly` will raise an `io_error` condition at runtime). If you
+/// desire a more-correctly-constrained interface to files, use the
+/// `{open_stream, open_reader, open_writer}` methods that are a part of `FileInfo`
+///
+/// # Errors
+///
+/// This function will raise an `io_error` condition under a number of different circumstances,
+/// to include but not limited to:
+///
+/// * Opening a file that already exists with `FileMode` of `Create` or vice versa (e.g.
+///   opening a non-existant file with `FileMode` or `Open`)
+/// * Attempting to open a file with a `FileAccess` that the user lacks permissions
+///   for
+/// * Filesystem-level errors (full disk, etc)
 pub fn open<P: PathLike>(path: &P,
                          mode: FileMode,
                          access: FileAccess
@@ -39,8 +109,28 @@ pub fn open<P: PathLike>(path: &P,
     }
 }
 
-/// Unlink (remove) a file from the filesystem, as indicated
-/// by `path`.
+/// Unlink a file from the underlying filesystem.
+///
+/// # Example
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::support::PathLike;
+///     use std::rt::io::file::unlink;
+///
+///     let p = &Path("/some/file/path.txt");
+///     unlink(p);
+///     // if we made it here without failing, then the
+///     // unlink operation was successful
+///
+/// Note that, just because an unlink call was successful, it is not
+/// guaranteed that a file is immediately deleted (e.g. depending on
+/// platform, other open file descriptors may prevent immediate removal)
+///
+/// # Errors
+///
+/// This function will raise an `io_error` condition if the user lacks permissions to
+/// remove the file or if some other filesystem-level error occurs
 pub fn unlink<P: PathLike>(path: &P) {
     let unlink_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
@@ -54,26 +144,231 @@ pub fn unlink<P: PathLike>(path: &P) {
     }
 }
 
-/// Abstraction representing *positional* access to a file. In this case,
-/// *positional* refers to it keeping an encounter *cursor* of where in the
-/// file a subsequent `read` or `write` will begin from. Users of a `FileStream`
-/// can `seek` to move the cursor to a given location *within the bounds of the
-/// file* and can ask to have the `FileStream` `tell` them the location, in
-/// bytes, of the cursor.
+/// Create a new, empty directory at the provided path
+///
+/// # Example
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::support::PathLike;
+///     use std::rt::io::file::mkdir;
+///
+///     let p = &Path("/some/dir");
+///     mkdir(p);
+///     // If we got here, our directory exists! Horray!
+///
+/// # Errors
+///
+/// This call will raise an `io_error` condition if the user lacks permissions to make a
+/// new directory at the provided path, or if the directory already exists
+pub fn mkdir<P: PathLike>(path: &P) {
+    let mkdir_result = unsafe {
+        let io: *mut IoFactoryObject = Local::unsafe_borrow();
+        (*io).fs_mkdir(path)
+    };
+    match mkdir_result {
+        Ok(_) => (),
+        Err(ioerr) => {
+            io_error::cond.raise(ioerr);
+        }
+    }
+}
+
+/// Remove an existing, empty directory
+///
+/// # Example
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::support::PathLike;
+///     use std::rt::io::file::rmdir;
+///
+///     let p = &Path("/some/dir");
+///     rmdir(p);
+///     // good riddance, you mean ol' directory
+///
+/// # Errors
+///
+/// This call will raise an `io_error` condition if the user lacks permissions to remove the
+/// directory at the provided path, or if the directory isn't empty
+pub fn rmdir<P: PathLike>(path: &P) {
+    let rmdir_result = unsafe {
+        let io: *mut IoFactoryObject = Local::unsafe_borrow();
+        (*io).fs_rmdir(path)
+    };
+    match rmdir_result {
+        Ok(_) => (),
+        Err(ioerr) => {
+            io_error::cond.raise(ioerr);
+        }
+    }
+}
+
+/// Get information on the file, directory, etc at the provided path
+///
+/// Given a `rt::io::support::PathLike`, query the file system to get
+/// information about a file, directory, etc.
+///
+/// Returns a `Some(std::rt::io::PathInfo)` on success
+///
+/// # Example
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::support::PathLike;
+///     use std::rt::io::file::stat;
+///
+///     let p = &Path("/some/file/path.txt");
+///
+///     do io_error::cond.trap(|_| {
+///         // hoo-boy...
+///     }).inside {
+///         let info = match stat(p) {
+///             Some(s) => s,
+///             None => fail!("whoops! I'm sure this raised, anyways..");
+///         }
+///         if stat.is_file {
+///             // just imagine the possibilities ...
+///         }
+///
+///         // the file stream will be closed at the end of this block
+///     }
+///     // ..
+///
+/// # Errors
+///
+/// This call will raise an `io_error` condition if the user lacks the requisite
+/// permissions to perform a `stat` call on the given path or if there is no
+/// entry in the filesystem at the provided path.
+pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
+    let open_result = unsafe {
+        let io: *mut IoFactoryObject = Local::unsafe_borrow();
+        (*io).fs_stat(path)
+    };
+    match open_result {
+        Ok(p) => {
+            Some(p)
+        },
+        Err(ioerr) => {
+            io_error::cond.raise(ioerr);
+            None
+        }
+    }
+}
+
+/// Retrieve a vector containing all entries within a provided directory
+///
+/// # Example
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::support::PathLike;
+///     use std::rt::io::file::readdir;
+///
+///     fn visit_dirs(dir: &Path, cb: &fn(&Path)) {
+///         if dir.is_dir() {
+///             let contents = dir.readdir();
+///             for entry in contents.iter() {
+///                 if entry.is_dir() { visit_dirs(entry, cb); }
+///                 else { cb(entry); }
+///             }
+///         }
+///         else { fail!("nope"); }
+///     }
+///
+/// # Errors
+///
+/// Will raise an `io_error` condition if the provided `path` doesn't exist,
+/// the process lacks permissions to view the contents or if the `path` points
+/// at a non-directory file
+pub fn readdir<P: PathLike>(path: &P) -> Option<~[Path]> {
+    let readdir_result = unsafe {
+        let io: *mut IoFactoryObject = Local::unsafe_borrow();
+        (*io).fs_readdir(path, 0)
+    };
+    match readdir_result {
+        Ok(p) => {
+            Some(p)
+        },
+        Err(ioerr) => {
+            io_error::cond.raise(ioerr);
+            None
+        }
+    }
+}
+
+/// Constrained version of `FileStream` that only exposes read-specific operations.
+///
+/// Can be retreived via `FileInfo.open_reader()`.
+pub struct FileReader { priv stream: FileStream }
+
+/// a `std::rt::io::Reader` trait impl for file I/O.
+impl Reader for FileReader {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        self.stream.read(buf)
+    }
+
+    fn eof(&mut self) -> bool {
+        self.stream.eof()
+    }
+}
+
+/// a `std::rt::io::Seek` trait impl for file I/O.
+impl Seek for FileReader {
+    fn tell(&self) -> u64 {
+        self.stream.tell()
+    }
+
+    fn seek(&mut self, pos: i64, style: SeekStyle) {
+        self.stream.seek(pos, style);
+    }
+}
+
+/// Constrained version of `FileStream` that only exposes write-specific operations.
+///
+/// Can be retreived via `FileInfo.open_writer()`.
+pub struct FileWriter { priv stream: FileStream }
+
+/// a `std::rt::io::Writer` trait impl for file I/O.
+impl Writer for FileWriter {
+    fn write(&mut self, buf: &[u8]) {
+        self.stream.write(buf);
+    }
+
+    fn flush(&mut self) {
+        self.stream.flush();
+    }
+}
+
+/// a `std::rt::io::Seek` trait impl for file I/O.
+impl Seek for FileWriter {
+    fn tell(&self) -> u64 {
+        self.stream.tell()
+    }
+
+    fn seek(&mut self, pos: i64, style: SeekStyle) {
+        self.stream.seek(pos, style);
+    }
+}
+
+/// Unconstrained file access type that exposes read and write operations
+///
+/// Can be retreived via `file::open()` and `FileInfo.open_stream()`.
+///
+/// # Errors
 ///
-/// This abstraction is roughly modeled on the access workflow as represented
-/// by `open(2)`, `read(2)`, `write(2)` and friends.
+/// This type will raise an io_error condition if operations are attempted against
+/// it for which its underlying file descriptor was not configured at creation
+/// time, via the `FileAccess` parameter to `file::open()`.
 ///
-/// The `open` and `unlink` static methods are provided to manage creation/removal
-/// of files. All other methods operatin on an instance of `FileStream`.
+/// For this reason, it is best to use the access-constrained wrappers that are
+/// exposed via `FileInfo.open_reader()` and `FileInfo.open_writer()`.
 pub struct FileStream {
     fd: ~RtioFileStream,
     last_nread: int,
 }
 
-impl FileStream {
-}
-
+/// a `std::rt::io::Reader` trait impl for file I/O.
 impl Reader for FileStream {
     fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
         match self.fd.read(buf) {
@@ -99,6 +394,7 @@ impl Reader for FileStream {
     }
 }
 
+/// a `std::rt::io::Writer` trait impl for file I/O.
 impl Writer for FileStream {
     fn write(&mut self, buf: &[u8]) {
         match self.fd.write(buf) {
@@ -119,6 +415,7 @@ impl Writer for FileStream {
     }
 }
 
+/// a `std::rt::io:Seek` trait impl for file I/O.
 impl Seek for FileStream {
     fn tell(&self) -> u64 {
         let res = self.fd.tell();
@@ -145,6 +442,242 @@ impl Seek for FileStream {
     }
 }
 
+/// Shared functionality between `FileInfo` and `DirectoryInfo`
+pub trait FileSystemInfo {
+    /// Get the filesystem path that this instance points at,
+    /// whether it is valid or not. In this way, it can be used to
+    /// to specify a path of a non-existent file which it
+    /// later creates
+    fn get_path<'a>(&'a self) -> &'a Path;
+
+    /// Get information on the file, directory, etc at the provided path
+    ///
+    /// Consult the `file::stat` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with `file::stat`
+    fn stat(&self) -> Option<FileStat> {
+        stat(self.get_path())
+    }
+
+    /// Boolean value indicator whether the underlying file exists on the filesystem
+    ///
+    /// # Errors
+    ///
+    /// Will not raise a condition
+    fn exists(&self) -> bool {
+        match ignore_io_error(|| self.stat()) {
+            Some(_) => true,
+            None => false
+        }
+    }
+
+}
+
+/// Represents a file, whose underlying path may or may not be valid
+///
+/// # Example
+///
+/// * Check if a file exists, reading from it if so
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::file::{FileInfo, FileReader};
+///
+///     let f = &Path("/some/file/path.txt");
+///     if f.exists() {
+///         let reader = f.open_reader(Open);
+///         let mut mem = [0u8, 8*64000];
+///         reader.read(mem);
+///         // ...
+///     }
+///
+/// * Is the given path a file?
+///
+///    let f = get_file_path_from_wherever();
+///    match f.is_file() {
+///        true => doing_something_with_a_file(f),
+///        _ => {}
+///    }
+pub trait FileInfo : FileSystemInfo {
+    /// Whether the underlying implemention (be it a file path,
+    /// or something else) points at a "regular file" on the FS. Will return
+    /// false for paths to non-existent locations or directories or
+    /// other non-regular files (named pipes, etc).
+    ///
+    /// # Errors
+    ///
+    /// Will not raise a condition
+    fn is_file(&self) -> bool {
+        match ignore_io_error(|| self.stat()) {
+            Some(s) => s.is_file,
+            None => false
+        }
+    }
+
+    /// Attempts to open a regular file for reading/writing based
+    /// on provided inputs
+    ///
+    /// See `file::open` for more information on runtime semantics and error conditions
+    fn open_stream(&self, mode: FileMode, access: FileAccess) -> Option<FileStream> {
+        match ignore_io_error(|| self.stat()) {
+            Some(s) => match s.is_file {
+                true => open(self.get_path(), mode, access),
+                false => None
+            },
+            None => open(self.get_path(), mode, access)
+        }
+    }
+
+    /// Attempts to open a regular file in read-only mode, based
+    /// on provided inputs
+    ///
+    /// See `file::open` for more information on runtime semantics and error conditions
+    fn open_reader(&self, mode: FileMode) -> Option<FileReader> {
+        match self.open_stream(mode, Read) {
+            Some(s) => Some(FileReader { stream: s}),
+            None => None
+        }
+    }
+
+    /// Attempts to open a regular file in write-only mode, based
+    /// on provided inputs
+    ///
+    /// See `file::open` for more information on runtime semantics and error conditions
+    fn open_writer(&self, mode: FileMode) -> Option<FileWriter> {
+        match self.open_stream(mode, Write) {
+            Some(s) => Some(FileWriter { stream: s}),
+            None => None
+        }
+    }
+
+    /// Attempt to remove a file from the filesystem
+    ///
+    /// See `file::unlink` for more information on runtime semantics and error conditions
+    fn unlink(&self) {
+        unlink(self.get_path());
+    }
+}
+
+/// `FileSystemInfo` implementation for `Path`s
+impl FileSystemInfo for Path {
+    fn get_path<'a>(&'a self) -> &'a Path { self }
+}
+
+/// `FileInfo` implementation for `Path`s
+impl FileInfo for Path { }
+
+/// Represents a directory, whose underlying path may or may not be valid
+///
+/// # Example
+///
+/// * Check if a directory exists, `mkdir`'ing it if not
+///
+///     use std;
+///     use std::path::Path;
+///     use std::rt::io::file::{DirectoryInfo};
+///
+///     let dir = &Path("/some/dir");
+///     if !dir.exists() {
+///         dir.mkdir();
+///     }
+///
+/// * Is the given path a directory? If so, iterate on its contents
+///
+///     fn visit_dirs(dir: &Path, cb: &fn(&Path)) {
+///         if dir.is_dir() {
+///             let contents = dir.readdir();
+///             for entry in contents.iter() {
+///                 if entry.is_dir() { visit_dirs(entry, cb); }
+///                 else { cb(entry); }
+///             }
+///         }
+///         else { fail!("nope"); }
+///     }
+trait DirectoryInfo : FileSystemInfo {
+    /// Whether the underlying implemention (be it a file path,
+    /// or something else) is pointing at a directory in the underlying FS.
+    /// Will return false for paths to non-existent locations or if the item is
+    /// not a directory (eg files, named pipes, links, etc)
+    ///
+    /// # Errors
+    ///
+    /// Will not raise a condition
+    fn is_dir(&self) -> bool {
+        match ignore_io_error(|| self.stat()) {
+            Some(s) => s.is_dir,
+            None => false
+        }
+    }
+
+    /// Create a directory at the location pointed to by the
+    /// type underlying the given `DirectoryInfo`.
+    ///
+    /// # Errors
+    ///
+    /// This method will raise a `PathAlreadyExists` kind of `io_error` condition
+    /// if the provided path exists
+    ///
+    /// See `file::mkdir` for more information on runtime semantics and error conditions
+    fn mkdir(&self) {
+        match ignore_io_error(|| self.stat()) {
+            Some(_) => {
+                io_error::cond.raise(IoError {
+                    kind: PathAlreadyExists,
+                    desc: "Path already exists",
+                    detail:
+                        Some(fmt!("%s already exists; can't mkdir it", self.get_path().to_str()))
+                })
+            },
+            None => mkdir(self.get_path())
+        }
+    }
+
+    /// Remove a directory at the given location.
+    ///
+    /// # Errors
+    ///
+    /// This method will raise a `PathDoesntExist` kind of `io_error` condition
+    /// if the provided path exists. It will raise a `MismatchedFileTypeForOperation`
+    /// kind of `io_error` condition if the provided path points at any
+    /// non-directory file type
+    ///
+    /// See `file::rmdir` for more information on runtime semantics and error conditions
+    fn rmdir(&self) {
+        match ignore_io_error(|| self.stat()) {
+            Some(s) => {
+                match s.is_dir {
+                    true => rmdir(self.get_path()),
+                    false => {
+                        let ioerr = IoError {
+                            kind: MismatchedFileTypeForOperation,
+                            desc: "Cannot do rmdir() on a non-directory",
+                            detail: Some(fmt!(
+                                "%s is a non-directory; can't rmdir it",
+                                self.get_path().to_str()))
+                        };
+                        io_error::cond.raise(ioerr);
+                    }
+                }
+            },
+            None =>
+                io_error::cond.raise(IoError {
+                    kind: PathDoesntExist,
+                    desc: "Path doesn't exist",
+                    detail: Some(fmt!("%s doesn't exist; can't rmdir it", self.get_path().to_str()))
+                })
+        }
+    }
+
+    // Get a collection of all entries at the given
+    // directory
+    fn readdir(&self) -> Option<~[Path]> {
+        readdir(self.get_path())
+    }
+}
+
+/// `DirectoryInfo` impl for `path::Path`
+impl DirectoryInfo for Path { }
+
 fn file_test_smoke_test_impl() {
     do run_in_mt_newsched_task {
         let message = "it's alright. have a good time";
@@ -273,7 +806,6 @@ fn file_test_io_seek_and_tell_smoke_test() {
 }
 
 fn file_test_io_seek_and_write_impl() {
-    use io;
     do run_in_mt_newsched_task {
         use str;
         let initial_msg =   "food-is-yummy";
@@ -294,7 +826,6 @@ fn file_test_io_seek_and_write_impl() {
         }
         unlink(filename);
         let read_str = str::from_utf8(read_mem);
-        io::println(fmt!("read_str: '%?' final_msg: '%?'", read_str, final_msg));
         assert!(read_str == final_msg.to_owned());
     }
 }
@@ -343,3 +874,111 @@ fn file_test_io_seek_shakedown_impl() {
 fn file_test_io_seek_shakedown() {
     file_test_io_seek_shakedown_impl();
 }
+
+#[test]
+fn file_test_stat_is_correct_on_is_file() {
+    do run_in_mt_newsched_task {
+        let filename = &Path("./tmp/file_stat_correct_on_is_file.txt");
+        {
+            let mut fs = open(filename, Create, ReadWrite).unwrap();
+            let msg = "hw";
+            fs.write(msg.as_bytes());
+        }
+        let stat_res = match stat(filename) {
+            Some(s) => s,
+            None => fail!("shouldn't happen")
+        };
+        assert!(stat_res.is_file);
+        unlink(filename);
+    }
+}
+
+#[test]
+fn file_test_stat_is_correct_on_is_dir() {
+    do run_in_mt_newsched_task {
+        let filename = &Path("./tmp/file_stat_correct_on_is_dir");
+        mkdir(filename);
+        let stat_res = match stat(filename) {
+            Some(s) => s,
+            None => fail!("shouldn't happen")
+        };
+        assert!(stat_res.is_dir);
+        rmdir(filename);
+    }
+}
+
+#[test]
+fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
+    do run_in_mt_newsched_task {
+        let dir = &Path("./tmp/fileinfo_false_on_dir");
+        mkdir(dir);
+        assert!(dir.is_file() == false);
+        rmdir(dir);
+    }
+}
+
+#[test]
+fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
+    do run_in_mt_newsched_task {
+        let file = &Path("./tmp/fileinfo_check_exists_b_and_a.txt");
+        {
+            let msg = "foo".as_bytes();
+            let mut w = file.open_writer(Create);
+            w.write(msg);
+        }
+        assert!(file.exists());
+        file.unlink();
+        assert!(!file.exists());
+    }
+}
+
+#[test]
+fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
+    do run_in_mt_newsched_task {
+        let dir = &Path("./tmp/before_and_after_dir");
+        assert!(!dir.exists());
+        dir.mkdir();
+        assert!(dir.exists());
+        assert!(dir.is_dir());
+        dir.rmdir();
+        assert!(!dir.exists());
+    }
+}
+
+#[test]
+fn file_test_directoryinfo_readdir() {
+    use str;
+    do run_in_mt_newsched_task {
+        let dir = &Path("./tmp/di_readdir");
+        dir.mkdir();
+        let prefix = "foo";
+        for n in range(0,3) {
+            let f = dir.push(fmt!("%d.txt", n));
+            let mut w = f.open_writer(Create);
+            let msg_str = (prefix + n.to_str().to_owned()).to_owned();
+            let msg = msg_str.as_bytes();
+            w.write(msg);
+        }
+        match dir.readdir() {
+            Some(files) => {
+                let mut mem = [0u8, .. 4];
+                for f in files.iter() {
+                    {
+                        let n = f.filestem();
+                        let mut r = f.open_reader(Open);
+                        r.read(mem);
+                        let read_str = str::from_utf8(mem);
+                        let expected = match n {
+                            Some(n) => prefix+n,
+                            None => fail!("really shouldn't happen..")
+                        };
+                        assert!(expected == read_str);
+                    }
+                    f.unlink();
+                }
+            },
+            None => fail!("shouldn't happen")
+        }
+        dir.rmdir();
+    }
+}
\ No newline at end of file
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
index 59ca5d57759..6b405b0948a 100644
--- a/src/libstd/rt/io/mod.rs
+++ b/src/libstd/rt/io/mod.rs
@@ -245,6 +245,7 @@ Out of scope
 use prelude::*;
 use to_str::ToStr;
 use str::{StrSlice, OwnedStr};
+use path::Path;
 
 // Reexports
 pub use self::stdio::stdin;
@@ -259,6 +260,9 @@ pub use self::net::ip::IpAddr;
 pub use self::net::tcp::TcpListener;
 pub use self::net::tcp::TcpStream;
 pub use self::net::udp::UdpStream;
+pub use self::pipe::PipeStream;
+pub use self::pipe::UnboundPipeStream;
+pub use self::process::Process;
 
 // Some extension traits that all Readers and Writers get.
 pub use self::extensions::ReaderUtil;
@@ -268,6 +272,12 @@ pub use self::extensions::WriterByteConversions;
 /// Synchronous, non-blocking file I/O.
 pub mod file;
 
+/// Synchronous, in-memory I/O.
+pub mod pipe;
+
+/// Child process management.
+pub mod process;
+
 /// Synchronous, non-blocking network I/O.
 pub mod net;
 
@@ -357,7 +367,10 @@ pub enum IoErrorKind {
     Closed,
     ConnectionRefused,
     ConnectionReset,
-    BrokenPipe
+    BrokenPipe,
+    PathAlreadyExists,
+    PathDoesntExist,
+    MismatchedFileTypeForOperation
 }
 
 // FIXME: #8242 implementing manually because deriving doesn't work for some reason
@@ -373,7 +386,10 @@ impl ToStr for IoErrorKind {
             Closed => ~"Closed",
             ConnectionRefused => ~"ConnectionRefused",
             ConnectionReset => ~"ConnectionReset",
-            BrokenPipe => ~"BrokenPipe"
+            BrokenPipe => ~"BrokenPipe",
+            PathAlreadyExists => ~"PathAlreadyExists",
+            PathDoesntExist => ~"PathDoesntExist",
+            MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation"
         }
     }
 }
@@ -381,17 +397,25 @@ impl ToStr for IoErrorKind {
 // XXX: Can't put doc comments on macros
 // Raised by `I/O` operations on error.
 condition! {
-    // NOTE: this super::IoError should be IoError
-    // Change this next time the snapshot is updated.
-    pub io_error: super::IoError -> ();
+    pub io_error: IoError -> ();
 }
 
 // XXX: Can't put doc comments on macros
 // Raised by `read` on error
 condition! {
-    // NOTE: this super::IoError should be IoError
-    // Change this next time the snapshot it updated.
-    pub read_error: super::IoError -> ();
+    pub read_error: IoError -> ();
+}
+
+/// Helper for wrapper calls where you want to
+/// ignore any io_errors that might be raised
+pub fn ignore_io_error<T>(cb: &fn() -> T) -> T {
+    do io_error::cond.trap(|_| {
+        // just swallow the error.. downstream users
+        // who can make a decision based on a None result
+        // won't care
+    }).inside {
+        cb()
+    }
 }
 
 pub trait Reader {
@@ -596,3 +620,22 @@ pub enum FileAccess {
     Write,
     ReadWrite
 }
+
+pub struct FileStat {
+    /// A `Path` object containing information about the `PathInfo`'s location
+    path: Path,
+    /// `true` if the file pointed at by the `PathInfo` is a regular file
+    is_file: bool,
+    /// `true` if the file pointed at by the `PathInfo` is a directory
+    is_dir: bool,
+    /// The file pointed at by the `PathInfo`'s size in bytes
+    size: u64,
+    /// The file pointed at by the `PathInfo`'s creation time
+    created: u64,
+    /// The file pointed at by the `PathInfo`'s last-modification time in
+    /// platform-dependent msecs
+    modified: u64,
+    /// The file pointed at by the `PathInfo`'s last-accessd time (e.g. read) in
+    /// platform-dependent msecs
+    accessed: u64,
+}
diff --git a/src/libstd/rt/io/pipe.rs b/src/libstd/rt/io/pipe.rs
new file mode 100644
index 00000000000..7e6c59ffd0b
--- /dev/null
+++ b/src/libstd/rt/io/pipe.rs
@@ -0,0 +1,76 @@
+// 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.
+
+//! Synchronous, in-memory pipes.
+//!
+//! Currently these aren't particularly useful, there only exists bindings
+//! enough so that pipes can be created to child processes.
+
+use prelude::*;
+use super::{Reader, Writer};
+use rt::io::{io_error, read_error, EndOfFile};
+use rt::local::Local;
+use rt::rtio::{RtioPipe, RtioPipeObject, IoFactoryObject, IoFactory};
+use rt::rtio::RtioUnboundPipeObject;
+
+pub struct PipeStream(RtioPipeObject);
+pub struct UnboundPipeStream(~RtioUnboundPipeObject);
+
+impl PipeStream {
+    /// Creates a new pipe initialized, but not bound to any particular
+    /// source/destination
+    pub fn new() -> Option<UnboundPipeStream> {
+        let pipe = unsafe {
+            let io: *mut IoFactoryObject = Local::unsafe_borrow();
+            (*io).pipe_init(false)
+        };
+        match pipe {
+            Ok(p) => Some(UnboundPipeStream(p)),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+
+    pub fn bind(inner: RtioPipeObject) -> PipeStream {
+        PipeStream(inner)
+    }
+}
+
+impl Reader for PipeStream {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        match (**self).read(buf) {
+            Ok(read) => Some(read),
+            Err(ioerr) => {
+                // EOF is indicated by returning None
+                if ioerr.kind != EndOfFile {
+                    read_error::cond.raise(ioerr);
+                }
+                return None;
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for PipeStream {
+    fn write(&mut self, buf: &[u8]) {
+        match (**self).write(buf) {
+            Ok(_) => (),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+            }
+        }
+    }
+
+    fn flush(&mut self) { fail!() }
+}
diff --git a/src/libstd/rt/io/process.rs b/src/libstd/rt/io/process.rs
new file mode 100644
index 00000000000..e92b0d3b7b5
--- /dev/null
+++ b/src/libstd/rt/io/process.rs
@@ -0,0 +1,278 @@
+// 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.
+
+//! Bindings for executing child processes
+
+use prelude::*;
+
+use libc;
+use rt::io;
+use rt::io::io_error;
+use rt::local::Local;
+use rt::rtio::{RtioProcess, RtioProcessObject, IoFactoryObject, IoFactory};
+
+pub struct Process {
+    priv handle: ~RtioProcessObject,
+    io: ~[Option<io::PipeStream>],
+}
+
+/// This configuration describes how a new process should be spawned. This is
+/// translated to libuv's own configuration
+pub struct ProcessConfig<'self> {
+    /// Path to the program to run
+    program: &'self str,
+
+    /// Arguments to pass to the program (doesn't include the program itself)
+    args: &'self [~str],
+
+    /// Optional environment to specify for the program. If this is None, then
+    /// it will inherit the current process's environment.
+    env: Option<&'self [(~str, ~str)]>,
+
+    /// Optional working directory for the new process. If this is None, then
+    /// the current directory of the running process is inherited.
+    cwd: Option<&'self str>,
+
+    /// Any number of streams/file descriptors/pipes may be attached to this
+    /// process. This list enumerates the file descriptors and such for the
+    /// process to be spawned, and the file descriptors inherited will start at
+    /// 0 and go to the length of this array.
+    ///
+    /// Standard file descriptors are:
+    ///
+    ///     0 - stdin
+    ///     1 - stdout
+    ///     2 - stderr
+    io: ~[StdioContainer]
+}
+
+/// Describes what to do with a standard io stream for a child process.
+pub enum StdioContainer {
+    /// This stream will be ignored. This is the equivalent of attaching the
+    /// stream to `/dev/null`
+    Ignored,
+
+    /// The specified file descriptor is inherited for the stream which it is
+    /// specified for.
+    InheritFd(libc::c_int),
+
+    // XXX: these two shouldn't have libuv-specific implementation details
+
+    /// The specified libuv stream is inherited for the corresponding file
+    /// descriptor it is assigned to.
+    // XXX: this needs to be thought out more.
+    //InheritStream(uv::net::StreamWatcher),
+
+    /// Creates a pipe for the specified file descriptor which will be directed
+    /// into the previously-initialized pipe passed in.
+    ///
+    /// The first boolean argument is whether the pipe is readable, and the
+    /// second is whether it is writable. These properties are from the view of
+    /// the *child* process, not the parent process.
+    CreatePipe(io::UnboundPipeStream,
+               bool /* readable */,
+               bool /* writable */),
+}
+
+impl Process {
+    /// Creates a new pipe initialized, but not bound to any particular
+    /// source/destination
+    pub fn new(config: ProcessConfig) -> Option<Process> {
+        let process = unsafe {
+            let io: *mut IoFactoryObject = Local::unsafe_borrow();
+            (*io).spawn(config)
+        };
+        match process {
+            Ok((p, io)) => Some(Process{
+                handle: p,
+                io: io.move_iter().map(|p|
+                    p.map_move(|p| io::PipeStream::bind(p))
+                ).collect()
+            }),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+
+    /// Returns the process id of this child process
+    pub fn id(&self) -> libc::pid_t { self.handle.id() }
+
+    /// Sends the specified signal to the child process, returning whether the
+    /// signal could be delivered or not.
+    ///
+    /// Note that this is purely a wrapper around libuv's `uv_process_kill`
+    /// function.
+    ///
+    /// If the signal delivery fails, then the `io_error` condition is raised on
+    pub fn signal(&mut self, signal: int) {
+        match self.handle.kill(signal) {
+            Ok(()) => {}
+            Err(err) => {
+                io_error::cond.raise(err)
+            }
+        }
+    }
+
+    /// Wait for the child to exit completely, returning the status that it
+    /// exited with. This function will continue to have the same return value
+    /// after it has been called at least once.
+    pub fn wait(&mut self) -> int { self.handle.wait() }
+}
+
+impl Drop for Process {
+    fn drop(&mut self) {
+        // Close all I/O before exiting to ensure that the child doesn't wait
+        // forever to print some text or something similar.
+        for _ in range(0, self.io.len()) {
+            self.io.pop();
+        }
+
+        self.wait();
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+    use super::*;
+
+    use rt::io::{Reader, Writer};
+    use rt::io::pipe::*;
+    use str;
+
+    #[test]
+    #[cfg(unix, not(android))]
+    fn smoke() {
+        let io = ~[];
+        let args = ProcessConfig {
+            program: "/bin/sh",
+            args: [~"-c", ~"true"],
+            env: None,
+            cwd: None,
+            io: io,
+        };
+        let p = Process::new(args);
+        assert!(p.is_some());
+        let mut p = p.unwrap();
+        assert_eq!(p.wait(), 0);
+    }
+
+    #[test]
+    #[cfg(unix, not(android))]
+    fn smoke_failure() {
+        let io = ~[];
+        let args = ProcessConfig {
+            program: "if-this-is-a-binary-then-the-world-has-ended",
+            args: [],
+            env: None,
+            cwd: None,
+            io: io,
+        };
+        let p = Process::new(args);
+        assert!(p.is_some());
+        let mut p = p.unwrap();
+        assert!(p.wait() != 0);
+    }
+
+    #[test]
+    #[cfg(unix, not(android))]
+    fn exit_reported_right() {
+        let io = ~[];
+        let args = ProcessConfig {
+            program: "/bin/sh",
+            args: [~"-c", ~"exit 1"],
+            env: None,
+            cwd: None,
+            io: io,
+        };
+        let p = Process::new(args);
+        assert!(p.is_some());
+        let mut p = p.unwrap();
+        assert_eq!(p.wait(), 1);
+    }
+
+    fn read_all(input: &mut Reader) -> ~str {
+        let mut ret = ~"";
+        let mut buf = [0, ..1024];
+        loop {
+            match input.read(buf) {
+                None | Some(0) => { break }
+                Some(n) => { ret = ret + str::from_utf8(buf.slice_to(n)); }
+            }
+        }
+        return ret;
+    }
+
+    fn run_output(args: ProcessConfig) -> ~str {
+        let p = Process::new(args);
+        assert!(p.is_some());
+        let mut p = p.unwrap();
+        assert!(p.io[0].is_none());
+        assert!(p.io[1].is_some());
+        let ret = read_all(p.io[1].get_mut_ref() as &mut Reader);
+        assert_eq!(p.wait(), 0);
+        return ret;
+    }
+
+    #[test]
+    #[cfg(unix, not(android))]
+    fn stdout_works() {
+        let pipe = PipeStream::new().unwrap();
+        let io = ~[Ignored, CreatePipe(pipe, false, true)];
+        let args = ProcessConfig {
+            program: "/bin/sh",
+            args: [~"-c", ~"echo foobar"],
+            env: None,
+            cwd: None,
+            io: io,
+        };
+        assert_eq!(run_output(args), ~"foobar\n");
+    }
+
+    #[test]
+    #[cfg(unix, not(android))]
+    fn set_cwd_works() {
+        let pipe = PipeStream::new().unwrap();
+        let io = ~[Ignored, CreatePipe(pipe, false, true)];
+        let cwd = Some("/");
+        let args = ProcessConfig {
+            program: "/bin/sh",
+            args: [~"-c", ~"pwd"],
+            env: None,
+            cwd: cwd,
+            io: io,
+        };
+        assert_eq!(run_output(args), ~"/\n");
+    }
+
+    #[test]
+    #[cfg(unix, not(android))]
+    fn stdin_works() {
+        let input = PipeStream::new().unwrap();
+        let output = PipeStream::new().unwrap();
+        let io = ~[CreatePipe(input, true, false),
+                   CreatePipe(output, false, true)];
+        let args = ProcessConfig {
+            program: "/bin/sh",
+            args: [~"-c", ~"read line; echo $line"],
+            env: None,
+            cwd: None,
+            io: io,
+        };
+        let mut p = Process::new(args).expect("didn't create a proces?!");
+        p.io[0].get_mut_ref().write("foobar".as_bytes());
+        p.io[0] = None; // close stdin;
+        let out = read_all(p.io[1].get_mut_ref() as &mut Reader);
+        assert_eq!(p.wait(), 0);
+        assert_eq!(out, ~"foobar\n");
+    }
+}
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 53f62786b62..6df857b8d55 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -198,18 +198,6 @@ pub fn start_on_main_thread(argc: int, argv: **u8, crate_map: *u8, main: ~fn())
     return exit_code;
 }
 
-#[cfg(stage0)]
-mod macro_hack {
-#[macro_escape];
-macro_rules! externfn(
-    (fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
-        extern {
-            fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
-        }
-    )
-)
-}
-
 /// One-time runtime initialization.
 ///
 /// Initializes global state, including frobbing
diff --git a/src/libstd/rt/rc.rs b/src/libstd/rt/rc.rs
index 0a6890f627b..2ba00c3a2fb 100644
--- a/src/libstd/rt/rc.rs
+++ b/src/libstd/rt/rc.rs
@@ -78,17 +78,14 @@ impl<T> Drop for RC<T> {
         assert!(self.refcount() > 0);
 
         unsafe {
-            // FIXME(#4330) Need self by value to get mutability.
-            let this: &mut RC<T> = cast::transmute_mut(self);
-
-            match *this.get_mut_state() {
+            match *self.get_mut_state() {
                 (ref mut count, _) => {
                     *count = *count - 1
                 }
             }
 
-            if this.refcount() == 0 {
-                let _: ~(uint, T) = cast::transmute(this.p);
+            if self.refcount() == 0 {
+                let _: ~(uint, T) = cast::transmute(self.p);
             }
         }
     }
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index c9c402baaf0..ca521c792dc 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -8,17 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use libc;
 use option::*;
 use result::*;
 use libc::c_int;
 
 use rt::io::IoError;
+use super::io::process::ProcessConfig;
 use super::io::net::ip::{IpAddr, SocketAddr};
 use rt::uv::uvio;
 use path::Path;
 use super::io::support::PathLike;
 use super::io::{SeekStyle};
-use super::io::{FileMode, FileAccess};
+use super::io::{FileMode, FileAccess, FileStat};
 
 // XXX: ~object doesn't work currently so these are some placeholder
 // types to use instead
@@ -31,6 +33,9 @@ pub type RtioTcpListenerObject = uvio::UvTcpListener;
 pub type RtioUdpSocketObject = uvio::UvUdpSocket;
 pub type RtioTimerObject = uvio::UvTimer;
 pub type PausibleIdleCallback = uvio::UvPausibleIdleCallback;
+pub type RtioPipeObject = uvio::UvPipeStream;
+pub type RtioUnboundPipeObject = uvio::UvUnboundPipe;
+pub type RtioProcessObject = uvio::UvProcess;
 
 pub trait EventLoop {
     fn run(&mut self);
@@ -74,6 +79,14 @@ pub trait IoFactory {
         -> Result<~RtioFileStream, IoError>;
     fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
     fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError>;
+    fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError>;
+    fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
+    fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
+    fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
+        Result<~[Path], IoError>;
+    fn pipe_init(&mut self, ipc: bool) -> Result<~RtioUnboundPipeObject, IoError>;
+    fn spawn(&mut self, config: ProcessConfig)
+            -> Result<(~RtioProcessObject, ~[Option<RtioPipeObject>]), IoError>;
 }
 
 pub trait RtioTcpListener : RtioSocket {
@@ -130,3 +143,14 @@ pub trait RtioFileStream {
     fn tell(&self) -> Result<u64, IoError>;
     fn flush(&mut self) -> Result<(), IoError>;
 }
+
+pub trait RtioProcess {
+    fn id(&self) -> libc::pid_t;
+    fn kill(&mut self, signal: int) -> Result<(), IoError>;
+    fn wait(&mut self) -> int;
+}
+
+pub trait RtioPipe {
+    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
+    fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
+}
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 09f5ee7febb..09bd89ec94a 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -444,17 +444,10 @@ impl Unwinder {
         }
 
         extern {
-            #[cfg(not(stage0))]
             #[rust_stack]
             fn rust_try(f: extern "C" fn(*c_void, *c_void),
                         code: *c_void,
                         data: *c_void) -> uintptr_t;
-
-            #[cfg(stage0)]
-            #[rust_stack]
-            fn rust_try(f: *u8,
-                        code: *c_void,
-                        data: *c_void) -> uintptr_t;
         }
     }
 
@@ -490,10 +483,10 @@ mod test {
     fn tls() {
         use local_data;
         do run_in_newsched_task() {
-            static key: local_data::Key<@~str> = &local_data::Key;
+            local_data_key!(key: @~str)
             local_data::set(key, @~"data");
             assert!(*local_data::get(key, |k| k.map_move(|k| *k)).unwrap() == ~"data");
-            static key2: local_data::Key<@~str> = &local_data::Key;
+            local_data_key!(key2: @~str)
             local_data::set(key2, @~"data");
             assert!(*local_data::get(key2, |k| k.map_move(|k| *k)).unwrap() == ~"data");
         }
diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs
index e87e2d4b1e4..ada558036cf 100644
--- a/src/libstd/rt/uv/file.rs
+++ b/src/libstd/rt/uv/file.rs
@@ -17,6 +17,7 @@ use rt::uv::uvll;
 use rt::uv::uvll::*;
 use super::super::io::support::PathLike;
 use cast::transmute;
+use libc;
 use libc::{c_int};
 use option::{None, Some, Option};
 
@@ -24,77 +25,230 @@ pub struct FsRequest(*uvll::uv_fs_t);
 impl Request for FsRequest;
 
 pub struct RequestData {
-    complete_cb: Option<FsCallback>,
-    raw_fd: Option<c_int>
+    complete_cb: Option<FsCallback>
 }
 
 impl FsRequest {
-    pub fn new(cb: Option<FsCallback>) -> FsRequest {
+    pub fn new() -> FsRequest {
         let fs_req = unsafe { malloc_req(UV_FS) };
         assert!(fs_req.is_not_null());
         let fs_req: FsRequest = NativeHandle::from_native_handle(fs_req);
-        fs_req.install_req_data(cb);
         fs_req
     }
 
-    fn open_common<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int,
-               cb: Option<FsCallback>) -> int {
-        let complete_cb_ptr = match cb {
-            Some(_) => compl_cb as *u8,
-            None => 0 as *u8
+    pub fn open<P: PathLike>(self, loop_: &Loop, path: &P, flags: int, mode: int,
+               cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
         };
-        let is_sync = cb.is_none();
-        let req = FsRequest::new(cb);
-        let result = path.path_as_str(|p| {
+        path.path_as_str(|p| {
             p.to_c_str().with_ref(|p| unsafe {
             uvll::fs_open(loop_.native_handle(),
-                          req.native_handle(), p, flags, mode, complete_cb_ptr) as int
+                          self.native_handle(), p, flags, mode, complete_cb_ptr)
             })
         });
-        if is_sync { req.cleanup_and_delete(); }
-        result
     }
-    pub fn open<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int,
-               cb: FsCallback) {
-        FsRequest::open_common(loop_, path, flags, mode, Some(cb));
+
+    pub fn open_sync<P: PathLike>(self, loop_: &Loop, path: &P,
+                                  flags: int, mode: int) -> Result<c_int, UvError> {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(None)
+        };
+        let result = path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+            uvll::fs_open(loop_.native_handle(),
+                    self.native_handle(), p, flags, mode, complete_cb_ptr)
+            })
+        });
+        self.sync_cleanup(result)
     }
 
-    pub fn open_sync<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int)
-          -> Result<int, UvError> {
-        let result = FsRequest::open_common(loop_, path, flags, mode, None);
-        sync_cleanup(result)
+    pub fn unlink<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+                uvll::fs_unlink(loop_.native_handle(),
+                              self.native_handle(), p, complete_cb_ptr)
+            })
+        });
     }
 
-    fn unlink_common<P: PathLike>(loop_: &Loop, path: &P, cb: Option<FsCallback>) -> int {
-        let complete_cb_ptr = match cb {
-            Some(_) => compl_cb as *u8,
-            None => 0 as *u8
+    pub fn unlink_sync<P: PathLike>(self, loop_: &Loop, path: &P)
+      -> Result<c_int, UvError> {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(None)
         };
-        let is_sync = cb.is_none();
-        let req = FsRequest::new(cb);
         let result = path.path_as_str(|p| {
             p.to_c_str().with_ref(|p| unsafe {
                 uvll::fs_unlink(loop_.native_handle(),
-                              req.native_handle(), p, complete_cb_ptr) as int
+                              self.native_handle(), p, complete_cb_ptr)
             })
         });
-        if is_sync { req.cleanup_and_delete(); }
-        result
+        self.sync_cleanup(result)
+    }
+
+    pub fn stat<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+                uvll::fs_stat(loop_.native_handle(),
+                              self.native_handle(), p, complete_cb_ptr)
+            })
+        });
+    }
+
+    pub fn write(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        let base_ptr = buf.base as *c_void;
+        let len = buf.len as uint;
+        unsafe {
+            uvll::fs_write(loop_.native_handle(), self.native_handle(),
+                           fd, base_ptr,
+                           len, offset, complete_cb_ptr)
+        };
     }
-    pub fn unlink<P: PathLike>(loop_: &Loop, path: &P, cb: FsCallback) {
-        let result = FsRequest::unlink_common(loop_, path, Some(cb));
-        sync_cleanup(result);
+    pub fn write_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
+          -> Result<c_int, UvError> {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(None)
+        };
+        let base_ptr = buf.base as *c_void;
+        let len = buf.len as uint;
+        let result = unsafe {
+            uvll::fs_write(loop_.native_handle(), self.native_handle(),
+                           fd, base_ptr,
+                           len, offset, complete_cb_ptr)
+        };
+        self.sync_cleanup(result)
+    }
+
+    pub fn read(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        let buf_ptr = buf.base as *c_void;
+        let len = buf.len as uint;
+        unsafe {
+            uvll::fs_read(loop_.native_handle(), self.native_handle(),
+                           fd, buf_ptr,
+                           len, offset, complete_cb_ptr)
+        };
     }
-    pub fn unlink_sync<P: PathLike>(loop_: &Loop, path: &P) -> Result<int, UvError> {
-        let result = FsRequest::unlink_common(loop_, path, None);
-        sync_cleanup(result)
+    pub fn read_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
+          -> Result<c_int, UvError> {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(None)
+        };
+        let buf_ptr = buf.base as *c_void;
+        let len = buf.len as uint;
+        let result = unsafe {
+            uvll::fs_read(loop_.native_handle(), self.native_handle(),
+                           fd, buf_ptr,
+                           len, offset, complete_cb_ptr)
+        };
+        self.sync_cleanup(result)
     }
 
-    pub fn install_req_data(&self, cb: Option<FsCallback>) {
+    pub fn close(self, loop_: &Loop, fd: c_int, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        unsafe {
+            uvll::fs_close(loop_.native_handle(), self.native_handle(),
+                           fd, complete_cb_ptr)
+        };
+    }
+    pub fn close_sync(self, loop_: &Loop, fd: c_int) -> Result<c_int, UvError> {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(None)
+        };
+        let result = unsafe {
+            uvll::fs_close(loop_.native_handle(), self.native_handle(),
+                           fd, complete_cb_ptr)
+        };
+        self.sync_cleanup(result)
+    }
+
+    pub fn mkdir<P: PathLike>(self, loop_: &Loop, path: &P, mode: int, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+            uvll::fs_mkdir(loop_.native_handle(),
+                          self.native_handle(), p, mode, complete_cb_ptr)
+            })
+        });
+    }
+
+    pub fn rmdir<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+            uvll::fs_rmdir(loop_.native_handle(),
+                          self.native_handle(), p, complete_cb_ptr)
+            })
+        });
+    }
+
+    pub fn readdir<P: PathLike>(self, loop_: &Loop, path: &P,
+                                flags: c_int, cb: FsCallback) {
+        let complete_cb_ptr = {
+            let mut me = self;
+            me.req_boilerplate(Some(cb))
+        };
+        path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+            uvll::fs_readdir(loop_.native_handle(),
+                          self.native_handle(), p, flags, complete_cb_ptr)
+            })
+        });
+    }
+
+    // accessors/utility funcs
+    fn sync_cleanup(self, result: c_int)
+          -> Result<c_int, UvError> {
+        self.cleanup_and_delete();
+        match status_to_maybe_uv_error(result as i32) {
+            Some(err) => Err(err),
+            None => Ok(result)
+        }
+    }
+    fn req_boilerplate(&mut self, cb: Option<FsCallback>) -> *u8 {
+        let result = match cb {
+            Some(_) => {
+                compl_cb as *u8
+            },
+            None => 0 as *u8
+        };
+        self.install_req_data(cb);
+        result
+    }
+    pub fn install_req_data(&mut self, cb: Option<FsCallback>) {
         let fs_req = (self.native_handle()) as *uvll::uv_write_t;
         let data = ~RequestData {
-            complete_cb: cb,
-            raw_fd: None
+            complete_cb: cb
         };
         unsafe {
             let data = transmute::<~RequestData, *c_void>(data);
@@ -106,7 +260,7 @@ impl FsRequest {
         unsafe {
             let data = uvll::get_data_for_req((self.native_handle()));
             let data = transmute::<&*c_void, &mut ~RequestData>(&data);
-            return &mut **data;
+            &mut **data
         }
     }
 
@@ -120,6 +274,42 @@ impl FsRequest {
         unsafe { Loop{handle:uvll::get_loop_from_fs_req(self.native_handle())} }
     }
 
+    pub fn get_stat(&self) -> uv_stat_t {
+        let stat = uv_stat_t::new();
+        unsafe { uvll::populate_stat(self.native_handle(), &stat); }
+        stat
+    }
+
+    pub fn get_ptr(&self) -> *libc::c_void {
+        unsafe {
+            uvll::get_ptr_from_fs_req(self.native_handle())
+        }
+    }
+
+    pub fn get_paths(&mut self) -> ~[~str] {
+        use str;
+        let ptr = self.get_ptr();
+        match self.get_result() {
+            n if (n <= 0) => {
+                ~[]
+            },
+            n => {
+                let n_len = n as uint;
+                // we pass in the len that uv tells us is there
+                // for the entries and we don't continue past that..
+                // it appears that sometimes the multistring isn't
+                // correctly delimited and we stray into garbage memory?
+                // in any case, passing Some(n_len) fixes it and ensures
+                // good results
+                let raw_path_strs = unsafe {
+                    str::raw::from_c_multistring(ptr as *libc::c_char, Some(n_len)) };
+                let raw_len = raw_path_strs.len();
+                assert_eq!(raw_len, n_len);
+                raw_path_strs
+            }
+        }
+    }
+
     fn cleanup_and_delete(self) {
         unsafe {
             let data = uvll::get_data_for_req(self.native_handle());
@@ -148,97 +338,6 @@ fn sync_cleanup(result: int)
     }
 }
 
-pub struct FileDescriptor(c_int);
-
-impl FileDescriptor {
-    fn new(fd: c_int) -> FileDescriptor {
-        FileDescriptor(fd)
-    }
-
-
-    pub fn from_open_req(req: &mut FsRequest) -> FileDescriptor {
-        FileDescriptor::new(req.get_result())
-    }
-
-    // as per bnoordhuis in #libuv: offset >= 0 uses prwrite instead of write
-    fn write_common(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: Option<FsCallback>)
-          -> int {
-        let complete_cb_ptr = match cb {
-            Some(_) => compl_cb as *u8,
-            None => 0 as *u8
-        };
-        let is_sync = cb.is_none();
-        let mut req = FsRequest::new(cb);
-        let base_ptr = buf.base as *c_void;
-        let len = buf.len as uint;
-        req.get_req_data().raw_fd = Some(self.native_handle());
-        let result = unsafe {
-            uvll::fs_write(loop_.native_handle(), req.native_handle(),
-                           self.native_handle(), base_ptr,
-                           len, offset, complete_cb_ptr) as int
-        };
-        if is_sync { req.cleanup_and_delete(); }
-        result
-    }
-    pub fn write(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: FsCallback) {
-        self.write_common(loop_, buf, offset, Some(cb));
-    }
-    pub fn write_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
-          -> Result<int, UvError> {
-        let result = self.write_common(loop_, buf, offset, None);
-        sync_cleanup(result)
-    }
-
-    fn read_common(&mut self, loop_: &Loop, buf: Buf,
-                   offset: i64, cb: Option<FsCallback>)
-          -> int {
-        let complete_cb_ptr = match cb {
-            Some(_) => compl_cb as *u8,
-            None => 0 as *u8
-        };
-        let is_sync = cb.is_none();
-        let mut req = FsRequest::new(cb);
-        req.get_req_data().raw_fd = Some(self.native_handle());
-        let buf_ptr = buf.base as *c_void;
-        let result = unsafe {
-            uvll::fs_read(loop_.native_handle(), req.native_handle(),
-                           self.native_handle(), buf_ptr,
-                           buf.len as uint, offset, complete_cb_ptr) as int
-        };
-        if is_sync { req.cleanup_and_delete(); }
-        result
-    }
-    pub fn read(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: FsCallback) {
-        self.read_common(loop_, buf, offset, Some(cb));
-    }
-    pub fn read_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
-          -> Result<int, UvError> {
-        let result = self.read_common(loop_, buf, offset, None);
-        sync_cleanup(result)
-    }
-
-    fn close_common(self, loop_: &Loop, cb: Option<FsCallback>) -> int {
-        let complete_cb_ptr = match cb {
-            Some(_) => compl_cb as *u8,
-            None => 0 as *u8
-        };
-        let is_sync = cb.is_none();
-        let req = FsRequest::new(cb);
-        let result = unsafe {
-            uvll::fs_close(loop_.native_handle(), req.native_handle(),
-                           self.native_handle(), complete_cb_ptr) as int
-        };
-        if is_sync { req.cleanup_and_delete(); }
-        result
-    }
-    pub fn close(self, loop_: &Loop, cb: FsCallback) {
-        self.close_common(loop_, Some(cb));
-    }
-    pub fn close_sync(self, loop_: &Loop) -> Result<int, UvError> {
-        let result = self.close_common(loop_, None);
-        sync_cleanup(result)
-    }
-}
 extern fn compl_cb(req: *uv_fs_t) {
     let mut req: FsRequest = NativeHandle::from_native_handle(req);
     // pull the user cb out of the req data
@@ -261,15 +360,7 @@ extern fn compl_cb(req: *uv_fs_t) {
     req.cleanup_and_delete();
 }
 
-impl NativeHandle<c_int> for FileDescriptor {
-    fn from_native_handle(handle: c_int) -> FileDescriptor {
-        FileDescriptor(handle)
-    }
-    fn native_handle(&self) -> c_int {
-        match self { &FileDescriptor(ptr) => ptr }
-    }
-}
-
+#[cfg(test)]
 mod test {
     use super::*;
     //use rt::test::*;
@@ -279,11 +370,11 @@ mod test {
     use unstable::run_in_bare_thread;
     use path::Path;
     use rt::uv::{Loop, Buf, slice_to_uv_buf};
-    use libc::{O_CREAT, O_RDWR, O_RDONLY,
-               S_IWUSR, S_IRUSR}; //NOTE: need defs for S_**GRP|S_**OTH in libc:: ...
-               //S_IRGRP, S_IROTH};
+    use libc::{c_int, O_CREAT, O_RDWR, O_RDONLY,
+               S_IWUSR, S_IRUSR};
 
-    fn file_test_full_simple_impl() {
+    #[test]
+    fn file_test_full_simple() {
         do run_in_bare_thread {
             let mut loop_ = Loop::new();
             let create_flags = O_RDWR | O_CREAT;
@@ -302,25 +393,27 @@ mod test {
             let read_buf = slice_to_uv_buf(read_mem);
             let read_buf_ptr: *Buf = &read_buf;
             let p = Path(path_str);
-            do FsRequest::open(&loop_, &p, create_flags as int, mode as int)
+            let open_req = FsRequest::new();
+            do open_req.open(&loop_, &p, create_flags as int, mode as int)
             |req, uverr| {
                 assert!(uverr.is_none());
-                let mut fd = FileDescriptor::from_open_req(req);
-                let raw_fd = fd.native_handle();
+                let fd = req.get_result();
                 let buf = unsafe { *write_buf_ptr };
-                do fd.write(&req.get_loop(), buf, -1) |req, uverr| {
-                    let fd = FileDescriptor(raw_fd);
-                    do fd.close(&req.get_loop()) |req, _| {
-                        let loop_ = req.get_loop();
+                let write_req = FsRequest::new();
+                do write_req.write(&req.get_loop(), fd, buf, -1) |req, uverr| {
+                    let close_req = FsRequest::new();
+                    do close_req.close(&req.get_loop(), fd) |req, _| {
                         assert!(uverr.is_none());
-                        do FsRequest::open(&loop_, &Path(path_str), read_flags as int,0)
+                        let loop_ = req.get_loop();
+                        let open_req = FsRequest::new();
+                        do open_req.open(&loop_, &Path(path_str), read_flags as int,0)
                             |req, uverr| {
                             assert!(uverr.is_none());
                             let loop_ = req.get_loop();
-                            let mut fd = FileDescriptor::from_open_req(req);
-                            let raw_fd = fd.native_handle();
+                            let fd = req.get_result();
                             let read_buf = unsafe { *read_buf_ptr };
-                            do fd.read(&loop_, read_buf, 0) |req, uverr| {
+                            let read_req = FsRequest::new();
+                            do read_req.read(&loop_, fd, read_buf, 0) |req, uverr| {
                                 assert!(uverr.is_none());
                                 let loop_ = req.get_loop();
                                 // we know nread >=0 because uverr is none..
@@ -334,15 +427,17 @@ mod test {
                                                 read_buf.base, nread))
                                     };
                                     assert!(read_str == ~"hello");
-                                    do FileDescriptor(raw_fd).close(&loop_) |req,uverr| {
+                                    let close_req = FsRequest::new();
+                                    do close_req.close(&loop_, fd) |req,uverr| {
                                         assert!(uverr.is_none());
                                         let loop_ = &req.get_loop();
-                                        do FsRequest::unlink(loop_, &Path(path_str))
+                                        let unlink_req = FsRequest::new();
+                                        do unlink_req.unlink(loop_, &Path(path_str))
                                         |_,uverr| {
                                             assert!(uverr.is_none());
                                         };
                                     };
-                                }
+                                };
                             };
                         };
                     };
@@ -352,7 +447,9 @@ mod test {
             loop_.close();
         }
     }
-    fn file_test_full_simple_impl_sync() {
+
+    #[test]
+    fn file_test_full_simple_sync() {
         do run_in_bare_thread {
             // setup
             let mut loop_ = Loop::new();
@@ -368,26 +465,31 @@ mod test {
             let write_val = "hello".as_bytes().to_owned();
             let write_buf = slice_to_uv_buf(write_val);
             // open/create
-            let result = FsRequest::open_sync(&loop_, &Path(path_str),
+            let open_req = FsRequest::new();
+            let result = open_req.open_sync(&loop_, &Path(path_str),
                                                    create_flags as int, mode as int);
             assert!(result.is_ok());
-            let mut fd = FileDescriptor(result.unwrap() as i32);
+            let fd = result.unwrap();
             // write
-            let result = fd.write_sync(&loop_, write_buf, -1);
+            let write_req = FsRequest::new();
+            let result = write_req.write_sync(&loop_, fd, write_buf, -1);
             assert!(result.is_ok());
             // close
-            let result = fd.close_sync(&loop_);
+            let close_req = FsRequest::new();
+            let result = close_req.close_sync(&loop_, fd);
             assert!(result.is_ok());
             // re-open
-            let result = FsRequest::open_sync(&loop_, &Path(path_str),
+            let open_req = FsRequest::new();
+            let result = open_req.open_sync(&loop_, &Path(path_str),
                                                    read_flags as int,0);
             assert!(result.is_ok());
             let len = 1028;
-            let mut fd = FileDescriptor(result.unwrap() as i32);
+            let fd = result.unwrap();
             // read
             let read_mem: ~[u8] = vec::from_elem(len, 0u8);
             let buf = slice_to_uv_buf(read_mem);
-            let result = fd.read_sync(&loop_, buf, 0);
+            let read_req = FsRequest::new();
+            let result = read_req.read_sync(&loop_, fd, buf, 0);
             assert!(result.is_ok());
             let nread = result.unwrap();
             // nread == 0 would be EOF.. we know it's >= zero because otherwise
@@ -397,31 +499,23 @@ mod test {
                     read_mem.slice(0, nread as uint));
                 assert!(read_str == ~"hello");
                 // close
-                let result = fd.close_sync(&loop_);
+                let close_req = FsRequest::new();
+                let result = close_req.close_sync(&loop_, fd);
                 assert!(result.is_ok());
                 // unlink
-                let result = FsRequest::unlink_sync(&loop_, &Path(path_str));
+                let unlink_req = FsRequest::new();
+                let result = unlink_req.unlink_sync(&loop_, &Path(path_str));
                 assert!(result.is_ok());
             } else { fail!("nread was 0.. wudn't expectin' that."); }
             loop_.close();
         }
     }
 
-    #[test]
-    fn file_test_full_simple() {
-        file_test_full_simple_impl();
-    }
-
-    #[test]
-    fn file_test_full_simple_sync() {
-        file_test_full_simple_impl_sync();
-    }
-
     fn naive_print(loop_: &Loop, input: &str) {
-        let mut stdout = FileDescriptor(STDOUT_FILENO);
         let write_val = input.as_bytes();
         let write_buf = slice_to_uv_buf(write_val);
-        stdout.write_sync(loop_, write_buf, -1);
+        let write_req = FsRequest::new();
+        write_req.write_sync(loop_, STDOUT_FILENO, write_buf, -1);
     }
 
     #[test]
@@ -433,4 +527,130 @@ mod test {
             loop_.close();
         };
     }
+    #[test]
+    fn file_test_stat_simple() {
+        do run_in_bare_thread {
+            let mut loop_ = Loop::new();
+            let path = "./tmp/file_test_stat_simple.txt";
+            let create_flags = O_RDWR |
+                O_CREAT;
+            let mode = S_IWUSR |
+                S_IRUSR;
+            let write_val = "hello".as_bytes().to_owned();
+            let write_buf  = slice_to_uv_buf(write_val);
+            let write_buf_ptr: *Buf = &write_buf;
+            let open_req = FsRequest::new();
+            do open_req.open(&loop_, &path, create_flags as int, mode as int)
+            |req, uverr| {
+                assert!(uverr.is_none());
+                let fd = req.get_result();
+                let buf = unsafe { *write_buf_ptr };
+                let write_req = FsRequest::new();
+                do write_req.write(&req.get_loop(), fd, buf, 0) |req, uverr| {
+                    assert!(uverr.is_none());
+                    let loop_ = req.get_loop();
+                    let stat_req = FsRequest::new();
+                    do stat_req.stat(&loop_, &path) |req, uverr| {
+                        assert!(uverr.is_none());
+                        let loop_ = req.get_loop();
+                        let stat = req.get_stat();
+                        let sz: uint = stat.st_size as uint;
+                        assert!(sz > 0);
+                        let close_req = FsRequest::new();
+                        do close_req.close(&loop_, fd) |req, uverr| {
+                            assert!(uverr.is_none());
+                            let loop_ = req.get_loop();
+                            let unlink_req = FsRequest::new();
+                            do unlink_req.unlink(&loop_, &path) |req,uverr| {
+                                assert!(uverr.is_none());
+                                let loop_ = req.get_loop();
+                                let stat_req = FsRequest::new();
+                                do stat_req.stat(&loop_, &path) |_, uverr| {
+                                    // should cause an error because the
+                                    // file doesn't exist anymore
+                                    assert!(uverr.is_some());
+                                };
+                            };
+                        };
+                    };
+                };
+            };
+            loop_.run();
+            loop_.close();
+        }
+    }
+
+    #[test]
+    fn file_test_mk_rm_dir() {
+        do run_in_bare_thread {
+            let mut loop_ = Loop::new();
+            let path = "./tmp/mk_rm_dir";
+            let mode = S_IWUSR |
+                S_IRUSR;
+            let mkdir_req = FsRequest::new();
+            do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
+                assert!(uverr.is_none());
+                let loop_ = req.get_loop();
+                let stat_req = FsRequest::new();
+                do stat_req.stat(&loop_, &path) |req, uverr| {
+                    assert!(uverr.is_none());
+                    let loop_ = req.get_loop();
+                    let stat = req.get_stat();
+                    naive_print(&loop_, fmt!("%?", stat));
+                    assert!(stat.is_dir());
+                    let rmdir_req = FsRequest::new();
+                    do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
+                        assert!(uverr.is_none());
+                        let loop_ = req.get_loop();
+                        let stat_req = FsRequest::new();
+                        do stat_req.stat(&loop_, &path) |req, uverr| {
+                            assert!(uverr.is_some());
+                        }
+                    }
+                }
+            }
+            loop_.run();
+            loop_.close();
+        }
+    }
+    #[test]
+    fn file_test_mkdir_chokes_on_double_create() {
+        do run_in_bare_thread {
+            let mut loop_ = Loop::new();
+            let path = "./tmp/double_create_dir";
+            let mode = S_IWUSR |
+                S_IRUSR;
+            let mkdir_req = FsRequest::new();
+            do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
+                assert!(uverr.is_none());
+                let loop_ = req.get_loop();
+                let mkdir_req = FsRequest::new();
+                do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
+                    assert!(uverr.is_some());
+                    let loop_ = req.get_loop();
+                    let stat = req.get_stat();
+                    let rmdir_req = FsRequest::new();
+                    do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
+                        assert!(uverr.is_none());
+                        let loop_ = req.get_loop();
+                    }
+                }
+            }
+            loop_.run();
+            loop_.close();
+        }
+    }
+    #[test]
+    fn file_test_rmdir_chokes_on_nonexistant_path() {
+        do run_in_bare_thread {
+            let mut loop_ = Loop::new();
+            let path = "./tmp/never_existed_dir";
+            let rmdir_req = FsRequest::new();
+            do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
+                assert!(uverr.is_some());
+            }
+            loop_.run();
+            loop_.close();
+        }
+    }
 }
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs
index 451d454d2d8..95b2059d538 100644
--- a/src/libstd/rt/uv/mod.rs
+++ b/src/libstd/rt/uv/mod.rs
@@ -58,6 +58,8 @@ pub use self::net::{StreamWatcher, TcpWatcher, UdpWatcher};
 pub use self::idle::IdleWatcher;
 pub use self::timer::TimerWatcher;
 pub use self::async::AsyncWatcher;
+pub use self::process::Process;
+pub use self::pipe::Pipe;
 
 /// The implementation of `rtio` for libuv
 pub mod uvio;
@@ -71,6 +73,8 @@ pub mod idle;
 pub mod timer;
 pub mod async;
 pub mod addrinfo;
+pub mod process;
+pub mod pipe;
 
 /// XXX: Loop(*handle) is buggy with destructors. Normal structs
 /// with dtors may not be destructured, but tuple structs can,
@@ -127,6 +131,8 @@ pub type NullCallback = ~fn();
 pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
 pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
 pub type FsCallback = ~fn(&mut FsRequest, Option<UvError>);
+// first int is exit_status, second is term_signal
+pub type ExitCallback = ~fn(Process, int, int, Option<UvError>);
 pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
 pub type AsyncCallback = ~fn(AsyncWatcher, Option<UvError>);
 pub type UdpReceiveCallback = ~fn(UdpWatcher, int, Buf, SocketAddr, uint, Option<UvError>);
@@ -145,7 +151,8 @@ struct WatcherData {
     timer_cb: Option<TimerCallback>,
     async_cb: Option<AsyncCallback>,
     udp_recv_cb: Option<UdpReceiveCallback>,
-    udp_send_cb: Option<UdpSendCallback>
+    udp_send_cb: Option<UdpSendCallback>,
+    exit_cb: Option<ExitCallback>,
 }
 
 pub trait WatcherInterop {
@@ -177,7 +184,8 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
                 timer_cb: None,
                 async_cb: None,
                 udp_recv_cb: None,
-                udp_send_cb: None
+                udp_send_cb: None,
+                exit_cb: None,
             };
             let data = transmute::<~WatcherData, *c_void>(data);
             uvll::set_data_for_uv_handle(self.native_handle(), data);
diff --git a/src/libstd/rt/uv/pipe.rs b/src/libstd/rt/uv/pipe.rs
new file mode 100644
index 00000000000..1147c731a60
--- /dev/null
+++ b/src/libstd/rt/uv/pipe.rs
@@ -0,0 +1,66 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use prelude::*;
+use libc;
+
+use rt::uv;
+use rt::uv::net;
+use rt::uv::uvll;
+
+pub struct Pipe(*uvll::uv_pipe_t);
+
+impl uv::Watcher for Pipe {}
+
+impl Pipe {
+    pub fn new(loop_: &uv::Loop, ipc: bool) -> Pipe {
+        unsafe {
+            let handle = uvll::malloc_handle(uvll::UV_NAMED_PIPE);
+            assert!(handle.is_not_null());
+            let ipc = ipc as libc::c_int;
+            assert_eq!(uvll::pipe_init(loop_.native_handle(), handle, ipc), 0);
+            let mut ret: Pipe =
+                    uv::NativeHandle::from_native_handle(handle);
+            ret.install_watcher_data();
+            ret
+        }
+    }
+
+    pub fn as_stream(&self) -> net::StreamWatcher {
+        net::StreamWatcher(**self as *uvll::uv_stream_t)
+    }
+
+    pub fn close(self, cb: uv::NullCallback) {
+        {
+            let mut this = self;
+            let data = this.get_watcher_data();
+            assert!(data.close_cb.is_none());
+            data.close_cb = Some(cb);
+        }
+
+        unsafe { uvll::close(self.native_handle(), close_cb); }
+
+        extern fn close_cb(handle: *uvll::uv_pipe_t) {
+            let mut process: Pipe = uv::NativeHandle::from_native_handle(handle);
+            process.get_watcher_data().close_cb.take_unwrap()();
+            process.drop_watcher_data();
+            unsafe { uvll::free_handle(handle as *libc::c_void) }
+        }
+    }
+}
+
+impl uv::NativeHandle<*uvll::uv_pipe_t> for Pipe {
+    fn from_native_handle(handle: *uvll::uv_pipe_t) -> Pipe {
+        Pipe(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_pipe_t {
+        match self { &Pipe(ptr) => ptr }
+    }
+}
diff --git a/src/libstd/rt/uv/process.rs b/src/libstd/rt/uv/process.rs
new file mode 100644
index 00000000000..ccfa1ff87db
--- /dev/null
+++ b/src/libstd/rt/uv/process.rs
@@ -0,0 +1,219 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use prelude::*;
+use cell::Cell;
+use libc;
+use ptr;
+use util;
+use vec;
+
+use rt::io::process::*;
+use rt::uv;
+use rt::uv::uvio::UvPipeStream;
+use rt::uv::uvll;
+
+/// A process wraps the handle of the underlying uv_process_t.
+pub struct Process(*uvll::uv_process_t);
+
+impl uv::Watcher for Process {}
+
+impl Process {
+    /// Creates a new process, ready to spawn inside an event loop
+    pub fn new() -> Process {
+        let handle = unsafe { uvll::malloc_handle(uvll::UV_PROCESS) };
+        assert!(handle.is_not_null());
+        let mut ret: Process = uv::NativeHandle::from_native_handle(handle);
+        ret.install_watcher_data();
+        return ret;
+    }
+
+    /// Spawn a new process inside the specified event loop.
+    ///
+    /// The `config` variable will be passed down to libuv, and the `exit_cb`
+    /// will be run only once, when the process exits.
+    ///
+    /// Returns either the corresponding process object or an error which
+    /// occurred.
+    pub fn spawn(&mut self, loop_: &uv::Loop, mut config: ProcessConfig,
+                 exit_cb: uv::ExitCallback)
+                    -> Result<~[Option<UvPipeStream>], uv::UvError>
+    {
+        let cwd = config.cwd.map_move(|s| s.to_c_str());
+
+        extern fn on_exit(p: *uvll::uv_process_t,
+                          exit_status: libc::c_int,
+                          term_signal: libc::c_int) {
+            let mut p: Process = uv::NativeHandle::from_native_handle(p);
+            let err = match exit_status {
+                0 => None,
+                _ => uv::status_to_maybe_uv_error(-1)
+            };
+            p.get_watcher_data().exit_cb.take_unwrap()(p,
+                                                       exit_status as int,
+                                                       term_signal as int,
+                                                       err);
+        }
+
+        let io = util::replace(&mut config.io, ~[]);
+        let mut stdio = vec::with_capacity::<uvll::uv_stdio_container_t>(io.len());
+        let mut ret_io = vec::with_capacity(io.len());
+        unsafe {
+            vec::raw::set_len(&mut stdio, io.len());
+            for (slot, other) in stdio.iter().zip(io.move_iter()) {
+                let io = set_stdio(slot as *uvll::uv_stdio_container_t, other);
+                ret_io.push(io);
+            }
+        }
+
+        let exit_cb = Cell::new(exit_cb);
+        let ret_io = Cell::new(ret_io);
+        do with_argv(config.program, config.args) |argv| {
+            do with_env(config.env) |envp| {
+                let options = uvll::uv_process_options_t {
+                    exit_cb: on_exit,
+                    file: unsafe { *argv },
+                    args: argv,
+                    env: envp,
+                    cwd: match cwd {
+                        Some(ref cwd) => cwd.with_ref(|p| p),
+                        None => ptr::null(),
+                    },
+                    flags: 0,
+                    stdio_count: stdio.len() as libc::c_int,
+                    stdio: stdio.as_imm_buf(|p, _| p),
+                    uid: 0,
+                    gid: 0,
+                };
+
+                match unsafe {
+                    uvll::spawn(loop_.native_handle(), **self, options)
+                } {
+                    0 => {
+                        (*self).get_watcher_data().exit_cb = Some(exit_cb.take());
+                        Ok(ret_io.take())
+                    }
+                    err => Err(uv::UvError(err))
+                }
+            }
+        }
+    }
+
+    /// Sends a signal to this process.
+    ///
+    /// This is a wrapper around `uv_process_kill`
+    pub fn kill(&self, signum: int) -> Result<(), uv::UvError> {
+        match unsafe {
+            uvll::process_kill(self.native_handle(), signum as libc::c_int)
+        } {
+            0 => Ok(()),
+            err => Err(uv::UvError(err))
+        }
+    }
+
+    /// Returns the process id of a spawned process
+    pub fn pid(&self) -> libc::pid_t {
+        unsafe { uvll::process_pid(**self) as libc::pid_t }
+    }
+
+    /// Closes this handle, invoking the specified callback once closed
+    pub fn close(self, cb: uv::NullCallback) {
+        {
+            let mut this = self;
+            let data = this.get_watcher_data();
+            assert!(data.close_cb.is_none());
+            data.close_cb = Some(cb);
+        }
+
+        unsafe { uvll::close(self.native_handle(), close_cb); }
+
+        extern fn close_cb(handle: *uvll::uv_process_t) {
+            let mut process: Process = uv::NativeHandle::from_native_handle(handle);
+            process.get_watcher_data().close_cb.take_unwrap()();
+            process.drop_watcher_data();
+            unsafe { uvll::free_handle(handle as *libc::c_void) }
+        }
+    }
+}
+
+unsafe fn set_stdio(dst: *uvll::uv_stdio_container_t,
+                    io: StdioContainer) -> Option<UvPipeStream> {
+    match io {
+        Ignored => {
+            uvll::set_stdio_container_flags(dst, uvll::STDIO_IGNORE);
+            None
+        }
+        InheritFd(fd) => {
+            uvll::set_stdio_container_flags(dst, uvll::STDIO_INHERIT_FD);
+            uvll::set_stdio_container_fd(dst, fd);
+            None
+        }
+        CreatePipe(pipe, readable, writable) => {
+            let mut flags = uvll::STDIO_CREATE_PIPE as libc::c_int;
+            if readable {
+                flags |= uvll::STDIO_READABLE_PIPE as libc::c_int;
+            }
+            if writable {
+                flags |= uvll::STDIO_WRITABLE_PIPE as libc::c_int;
+            }
+            let handle = pipe.pipe.as_stream().native_handle();
+            uvll::set_stdio_container_flags(dst, flags);
+            uvll::set_stdio_container_stream(dst, handle);
+            Some(pipe.bind())
+        }
+    }
+}
+
+/// Converts the program and arguments to the argv array expected by libuv
+fn with_argv<T>(prog: &str, args: &[~str], f: &fn(**libc::c_char) -> T) -> T {
+    // First, allocation space to put all the C-strings (we need to have
+    // ownership of them somewhere
+    let mut c_strs = vec::with_capacity(args.len() + 1);
+    c_strs.push(prog.to_c_str());
+    for arg in args.iter() {
+        c_strs.push(arg.to_c_str());
+    }
+
+    // Next, create the char** array
+    let mut c_args = vec::with_capacity(c_strs.len() + 1);
+    for s in c_strs.iter() {
+        c_args.push(s.with_ref(|p| p));
+    }
+    c_args.push(ptr::null());
+    c_args.as_imm_buf(|buf, _| f(buf))
+}
+
+/// Converts the environment to the env array expected by libuv
+fn with_env<T>(env: Option<&[(~str, ~str)]>, f: &fn(**libc::c_char) -> T) -> T {
+    let env = match env {
+        Some(s) => s,
+        None => { return f(ptr::null()); }
+    };
+    // As with argv, create some temporary storage and then the actual array
+    let mut envp = vec::with_capacity(env.len());
+    for &(ref key, ref value) in env.iter() {
+        envp.push(fmt!("%s=%s", *key, *value).to_c_str());
+    }
+    let mut c_envp = vec::with_capacity(envp.len() + 1);
+    for s in envp.iter() {
+        c_envp.push(s.with_ref(|p| p));
+    }
+    c_envp.push(ptr::null());
+    c_envp.as_imm_buf(|buf, _| f(buf))
+}
+
+impl uv::NativeHandle<*uvll::uv_process_t> for Process {
+    fn from_native_handle(handle: *uvll::uv_process_t) -> Process {
+        Process(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_process_t {
+        match self { &Process(ptr) => ptr }
+    }
+}
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index f3b97441e8e..ed6e16c8fdb 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -13,7 +13,7 @@ use cast::transmute;
 use cast;
 use cell::Cell;
 use clone::Clone;
-use libc::{c_int, c_uint, c_void};
+use libc::{c_int, c_uint, c_void, pid_t};
 use ops::Drop;
 use option::*;
 use ptr;
@@ -22,6 +22,8 @@ use result::*;
 use rt::io::IoError;
 use rt::io::net::ip::{SocketAddr, IpAddr};
 use rt::io::{standard_error, OtherIoError, SeekStyle, SeekSet, SeekCur, SeekEnd};
+use rt::io::process::ProcessConfig;
+use rt::kill::BlockedTask;
 use rt::local::Local;
 use rt::rtio::*;
 use rt::sched::{Scheduler, SchedHandle};
@@ -32,11 +34,13 @@ use rt::uv::idle::IdleWatcher;
 use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
 use rt::uv::addrinfo::GetAddrInfoRequest;
 use unstable::sync::Exclusive;
+use path::Path;
 use super::super::io::support::PathLike;
 use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
-          S_IRUSR, S_IWUSR};
+          S_IRUSR, S_IWUSR, S_IRWXU};
 use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create,
-            CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite};
+             CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite,
+             FileStat};
 use task;
 
 #[cfg(test)] use container::Container;
@@ -188,11 +192,7 @@ impl UvEventLoop {
 
 impl Drop for UvEventLoop {
     fn drop(&mut self) {
-        // XXX: Need mutable finalizer
-        let this = unsafe {
-            transmute::<&UvEventLoop, &mut UvEventLoop>(self)
-        };
-        this.uvio.uv_loop().close();
+        self.uvio.uv_loop().close();
     }
 }
 
@@ -411,6 +411,36 @@ impl UvIoFactory {
     }
 }
 
+/// Helper for a variety of simple uv_fs_* functions that
+/// have no ret val
+fn uv_fs_helper<P: PathLike>(loop_: &mut Loop, path: &P,
+                             cb: ~fn(&mut FsRequest, &mut Loop, &P,
+                                     ~fn(&FsRequest, Option<UvError>)))
+        -> Result<(), IoError> {
+    let result_cell = Cell::new_empty();
+    let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
+    let path_cell = Cell::new(path);
+    do task::unkillable { // FIXME(#8674)
+        let scheduler: ~Scheduler = Local::take();
+        let mut new_req = FsRequest::new();
+        do scheduler.deschedule_running_task_and_then |_, task| {
+            let task_cell = Cell::new(task);
+            let path = path_cell.take();
+            do cb(&mut new_req, loop_, path) |_, err| {
+                let res = match err {
+                    None => Ok(()),
+                    Some(err) => Err(uv_error_to_io_error(err))
+                };
+                unsafe { (*result_cell_ptr).put_back(res); }
+                let scheduler: ~Scheduler = Local::take();
+                scheduler.resume_blocked_task_immediately(task_cell.take());
+            };
+        }
+    }
+    assert!(!result_cell.is_empty());
+    return result_cell.take();
+}
+
 impl IoFactory for UvIoFactory {
     // Connect to an address and return a new stream
     // NB: This blocks the task waiting on the connection.
@@ -516,7 +546,6 @@ impl IoFactory for UvIoFactory {
 
     fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream {
         let loop_ = Loop {handle: self.uv_loop().native_handle()};
-        let fd = file::FileDescriptor(fd);
         let home = get_handle_to_current_scheduler!();
         ~UvFileStream::new(loop_, fd, close_on_drop, home) as ~RtioFileStream
     }
@@ -547,15 +576,16 @@ impl IoFactory for UvIoFactory {
         let path_cell = Cell::new(path);
         do task::unkillable { // FIXME(#8674)
             let scheduler: ~Scheduler = Local::take();
+            let open_req = file::FsRequest::new();
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 let path = path_cell.take();
-                do file::FsRequest::open(self.uv_loop(), path, flags as int, create_mode as int)
+                do open_req.open(self.uv_loop(), path, flags as int, create_mode as int)
                       |req,err| {
                     if err.is_none() {
                         let loop_ = Loop {handle: req.get_loop().native_handle()};
                         let home = get_handle_to_current_scheduler!();
-                        let fd = file::FileDescriptor(req.get_result());
+                        let fd = req.get_result() as c_int;
                         let fs = ~UvFileStream::new(
                             loop_, fd, true, home) as ~RtioFileStream;
                         let res = Ok(fs);
@@ -570,31 +600,56 @@ impl IoFactory for UvIoFactory {
                     }
                 };
             };
-        }
+        };
         assert!(!result_cell.is_empty());
         return result_cell.take();
     }
 
     fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
+        do uv_fs_helper(self.uv_loop(), path) |unlink_req, l, p, cb| {
+            do unlink_req.unlink(l, p) |req, err| {
+                cb(req, err)
+            };
+        }
+    }
+    fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError> {
+        use str::StrSlice;
         let result_cell = Cell::new_empty();
-        let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
+        let result_cell_ptr: *Cell<Result<FileStat,
+                                           IoError>> = &result_cell;
         let path_cell = Cell::new(path);
         do task::unkillable { // FIXME(#8674)
             let scheduler: ~Scheduler = Local::take();
+            let stat_req = file::FsRequest::new();
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 let path = path_cell.take();
-                do file::FsRequest::unlink(self.uv_loop(), path) |_, err| {
+                let path_str = path.path_as_str(|p| p.to_owned());
+                do stat_req.stat(self.uv_loop(), path)
+                      |req,err| {
                     let res = match err {
-                        None => Ok(()),
-                        Some(err) => Err(uv_error_to_io_error(err))
+                        None => {
+                            let stat = req.get_stat();
+                            Ok(FileStat {
+                                path: Path(path_str),
+                                is_file: stat.is_file(),
+                                is_dir: stat.is_dir(),
+                                size: stat.st_size,
+                                created: stat.st_ctim.tv_sec as u64,
+                                modified: stat.st_mtim.tv_sec as u64,
+                                accessed: stat.st_atim.tv_sec as u64
+                            })
+                        },
+                        Some(e) => {
+                            Err(uv_error_to_io_error(e))
+                        }
                     };
                     unsafe { (*result_cell_ptr).put_back(res); }
                     let scheduler: ~Scheduler = Local::take();
                     scheduler.resume_blocked_task_immediately(task_cell.take());
                 };
             };
-        }
+        };
         assert!(!result_cell.is_empty());
         return result_cell.take();
     }
@@ -629,6 +684,117 @@ impl IoFactory for UvIoFactory {
         assert!(!result_cell.is_empty());
         return result_cell.take();
     }
+    fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
+        let mode = S_IRWXU as int;
+        do uv_fs_helper(self.uv_loop(), path) |mkdir_req, l, p, cb| {
+            do mkdir_req.mkdir(l, p, mode as int) |req, err| {
+                cb(req, err)
+            };
+        }
+    }
+    fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
+        do uv_fs_helper(self.uv_loop(), path) |rmdir_req, l, p, cb| {
+            do rmdir_req.rmdir(l, p) |req, err| {
+                cb(req, err)
+            };
+        }
+    }
+    fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
+        Result<~[Path], IoError> {
+        use str::StrSlice;
+        let result_cell = Cell::new_empty();
+        let result_cell_ptr: *Cell<Result<~[Path],
+                                           IoError>> = &result_cell;
+        let path_cell = Cell::new(path);
+        do task::unkillable { // FIXME(#8674)
+            let scheduler: ~Scheduler = Local::take();
+            let stat_req = file::FsRequest::new();
+            do scheduler.deschedule_running_task_and_then |_, task| {
+                let task_cell = Cell::new(task);
+                let path = path_cell.take();
+                let path_str = path.path_as_str(|p| p.to_owned());
+                do stat_req.readdir(self.uv_loop(), path, flags)
+                      |req,err| {
+                    let res = match err {
+                        None => {
+                            let rel_paths = req.get_paths();
+                            let mut paths = ~[];
+                            for r in rel_paths.iter() {
+                                paths.push(Path(path_str+"/"+*r));
+                            }
+                            Ok(paths)
+                        },
+                        Some(e) => {
+                            Err(uv_error_to_io_error(e))
+                        }
+                    };
+                    unsafe { (*result_cell_ptr).put_back(res); }
+                    let scheduler: ~Scheduler = Local::take();
+                    scheduler.resume_blocked_task_immediately(task_cell.take());
+                };
+            };
+        };
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
+
+    fn pipe_init(&mut self, ipc: bool) -> Result<~RtioUnboundPipeObject, IoError> {
+        let home = get_handle_to_current_scheduler!();
+        Ok(~UvUnboundPipe { pipe: Pipe::new(self.uv_loop(), ipc), home: home })
+    }
+
+    fn spawn(&mut self, config: ProcessConfig)
+            -> Result<(~RtioProcessObject, ~[Option<RtioPipeObject>]), IoError>
+    {
+        // Sadly, we must create the UvProcess before we actually call uv_spawn
+        // so that the exit_cb can close over it and notify it when the process
+        // has exited.
+        let mut ret = ~UvProcess {
+            process: Process::new(),
+            home: None,
+            exit_status: None,
+            term_signal: None,
+            exit_error: None,
+            descheduled: None,
+        };
+        let ret_ptr = unsafe {
+            *cast::transmute::<&~UvProcess, &*mut UvProcess>(&ret)
+        };
+
+        // The purpose of this exit callback is to record the data about the
+        // exit and then wake up the task which may be waiting for the process
+        // to exit. This is all performed in the current io-loop, and the
+        // implementation of UvProcess ensures that reading these fields always
+        // occurs on the current io-loop.
+        let exit_cb: ExitCallback = |_, exit_status, term_signal, error| {
+            unsafe {
+                assert!((*ret_ptr).exit_status.is_none());
+                (*ret_ptr).exit_status = Some(exit_status);
+                (*ret_ptr).term_signal = Some(term_signal);
+                (*ret_ptr).exit_error = error;
+                match (*ret_ptr).descheduled.take() {
+                    Some(task) => {
+                        let scheduler: ~Scheduler = Local::take();
+                        scheduler.resume_blocked_task_immediately(task);
+                    }
+                    None => {}
+                }
+            }
+        };
+
+        match ret.process.spawn(self.uv_loop(), config, exit_cb) {
+            Ok(io) => {
+                // Only now do we actually get a handle to this scheduler.
+                ret.home = Some(get_handle_to_current_scheduler!());
+                Ok((ret, io))
+            }
+            Err(uverr) => {
+                // We still need to close the process handle we created, but
+                // that's taken care for us in the destructor of UvProcess
+                Err(uv_error_to_io_error(uverr))
+            }
+        }
+    }
 }
 
 pub struct UvTcpListener {
@@ -648,9 +814,7 @@ impl UvTcpListener {
 
 impl Drop for UvTcpListener {
     fn drop(&mut self) {
-        // XXX need mutable finalizer
-        let self_ = unsafe { transmute::<&UvTcpListener, &mut UvTcpListener>(self) };
-        do self_.home_for_io_with_sched |self_, scheduler| {
+        do self.home_for_io_with_sched |self_, scheduler| {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task = Cell::new(task);
                 do self_.watcher.as_stream().close {
@@ -752,6 +916,126 @@ impl RtioTcpAcceptor for UvTcpAcceptor {
     }
 }
 
+fn read_stream(mut watcher: StreamWatcher,
+               scheduler: ~Scheduler,
+               buf: &mut [u8]) -> Result<uint, IoError> {
+    let result_cell = Cell::new_empty();
+    let result_cell_ptr: *Cell<Result<uint, IoError>> = &result_cell;
+
+    let buf_ptr: *&mut [u8] = &buf;
+    do scheduler.deschedule_running_task_and_then |_sched, task| {
+        let task_cell = Cell::new(task);
+        // XXX: We shouldn't reallocate these callbacks every
+        // call to read
+        let alloc: AllocCallback = |_| unsafe {
+            slice_to_uv_buf(*buf_ptr)
+        };
+        do watcher.read_start(alloc) |mut watcher, nread, _buf, status| {
+
+            // Stop reading so that no read callbacks are
+            // triggered before the user calls `read` again.
+            // XXX: Is there a performance impact to calling
+            // stop here?
+            watcher.read_stop();
+
+            let result = if status.is_none() {
+                assert!(nread >= 0);
+                Ok(nread as uint)
+            } else {
+                Err(uv_error_to_io_error(status.unwrap()))
+            };
+
+            unsafe { (*result_cell_ptr).put_back(result); }
+
+            let scheduler: ~Scheduler = Local::take();
+            scheduler.resume_blocked_task_immediately(task_cell.take());
+        }
+    }
+
+    assert!(!result_cell.is_empty());
+    result_cell.take()
+}
+
+fn write_stream(mut watcher: StreamWatcher,
+                scheduler: ~Scheduler,
+                buf: &[u8]) -> Result<(), IoError> {
+    let result_cell = Cell::new_empty();
+    let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
+    let buf_ptr: *&[u8] = &buf;
+    do scheduler.deschedule_running_task_and_then |_, task| {
+        let task_cell = Cell::new(task);
+        let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
+        do watcher.write(buf) |_watcher, status| {
+            let result = if status.is_none() {
+                Ok(())
+            } else {
+                Err(uv_error_to_io_error(status.unwrap()))
+            };
+
+            unsafe { (*result_cell_ptr).put_back(result); }
+
+            let scheduler: ~Scheduler = Local::take();
+            scheduler.resume_blocked_task_immediately(task_cell.take());
+        }
+    }
+
+    assert!(!result_cell.is_empty());
+    result_cell.take()
+}
+
+pub struct UvUnboundPipe {
+    pipe: Pipe,
+    home: SchedHandle,
+}
+
+impl HomingIO for UvUnboundPipe {
+    fn home<'r>(&'r mut self) -> &'r mut SchedHandle { &mut self.home }
+}
+
+impl Drop for UvUnboundPipe {
+    fn drop(&mut self) {
+        do self.home_for_io |self_| {
+            let scheduler: ~Scheduler = Local::take();
+            do scheduler.deschedule_running_task_and_then |_, task| {
+                let task_cell = Cell::new(task);
+                do self_.pipe.close {
+                    let scheduler: ~Scheduler = Local::take();
+                    scheduler.resume_blocked_task_immediately(task_cell.take());
+                }
+            }
+        }
+    }
+}
+
+impl UvUnboundPipe {
+    pub unsafe fn bind(~self) -> UvPipeStream {
+        UvPipeStream { inner: self }
+    }
+}
+
+pub struct UvPipeStream {
+    priv inner: ~UvUnboundPipe,
+}
+
+impl UvPipeStream {
+    pub fn new(inner: ~UvUnboundPipe) -> UvPipeStream {
+        UvPipeStream { inner: inner }
+    }
+}
+
+impl RtioPipe for UvPipeStream {
+    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
+        do self.inner.home_for_io_with_sched |self_, scheduler| {
+            read_stream(self_.pipe.as_stream(), scheduler, buf)
+        }
+    }
+    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
+        do self.inner.home_for_io_with_sched |self_, scheduler| {
+            write_stream(self_.pipe.as_stream(), scheduler, buf)
+        }
+    }
+}
+
 pub struct UvTcpStream {
     watcher: TcpWatcher,
     home: SchedHandle,
@@ -763,9 +1047,7 @@ impl HomingIO for UvTcpStream {
 
 impl Drop for UvTcpStream {
     fn drop(&mut self) {
-        // XXX need mutable finalizer
-        let this = unsafe { transmute::<&UvTcpStream, &mut UvTcpStream>(self) };
-        do this.home_for_io_with_sched |self_, scheduler| {
+        do self.home_for_io_with_sched |self_, scheduler| {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 do self_.watcher.as_stream().close {
@@ -788,70 +1070,13 @@ impl RtioSocket for UvTcpStream {
 impl RtioTcpStream for UvTcpStream {
     fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
         do self.home_for_io_with_sched |self_, scheduler| {
-            let result_cell = Cell::new_empty();
-            let result_cell_ptr: *Cell<Result<uint, IoError>> = &result_cell;
-
-            let buf_ptr: *&mut [u8] = &buf;
-            do scheduler.deschedule_running_task_and_then |_sched, task| {
-                let task_cell = Cell::new(task);
-                // XXX: We shouldn't reallocate these callbacks every
-                // call to read
-                let alloc: AllocCallback = |_| unsafe {
-                    slice_to_uv_buf(*buf_ptr)
-                };
-                let mut watcher = self_.watcher.as_stream();
-                do watcher.read_start(alloc) |mut watcher, nread, _buf, status| {
-
-                    // Stop reading so that no read callbacks are
-                    // triggered before the user calls `read` again.
-                    // XXX: Is there a performance impact to calling
-                    // stop here?
-                    watcher.read_stop();
-
-                    let result = if status.is_none() {
-                        assert!(nread >= 0);
-                        Ok(nread as uint)
-                    } else {
-                        Err(uv_error_to_io_error(status.unwrap()))
-                    };
-
-                    unsafe { (*result_cell_ptr).put_back(result); }
-
-                    let scheduler: ~Scheduler = Local::take();
-                    scheduler.resume_blocked_task_immediately(task_cell.take());
-                }
-            }
-
-            assert!(!result_cell.is_empty());
-            result_cell.take()
+            read_stream(self_.watcher.as_stream(), scheduler, buf)
         }
     }
 
     fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
         do self.home_for_io_with_sched |self_, scheduler| {
-            let result_cell = Cell::new_empty();
-            let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
-            let buf_ptr: *&[u8] = &buf;
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                let task_cell = Cell::new(task);
-                let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
-                let mut watcher = self_.watcher.as_stream();
-                do watcher.write(buf) |_watcher, status| {
-                    let result = if status.is_none() {
-                        Ok(())
-                    } else {
-                        Err(uv_error_to_io_error(status.unwrap()))
-                    };
-
-                    unsafe { (*result_cell_ptr).put_back(result); }
-
-                    let scheduler: ~Scheduler = Local::take();
-                    scheduler.resume_blocked_task_immediately(task_cell.take());
-                }
-            }
-
-            assert!(!result_cell.is_empty());
-            result_cell.take()
+            write_stream(self_.watcher.as_stream(), scheduler, buf)
         }
     }
 
@@ -922,9 +1147,7 @@ impl HomingIO for UvUdpSocket {
 
 impl Drop for UvUdpSocket {
     fn drop(&mut self) {
-        // XXX need mutable finalizer
-        let this = unsafe { transmute::<&UvUdpSocket, &mut UvUdpSocket>(self) };
-        do this.home_for_io_with_sched |self_, scheduler| {
+        do self.home_for_io_with_sched |self_, scheduler| {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
                 do self_.watcher.close {
@@ -1140,8 +1363,7 @@ impl UvTimer {
 
 impl Drop for UvTimer {
     fn drop(&mut self) {
-        let self_ = unsafe { transmute::<&UvTimer, &mut UvTimer>(self) };
-        do self_.home_for_io_with_sched |self_, scheduler| {
+        do self.home_for_io_with_sched |self_, scheduler| {
             rtdebug!("closing UvTimer");
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
@@ -1173,7 +1395,7 @@ impl RtioTimer for UvTimer {
 
 pub struct UvFileStream {
     loop_: Loop,
-    fd: file::FileDescriptor,
+    fd: c_int,
     close_on_drop: bool,
     home: SchedHandle
 }
@@ -1183,7 +1405,7 @@ impl HomingIO for UvFileStream {
 }
 
 impl UvFileStream {
-    fn new(loop_: Loop, fd: file::FileDescriptor, close_on_drop: bool,
+    fn new(loop_: Loop, fd: c_int, close_on_drop: bool,
            home: SchedHandle) -> UvFileStream {
         UvFileStream {
             loop_: loop_,
@@ -1200,7 +1422,8 @@ impl UvFileStream {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
                 let task_cell = Cell::new(task);
-                do self_.fd.read(&self_.loop_, buf, offset) |req, uverr| {
+                let read_req = file::FsRequest::new();
+                do read_req.read(&self_.loop_, self_.fd, buf, offset) |req, uverr| {
                     let res = match uverr  {
                         None => Ok(req.get_result() as int),
                         Some(err) => Err(uv_error_to_io_error(err))
@@ -1221,7 +1444,8 @@ impl UvFileStream {
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
                 let task_cell = Cell::new(task);
-                do self_.fd.write(&self_.loop_, buf, offset) |_, uverr| {
+                let write_req = file::FsRequest::new();
+                do write_req.write(&self_.loop_, self_.fd, buf, offset) |_, uverr| {
                     let res = match uverr  {
                         None => Ok(()),
                         Some(err) => Err(uv_error_to_io_error(err))
@@ -1238,7 +1462,7 @@ impl UvFileStream {
         Result<u64, IoError>{
         #[fixed_stack_segment]; #[inline(never)];
         unsafe {
-            match lseek((*self.fd), pos as off_t, whence) {
+            match lseek(self.fd, pos as off_t, whence) {
                 -1 => {
                     Err(IoError {
                         kind: OtherIoError,
@@ -1254,12 +1478,12 @@ impl UvFileStream {
 
 impl Drop for UvFileStream {
     fn drop(&mut self) {
-        let self_ = unsafe { transmute::<&UvFileStream, &mut UvFileStream>(self) };
         if self.close_on_drop {
-            do self_.home_for_io_with_sched |self_, scheduler| {
+            do self.home_for_io_with_sched |self_, scheduler| {
                 do scheduler.deschedule_running_task_and_then |_, task| {
                     let task_cell = Cell::new(task);
-                    do self_.fd.close(&self.loop_) |_,_| {
+                    let close_req = file::FsRequest::new();
+                    do close_req.close(&self_.loop_, self_.fd) |_,_| {
                         let scheduler: ~Scheduler = Local::take();
                         scheduler.resume_blocked_task_immediately(task_cell.take());
                     };
@@ -1302,6 +1526,86 @@ impl RtioFileStream for UvFileStream {
     }
 }
 
+pub struct UvProcess {
+    process: process::Process,
+
+    // Sadly, this structure must be created before we return it, so in that
+    // brief interim the `home` is None.
+    home: Option<SchedHandle>,
+
+    // All None until the process exits (exit_error may stay None)
+    priv exit_status: Option<int>,
+    priv term_signal: Option<int>,
+    priv exit_error: Option<UvError>,
+
+    // Used to store which task to wake up from the exit_cb
+    priv descheduled: Option<BlockedTask>,
+}
+
+impl HomingIO for UvProcess {
+    fn home<'r>(&'r mut self) -> &'r mut SchedHandle { self.home.get_mut_ref() }
+}
+
+impl Drop for UvProcess {
+    fn drop(&mut self) {
+        let close = |self_: &mut UvProcess| {
+            let scheduler: ~Scheduler = Local::take();
+            do scheduler.deschedule_running_task_and_then |_, task| {
+                let task = Cell::new(task);
+                do self_.process.close {
+                    let scheduler: ~Scheduler = Local::take();
+                    scheduler.resume_blocked_task_immediately(task.take());
+                }
+            }
+        };
+
+        // If home is none, then this process never actually successfully
+        // spawned, so there's no need to switch event loops
+        if self.home.is_none() {
+            close(self)
+        } else {
+            self.home_for_io(close)
+        }
+    }
+}
+
+impl RtioProcess for UvProcess {
+    fn id(&self) -> pid_t {
+        self.process.pid()
+    }
+
+    fn kill(&mut self, signal: int) -> Result<(), IoError> {
+        do self.home_for_io |self_| {
+            match self_.process.kill(signal) {
+                Ok(()) => Ok(()),
+                Err(uverr) => Err(uv_error_to_io_error(uverr))
+            }
+        }
+    }
+
+    fn wait(&mut self) -> int {
+        // Make sure (on the home scheduler) that we have an exit status listed
+        do self.home_for_io |self_| {
+            match self_.exit_status {
+                Some(*) => {}
+                None => {
+                    // If there's no exit code previously listed, then the
+                    // process's exit callback has yet to be invoked. We just
+                    // need to deschedule ourselves and wait to be reawoken.
+                    let scheduler: ~Scheduler = Local::take();
+                    do scheduler.deschedule_running_task_and_then |_, task| {
+                        assert!(self_.descheduled.is_none());
+                        self_.descheduled = Some(task);
+                    }
+                    assert!(self_.exit_status.is_some());
+                }
+            }
+        }
+
+        self.exit_status.unwrap()
+    }
+}
+
 #[test]
 fn test_simple_io_no_connect() {
     do run_in_mt_newsched_task {
diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs
index 8f3cef4d238..790bf53a291 100644
--- a/src/libstd/rt/uv/uvll.rs
+++ b/src/libstd/rt/uv/uvll.rs
@@ -31,7 +31,6 @@
 
 use c_str::ToCStr;
 use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t};
-#[cfg(not(stage0))]
 use libc::ssize_t;
 use libc::{malloc, free};
 use libc;
@@ -67,6 +66,19 @@ pub mod errors {
     pub static EPIPE: c_int = -libc::EPIPE;
 }
 
+pub static PROCESS_SETUID: c_int = 1 << 0;
+pub static PROCESS_SETGID: c_int = 1 << 1;
+pub static PROCESS_WINDOWS_VERBATIM_ARGUMENTS: c_int = 1 << 2;
+pub static PROCESS_DETACHED: c_int = 1 << 3;
+pub static PROCESS_WINDOWS_HIDE: c_int = 1 << 4;
+
+pub static STDIO_IGNORE: c_int = 0x00;
+pub static STDIO_CREATE_PIPE: c_int = 0x01;
+pub static STDIO_INHERIT_FD: c_int = 0x02;
+pub static STDIO_INHERIT_STREAM: c_int = 0x04;
+pub static STDIO_READABLE_PIPE: c_int = 0x10;
+pub static STDIO_WRITABLE_PIPE: c_int = 0x20;
+
 // see libuv/include/uv-unix.h
 #[cfg(unix)]
 pub struct uv_buf_t {
@@ -81,6 +93,26 @@ pub struct uv_buf_t {
     base: *u8,
 }
 
+pub struct uv_process_options_t {
+    exit_cb: uv_exit_cb,
+    file: *libc::c_char,
+    args: **libc::c_char,
+    env: **libc::c_char,
+    cwd: *libc::c_char,
+    flags: libc::c_uint,
+    stdio_count: libc::c_int,
+    stdio: *uv_stdio_container_t,
+    uid: uv_uid_t,
+    gid: uv_gid_t,
+}
+
+// These fields are private because they must be interfaced with through the
+// functions below.
+pub struct uv_stdio_container_t {
+    priv flags: libc::c_int,
+    priv stream: *uv_stream_t,
+}
+
 pub type uv_handle_t = c_void;
 pub type uv_loop_t = c_void;
 pub type uv_idle_t = c_void;
@@ -95,77 +127,95 @@ pub type uv_stream_t = c_void;
 pub type uv_fs_t = c_void;
 pub type uv_udp_send_t = c_void;
 pub type uv_getaddrinfo_t = c_void;
+pub type uv_process_t = c_void;
+pub type uv_pipe_t = c_void;
+
+pub struct uv_timespec_t {
+    tv_sec: libc::c_long,
+    tv_nsec: libc::c_long
+}
+
+pub struct uv_stat_t {
+    st_dev: libc::uint64_t,
+    st_mode: libc::uint64_t,
+    st_nlink: libc::uint64_t,
+    st_uid: libc::uint64_t,
+    st_gid: libc::uint64_t,
+    st_rdev: libc::uint64_t,
+    st_ino: libc::uint64_t,
+    st_size: libc::uint64_t,
+    st_blksize: libc::uint64_t,
+    st_blocks: libc::uint64_t,
+    st_flags: libc::uint64_t,
+    st_gen: libc::uint64_t,
+    st_atim: uv_timespec_t,
+    st_mtim: uv_timespec_t,
+    st_ctim: uv_timespec_t,
+    st_birthtim: uv_timespec_t
+}
+
+impl uv_stat_t {
+    pub fn new() -> uv_stat_t {
+        uv_stat_t {
+            st_dev: 0,
+            st_mode: 0,
+            st_nlink: 0,
+            st_uid: 0,
+            st_gid: 0,
+            st_rdev: 0,
+            st_ino: 0,
+            st_size: 0,
+            st_blksize: 0,
+            st_blocks: 0,
+            st_flags: 0,
+            st_gen: 0,
+            st_atim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
+            st_mtim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
+            st_ctim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
+            st_birthtim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 }
+        }
+    }
+    pub fn is_file(&self) -> bool {
+        ((self.st_mode) & libc::S_IFMT as libc::uint64_t) == libc::S_IFREG as libc::uint64_t
+    }
+    pub fn is_dir(&self) -> bool {
+        ((self.st_mode) & libc::S_IFMT as libc::uint64_t) == libc::S_IFDIR as libc::uint64_t
+    }
+}
 
-#[cfg(stage0)]
-pub type uv_idle_cb = *u8;
-#[cfg(stage0)]
-pub type uv_alloc_cb = *u8;
-#[cfg(stage0)]
-pub type uv_read_cb = *u8;
-#[cfg(stage0)]
-pub type uv_udp_send_cb = *u8;
-#[cfg(stage0)]
-pub type uv_udp_recv_cb = *u8;
-#[cfg(stage0)]
-pub type uv_close_cb = *u8;
-#[cfg(stage0)]
-pub type uv_walk_cb = *u8;
-#[cfg(stage0)]
-pub type uv_async_cb = *u8;
-#[cfg(stage0)]
-pub type uv_connect_cb = *u8;
-#[cfg(stage0)]
-pub type uv_connection_cb = *u8;
-#[cfg(stage0)]
-pub type uv_timer_cb = *u8;
-#[cfg(stage0)]
-pub type uv_write_cb = *u8;
-#[cfg(stage0)]
-pub type uv_getaddrinfo_cb = *u8;
-
-#[cfg(not(stage0))]
 pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t,
                                     status: c_int);
-#[cfg(not(stage0))]
 pub type uv_alloc_cb = extern "C" fn(stream: *uv_stream_t,
                                      suggested_size: size_t) -> uv_buf_t;
-#[cfg(not(stage0))]
 pub type uv_read_cb = extern "C" fn(stream: *uv_stream_t,
                                     nread: ssize_t,
                                     buf: uv_buf_t);
-#[cfg(not(stage0))]
 pub type uv_udp_send_cb = extern "C" fn(req: *uv_udp_send_t,
                                         status: c_int);
-#[cfg(not(stage0))]
 pub type uv_udp_recv_cb = extern "C" fn(handle: *uv_udp_t,
                                         nread: ssize_t,
                                         buf: uv_buf_t,
                                         addr: *sockaddr,
                                         flags: c_uint);
-#[cfg(not(stage0))]
 pub type uv_close_cb = extern "C" fn(handle: *uv_handle_t);
-#[cfg(not(stage0))]
 pub type uv_walk_cb = extern "C" fn(handle: *uv_handle_t,
                                     arg: *c_void);
-#[cfg(not(stage0))]
 pub type uv_async_cb = extern "C" fn(handle: *uv_async_t,
                                      status: c_int);
-#[cfg(not(stage0))]
 pub type uv_connect_cb = extern "C" fn(handle: *uv_connect_t,
                                        status: c_int);
-#[cfg(not(stage0))]
 pub type uv_connection_cb = extern "C" fn(handle: *uv_connection_t,
                                           status: c_int);
-#[cfg(not(stage0))]
 pub type uv_timer_cb = extern "C" fn(handle: *uv_timer_t,
                                      status: c_int);
-#[cfg(not(stage0))]
 pub type uv_write_cb = extern "C" fn(handle: *uv_write_t,
                                      status: c_int);
-#[cfg(not(stage0))]
 pub type uv_getaddrinfo_cb = extern "C" fn(req: *uv_getaddrinfo_t,
                                            status: c_int,
                                            res: *addrinfo);
+pub type uv_exit_cb = extern "C" fn(handle: *uv_process_t,
+                                    exit_status: c_int,
+                                    term_signal: c_int);
 
 pub type sockaddr = c_void;
 pub type sockaddr_in = c_void;
@@ -214,6 +264,11 @@ pub struct addrinfo {
     ai_next: *addrinfo
 }
 
+#[cfg(unix)] pub type uv_uid_t = libc::types::os::arch::posix88::uid_t;
+#[cfg(unix)] pub type uv_gid_t = libc::types::os::arch::posix88::gid_t;
+#[cfg(windows)] pub type uv_uid_t = libc::c_uchar;
+#[cfg(windows)] pub type uv_gid_t = libc::c_uchar;
+
 #[deriving(Eq)]
 pub enum uv_handle_type {
     UV_UNKNOWN_HANDLE,
@@ -736,18 +791,95 @@ pub unsafe fn fs_close(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int,
 
     rust_uv_fs_close(loop_ptr, req, fd, cb)
 }
+pub unsafe fn fs_stat(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_fs_stat(loop_ptr, req, path, cb)
+}
+pub unsafe fn fs_fstat(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_fs_fstat(loop_ptr, req, fd, cb)
+}
+pub unsafe fn fs_mkdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, mode: int,
+                cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_fs_mkdir(loop_ptr, req, path, mode as c_int, cb)
+}
+pub unsafe fn fs_rmdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
+                cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_fs_rmdir(loop_ptr, req, path, cb)
+}
+pub unsafe fn fs_readdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
+                flags: c_int, cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_fs_readdir(loop_ptr, req, path, flags, cb)
+}
+pub unsafe fn populate_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t) {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_populate_uv_stat(req_in, stat_out)
+}
 pub unsafe fn fs_req_cleanup(req: *uv_fs_t) {
     #[fixed_stack_segment]; #[inline(never)];
 
     rust_uv_fs_req_cleanup(req);
 }
 
+pub unsafe fn spawn(loop_ptr: *c_void, result: *uv_process_t,
+                    options: uv_process_options_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+    return rust_uv_spawn(loop_ptr, result, options);
+}
+
+pub unsafe fn process_kill(p: *uv_process_t, signum: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+    return rust_uv_process_kill(p, signum);
+}
+
+pub unsafe fn process_pid(p: *uv_process_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+    return rust_uv_process_pid(p);
+}
+
+pub unsafe fn set_stdio_container_flags(c: *uv_stdio_container_t,
+                                        flags: libc::c_int) {
+    #[fixed_stack_segment]; #[inline(never)];
+    rust_set_stdio_container_flags(c, flags);
+}
+
+pub unsafe fn set_stdio_container_fd(c: *uv_stdio_container_t,
+                                     fd: libc::c_int) {
+    #[fixed_stack_segment]; #[inline(never)];
+    rust_set_stdio_container_fd(c, fd);
+}
+
+pub unsafe fn set_stdio_container_stream(c: *uv_stdio_container_t,
+                                         stream: *uv_stream_t) {
+    #[fixed_stack_segment]; #[inline(never)];
+    rust_set_stdio_container_stream(c, stream);
+}
+
+pub unsafe fn pipe_init(loop_ptr: *c_void, p: *uv_pipe_t, ipc: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+    rust_uv_pipe_init(loop_ptr, p, ipc)
+}
+
 // data access helpers
 pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int {
     #[fixed_stack_segment]; #[inline(never)];
 
     rust_uv_get_result_from_fs_req(req)
 }
+pub unsafe fn get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_get_ptr_from_fs_req(req)
+}
 pub unsafe fn get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t {
     #[fixed_stack_segment]; #[inline(never)];
 
@@ -928,8 +1060,18 @@ extern {
                        buf: *c_void, len: c_uint, offset: i64, cb: *u8) -> c_int;
     fn rust_uv_fs_close(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
                         cb: *u8) -> c_int;
+    fn rust_uv_fs_stat(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int;
+    fn rust_uv_fs_fstat(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int;
+    fn rust_uv_fs_mkdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
+                        mode: c_int, cb: *u8) -> c_int;
+    fn rust_uv_fs_rmdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
+                        cb: *u8) -> c_int;
+    fn rust_uv_fs_readdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
+                        flags: c_int, cb: *u8) -> c_int;
     fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
+    fn rust_uv_populate_uv_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t);
     fn rust_uv_get_result_from_fs_req(req: *uv_fs_t) -> c_int;
+    fn rust_uv_get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void;
     fn rust_uv_get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t;
     fn rust_uv_get_loop_from_getaddrinfo_req(req: *uv_fs_t) -> *uv_loop_t;
 
@@ -949,4 +1091,13 @@ extern {
                            node: *c_char, service: *c_char,
                            hints: *addrinfo) -> c_int;
     fn rust_uv_freeaddrinfo(ai: *addrinfo);
+    fn rust_uv_spawn(loop_ptr: *c_void, outptr: *uv_process_t,
+                     options: uv_process_options_t) -> c_int;
+    fn rust_uv_process_kill(p: *uv_process_t, signum: c_int) -> c_int;
+    fn rust_uv_process_pid(p: *uv_process_t) -> c_int;
+    fn rust_set_stdio_container_flags(c: *uv_stdio_container_t, flags: c_int);
+    fn rust_set_stdio_container_fd(c: *uv_stdio_container_t, fd: c_int);
+    fn rust_set_stdio_container_stream(c: *uv_stdio_container_t,
+                                       stream: *uv_stream_t);
+    fn rust_uv_pipe_init(loop_ptr: *c_void, p: *uv_pipe_t, ipc: c_int) -> c_int;
 }
diff --git a/src/libstd/run.rs b/src/libstd/run.rs
index 94673ac5a59..362eab17fe7 100644
--- a/src/libstd/run.rs
+++ b/src/libstd/run.rs
@@ -749,8 +749,6 @@ fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T {
             let mut tmps = vec::with_capacity(env.len());
 
             for pair in env.iter() {
-                // Use of match here is just to workaround limitations
-                // in the stage0 irrefutable pattern impl.
                 let kv = fmt!("%s=%s", pair.first(), pair.second());
                 tmps.push(kv.to_c_str());
             }
diff --git a/src/libstd/std.rs b/src/libstd/std.rs
index 05433c47059..e9d5dd416ad 100644
--- a/src/libstd/std.rs
+++ b/src/libstd/std.rs
@@ -179,14 +179,8 @@ pub mod run;
 pub mod sys;
 pub mod cast;
 pub mod fmt;
-#[cfg(stage0)] #[path = "repr_stage0.rs"]
-pub mod repr;
-#[cfg(not(stage0))]
 pub mod repr;
 pub mod cleanup;
-#[cfg(stage0)] #[path = "reflect_stage0.rs"]
-pub mod reflect;
-#[cfg(not(stage0))]
 pub mod reflect;
 pub mod condition;
 pub mod logging;
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index bd484a5074c..9707d592a2e 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -938,6 +938,7 @@ static TAG_CONT_U8: u8 = 128u8;
 
 /// Unsafe operations
 pub mod raw {
+    use option::{Option, Some};
     use cast;
     use libc;
     use ptr;
@@ -1091,6 +1092,34 @@ pub mod raw {
         vec::raw::set_len(as_owned_vec(s), new_len)
     }
 
+    /// Parses a C "multistring", eg windows env values or
+    /// the req->ptr result in a uv_fs_readdir() call.
+    /// Optionally, a `count` can be passed in, limiting the
+    /// parsing to only being done `count`-times.
+    #[inline]
+    pub unsafe fn from_c_multistring(buf: *libc::c_char, count: Option<uint>) -> ~[~str] {
+        #[fixed_stack_segment]; #[inline(never)];
+
+        let mut curr_ptr: uint = buf as uint;
+        let mut result = ~[];
+        let mut ctr = 0;
+        let (limited_count, limit) = match count {
+            Some(limit) => (true, limit),
+            None => (false, 0)
+        };
+        while(((limited_count && ctr < limit) || !limited_count)
+              && *(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
+            let env_pair = from_c_str(
+                curr_ptr as *libc::c_char);
+            result.push(env_pair);
+            curr_ptr +=
+                libc::strlen(curr_ptr as *libc::c_char) as uint
+                + 1;
+            ctr += 1;
+        }
+        result
+    }
+
     /// Sets the length of a string
     ///
     /// This will explicitly set the size of the string, without actually
@@ -1106,6 +1135,25 @@ pub mod raw {
         }
     }
 
+    #[test]
+    fn test_str_multistring_parsing() {
+        use option::None;
+        unsafe {
+            let input = bytes!("zero", "\x00", "one", "\x00", "\x00");
+            let ptr = vec::raw::to_ptr(input);
+            let mut result = from_c_multistring(ptr as *libc::c_char, None);
+            assert!(result.len() == 2);
+            let mut ctr = 0;
+            for x in result.iter() {
+                match ctr {
+                    0 => assert_eq!(x, &~"zero"),
+                    1 => assert_eq!(x, &~"one"),
+                    _ => fail!("shouldn't happen!")
+                }
+                ctr += 1;
+            }
+        }
+    }
 }
 
 /*
diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs
index 3d35de0f898..c315c3f9dfc 100644
--- a/src/libstd/sys.rs
+++ b/src/libstd/sys.rs
@@ -14,8 +14,6 @@
 
 use c_str::ToCStr;
 use cast;
-#[cfg(stage0)]
-use io;
 use libc;
 use libc::{c_char, size_t};
 use repr;
@@ -92,7 +90,6 @@ pub fn refcount<T>(t: @T) -> uint {
     }
 }
 
-#[cfg(not(stage0))]
 pub fn log_str<T>(t: &T) -> ~str {
     use rt::io;
     use rt::io::Decorator;
@@ -101,12 +98,6 @@ pub fn log_str<T>(t: &T) -> ~str {
     repr::write_repr(&mut result as &mut io::Writer, t);
     str::from_utf8_owned(result.inner())
 }
-#[cfg(stage0)]
-pub fn log_str<T>(t: &T) -> ~str {
-    do io::with_str_writer |w| {
-        repr::write_repr(w, t)
-    }
-}
 
 /// Trait for initiating task failure.
 pub trait FailWithCause {
diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs
index a32b52db1cc..e8835462a80 100644
--- a/src/libstd/unstable/atomics.rs
+++ b/src/libstd/unstable/atomics.rs
@@ -339,13 +339,7 @@ impl<T> AtomicOption<T> {
 #[unsafe_destructor]
 impl<T> Drop for AtomicOption<T> {
     fn drop(&mut self) {
-        // This will ensure that the contained data is
-        // destroyed, unless it's null.
-        unsafe {
-            // FIXME(#4330) Need self by value to get mutability.
-            let this : &mut AtomicOption<T> = cast::transmute(self);
-            let _ = this.take(SeqCst);
-        }
+        let _ = self.take(SeqCst);
     }
 }
 
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index c3791d18b38..349739a5ea6 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -76,103 +76,7 @@ pub struct TyDesc {
 pub enum Opaque { }
 
 #[lang="ty_visitor"]
-#[cfg(not(test), stage0)]
-pub trait TyVisitor {
-    fn visit_bot(&self) -> bool;
-    fn visit_nil(&self) -> bool;
-    fn visit_bool(&self) -> bool;
-
-    fn visit_int(&self) -> bool;
-    fn visit_i8(&self) -> bool;
-    fn visit_i16(&self) -> bool;
-    fn visit_i32(&self) -> bool;
-    fn visit_i64(&self) -> bool;
-
-    fn visit_uint(&self) -> bool;
-    fn visit_u8(&self) -> bool;
-    fn visit_u16(&self) -> bool;
-    fn visit_u32(&self) -> bool;
-    fn visit_u64(&self) -> bool;
-
-    fn visit_float(&self) -> bool;
-    fn visit_f32(&self) -> bool;
-    fn visit_f64(&self) -> bool;
-
-    fn visit_char(&self) -> bool;
-
-    fn visit_estr_box(&self) -> bool;
-    fn visit_estr_uniq(&self) -> bool;
-    fn visit_estr_slice(&self) -> bool;
-    fn visit_estr_fixed(&self, n: uint, sz: uint, align: uint) -> bool;
-
-    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
-
-    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_evec_uniq_managed(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
-                        mtbl: uint, inner: *TyDesc) -> bool;
-
-    fn visit_enter_rec(&self, n_fields: uint,
-                       sz: uint, align: uint) -> bool;
-    fn visit_rec_field(&self, i: uint, name: &str,
-                       mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_leave_rec(&self, n_fields: uint,
-                       sz: uint, align: uint) -> bool;
-
-    fn visit_enter_class(&self, n_fields: uint,
-                         sz: uint, align: uint) -> bool;
-    fn visit_class_field(&self, i: uint, name: &str,
-                         mtbl: uint, inner: *TyDesc) -> bool;
-    fn visit_leave_class(&self, n_fields: uint,
-                         sz: uint, align: uint) -> bool;
-
-    fn visit_enter_tup(&self, n_fields: uint,
-                       sz: uint, align: uint) -> bool;
-    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool;
-    fn visit_leave_tup(&self, n_fields: uint,
-                       sz: uint, align: uint) -> bool;
-
-    fn visit_enter_enum(&self, n_variants: uint,
-                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                        sz: uint, align: uint) -> bool;
-    fn visit_enter_enum_variant(&self, variant: uint,
-                                disr_val: int,
-                                n_fields: uint,
-                                name: &str) -> bool;
-    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool;
-    fn visit_leave_enum_variant(&self, variant: uint,
-                                disr_val: int,
-                                n_fields: uint,
-                                name: &str) -> bool;
-    fn visit_leave_enum(&self, n_variants: uint,
-                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                        sz: uint, align: uint) -> bool;
-
-    fn visit_enter_fn(&self, purity: uint, proto: uint,
-                      n_inputs: uint, retstyle: uint) -> bool;
-    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool;
-    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool;
-    fn visit_leave_fn(&self, purity: uint, proto: uint,
-                      n_inputs: uint, retstyle: uint) -> bool;
-
-    fn visit_trait(&self) -> bool;
-    fn visit_param(&self, i: uint) -> bool;
-    fn visit_self(&self) -> bool;
-    fn visit_type(&self) -> bool;
-    fn visit_opaque_box(&self) -> bool;
-    fn visit_closure_ptr(&self, ck: uint) -> bool;
-}
-
-#[lang="ty_visitor"]
-#[cfg(not(test), not(stage0))]
+#[cfg(not(test))]
 pub trait TyVisitor {
     fn visit_bot(&mut self) -> bool;
     fn visit_nil(&mut self) -> bool;
@@ -424,9 +328,6 @@ extern "rust-intrinsic" {
     /// Returns `true` if a type is managed (will be allocated on the local heap)
     pub fn contains_managed<T>() -> bool;
 
-    #[cfg(stage0)]
-    pub fn visit_tydesc(td: *TyDesc, tv: &TyVisitor);
-    #[cfg(not(stage0))]
     pub fn visit_tydesc(td: *TyDesc, tv: &mut TyVisitor);
 
     pub fn frame_address(f: &once fn(*u8));
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
index 1dafeb27a0e..c2ef2300fc2 100644
--- a/src/libstd/unstable/sync.rs
+++ b/src/libstd/unstable/sync.rs
@@ -411,23 +411,6 @@ impl<T:Send> Exclusive<T> {
     }
 }
 
-#[cfg(stage0)]
-mod macro_hack {
-#[macro_escape];
-macro_rules! externfn(
-    (fn $name:ident () $(-> $ret_ty:ty),*) => (
-        extern {
-            fn $name() $(-> $ret_ty),*;
-        }
-    );
-    (fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
-        extern {
-            fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
-        }
-    )
-)
-}
-
 externfn!(fn rust_create_little_lock() -> rust_little_lock)
 externfn!(fn rust_destroy_little_lock(lock: rust_little_lock))
 externfn!(fn rust_lock_little_lock(lock: rust_little_lock))
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index cbc6b604bb7..f0f86911f50 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -804,7 +804,7 @@ pub fn new_sctable_internal() -> SCTable {
 
 // fetch the SCTable from TLS, create one if it doesn't yet exist.
 pub fn get_sctable() -> @mut SCTable {
-    static sctable_key: local_data::Key<@@mut SCTable> = &local_data::Key;
+    local_data_key!(sctable_key: @@mut SCTable)
     match local_data::get(sctable_key, |k| k.map_move(|k| *k)) {
         None => {
             let new_table = @@mut new_sctable_internal();
@@ -841,7 +841,7 @@ pub type ResolveTable = HashMap<(Name,SyntaxContext),Name>;
 // okay, I admit, putting this in TLS is not so nice:
 // fetch the SCTable from TLS, create one if it doesn't yet exist.
 pub fn get_resolve_table() -> @mut ResolveTable {
-    static resolve_table_key: local_data::Key<@@mut ResolveTable> = &local_data::Key;
+    local_data_key!(resolve_table_key: @@mut ResolveTable)
     match local_data::get(resolve_table_key, |k| k.map(|&k| *k)) {
         None => {
             let new_table = @@mut HashMap::new();
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 536267a2235..5e9714ca5b2 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -187,7 +187,7 @@ fn diagnosticcolor(lvl: level) -> term::color::Color {
 }
 
 fn print_maybe_styled(msg: &str, color: term::attr::Attr) {
-    static tls_terminal: local_data::Key<@Option<term::Terminal>> = &local_data::Key;
+    local_data_key!(tls_terminal: @Option<term::Terminal>)
 
     let stderr = io::stderr();
 
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 6cb5a93a313..889c2a5976e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -644,25 +644,11 @@ impl AstBuilder for @ExtCtxt {
 
         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
     }
-    #[cfg(stage0)]
-    fn lambda0(&self, _span: Span, blk: ast::Block) -> @ast::Expr {
-        let ext_cx = *self;
-        let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
-        quote_expr!(|| $blk_e )
-    }
-    #[cfg(not(stage0))]
     fn lambda0(&self, _span: Span, blk: ast::Block) -> @ast::Expr {
         let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
         quote_expr!(*self, || $blk_e )
     }
 
-    #[cfg(stage0)]
-    fn lambda1(&self, _span: Span, blk: ast::Block, ident: ast::Ident) -> @ast::Expr {
-        let ext_cx = *self;
-        let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
-        quote_expr!(|$ident| $blk_e )
-    }
-    #[cfg(not(stage0))]
     fn lambda1(&self, _span: Span, blk: ast::Block, ident: ast::Ident) -> @ast::Expr {
         let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
         quote_expr!(*self, |$ident| $blk_e )
diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
index cac311b0088..b27fcb6c9b9 100644
--- a/src/libsyntax/ext/bytes.rs
+++ b/src/libsyntax/ext/bytes.rs
@@ -30,43 +30,43 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) -> bas
                 // string literal, push each byte to vector expression
                 ast::lit_str(s) => {
                     for byte in s.byte_iter() {
-                        bytes.push(cx.expr_u8(sp, byte));
+                        bytes.push(cx.expr_u8(expr.span, byte));
                     }
                 }
 
                 // u8 literal, push to vector expression
                 ast::lit_uint(v, ast::ty_u8) => {
                     if v > 0xFF {
-                        cx.span_err(sp, "Too large u8 literal in bytes!")
+                        cx.span_err(expr.span, "Too large u8 literal in bytes!")
                     } else {
-                        bytes.push(cx.expr_u8(sp, v as u8));
+                        bytes.push(cx.expr_u8(expr.span, v as u8));
                     }
                 }
 
                 // integer literal, push to vector expression
                 ast::lit_int_unsuffixed(v) => {
                     if v > 0xFF {
-                        cx.span_err(sp, "Too large integer literal in bytes!")
+                        cx.span_err(expr.span, "Too large integer literal in bytes!")
                     } else if v < 0 {
-                        cx.span_err(sp, "Negative integer literal in bytes!")
+                        cx.span_err(expr.span, "Negative integer literal in bytes!")
                     } else {
-                        bytes.push(cx.expr_u8(sp, v as u8));
+                        bytes.push(cx.expr_u8(expr.span, v as u8));
                     }
                 }
 
                 // char literal, push to vector expression
                 ast::lit_char(v) => {
                     if char::from_u32(v).unwrap().is_ascii() {
-                        bytes.push(cx.expr_u8(sp, v as u8));
+                        bytes.push(cx.expr_u8(expr.span, v as u8));
                     } else {
-                        cx.span_err(sp, "Non-ascii char literal in bytes!")
+                        cx.span_err(expr.span, "Non-ascii char literal in bytes!")
                     }
                 }
 
-                _ => cx.span_err(sp, "Unsupported literal in bytes!")
+                _ => cx.span_err(expr.span, "Unsupported literal in bytes!")
             },
 
-            _ => cx.span_err(sp, "Non-literal in bytes!")
+            _ => cx.span_err(expr.span, "Non-literal in bytes!")
         }
     }
 
diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs
index ac8a7d513dd..e97af9cbfb1 100644
--- a/src/libsyntax/ext/env.rs
+++ b/src/libsyntax/ext/env.rs
@@ -22,18 +22,6 @@ use ext::build::AstBuilder;
 
 use std::os;
 
-#[cfg(stage0)]
-pub fn expand_option_env(ext_cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
-    -> base::MacResult {
-    let var = get_single_str_from_tts(ext_cx, sp, tts, "option_env!");
-
-    let e = match os::getenv(var) {
-      None => quote_expr!(::std::option::None::<&'static str>),
-      Some(s) => quote_expr!(::std::option::Some($s))
-    };
-    MRExpr(e)
-}
-#[cfg(not(stage0))]
 pub fn expand_option_env(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
     -> base::MacResult {
     let var = get_single_str_from_tts(cx, sp, tts, "option_env!");
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index ac094c27a81..7254e8e775a 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -863,9 +863,7 @@ pub fn std_macros() -> @str {
 
                 use super::*;
 
-                static key: ::std::local_data::Key<
-                    @::std::condition::Handler<$input, $out>> =
-                    &::std::local_data::Key;
+                local_data_key!(key: @::std::condition::Handler<$input, $out>)
 
                 pub static cond :
                     ::std::condition::Condition<$input,$out> =
@@ -884,9 +882,7 @@ pub fn std_macros() -> @str {
 
                 use super::*;
 
-                static key: ::std::local_data::Key<
-                    @::std::condition::Handler<$input, $out>> =
-                    &::std::local_data::Key;
+                local_data_key!(key: @::std::condition::Handler<$input, $out>)
 
                 pub static cond :
                     ::std::condition::Condition<$input,$out> =
@@ -975,8 +971,6 @@ pub fn std_macros() -> @str {
         ($($arg:tt)*) => (::std::io::println(format!($($arg)*)))
     )
 
-    // NOTE: use this after a snapshot lands to abstract the details
-    // of the TLS interface.
     macro_rules! local_data_key (
         ($name:ident: $ty:ty) => (
             static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key;
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index c267a673fce..0bc9e619274 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -699,6 +699,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
               '\\' => { c2 = '\\'; }
               '\'' => { c2 = '\''; }
               '"' => { c2 = '"'; }
+              '0' => { c2 = '\x00'; }
               'x' => { c2 = scan_numeric_escape(rdr, 2u); }
               'u' => { c2 = scan_numeric_escape(rdr, 4u); }
               'U' => { c2 = scan_numeric_escape(rdr, 8u); }
@@ -738,6 +739,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
                   '\'' => accum_str.push_char('\''),
                   '"' => accum_str.push_char('"'),
                   '\n' => consume_whitespace(rdr),
+                  '0' => accum_str.push_char('\x00'),
                   'x' => {
                     accum_str.push_char(scan_numeric_escape(rdr, 2u));
                   }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index fa00b536837..a8df737e49f 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -490,8 +490,7 @@ fn mk_fresh_ident_interner() -> @ident_interner {
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
 pub fn get_ident_interner() -> @ident_interner {
-    static key: local_data::Key<@@::parse::token::ident_interner> =
-        &local_data::Key;
+    local_data_key!(key: @@::parse::token::ident_interner)
     match local_data::get(key, |k| k.map_move(|k| *k)) {
         Some(interner) => *interner,
         None => {
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index af2a4977082..615f3301373 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -243,7 +243,7 @@ pub fn mk_printer(out: @io::Writer, linewidth: uint) -> @mut Printer {
  * the entire buffered window, but can't output anything until the size is >=
  * 0 (sizes are set to negative while they're pending calculation).
  *
- * So SCAN takeks input and buffers tokens and pending calculations, while
+ * So SCAN takes input and buffers tokens and pending calculations, while
  * PRINT gobbles up completed calculations and tokens from the buffer. The
  * theory is that the two can never get more than 3N tokens apart, because
  * once there's "obviously" too much data to fit on a line, in a size
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index ec84cbda973..b5868cbc63d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1535,15 +1535,15 @@ fn print_path_(s: @ps,
 
         print_ident(s, segment.identifier);
 
-        if segment.lifetime.is_some() || !segment.types.is_empty() {
-            // If this is the last segment, print the bounds.
-            if i == path.segments.len() - 1 {
-                match *opt_bounds {
-                    None => {}
-                    Some(ref bounds) => print_bounds(s, bounds, true),
-                }
+        // If this is the last segment, print the bounds.
+        if i == path.segments.len() - 1 {
+            match *opt_bounds {
+                None => {}
+                Some(ref bounds) => print_bounds(s, bounds, true),
             }
+        }
 
+        if segment.lifetime.is_some() || !segment.types.is_empty() {
             if colons_before_params {
                 word(s.s, "::")
             }
diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp
index bfdf0e67a9b..3e9b8ba136e 100644
--- a/src/rt/rust_uv.cpp
+++ b/src/rt/rust_uv.cpp
@@ -542,6 +542,10 @@ extern "C" int
 rust_uv_get_result_from_fs_req(uv_fs_t* req) {
   return req->result;
 }
+extern "C" void*
+rust_uv_get_ptr_from_fs_req(uv_fs_t* req) {
+  return req->ptr;
+}
 extern "C" uv_loop_t*
 rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
   return req->loop;
@@ -551,3 +555,85 @@ extern "C" uv_loop_t*
 rust_uv_get_loop_from_getaddrinfo_req(uv_getaddrinfo_t* req) {
   return req->loop;
 }
+
+extern "C" int
+rust_uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
+  return uv_fs_stat(loop, req, path, cb);
+}
+extern "C" int
+rust_uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
+  return uv_fs_fstat(loop, req, file, cb);
+}
+
+extern "C" void
+rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) {
+  stat_out->st_dev = req_in->statbuf.st_dev;
+  stat_out->st_mode = req_in->statbuf.st_mode;
+  stat_out->st_nlink = req_in->statbuf.st_nlink;
+  stat_out->st_uid = req_in->statbuf.st_uid;
+  stat_out->st_gid = req_in->statbuf.st_gid;
+  stat_out->st_rdev = req_in->statbuf.st_rdev;
+  stat_out->st_ino = req_in->statbuf.st_ino;
+  stat_out->st_size = req_in->statbuf.st_size;
+  stat_out->st_blksize = req_in->statbuf.st_blksize;
+  stat_out->st_blocks = req_in->statbuf.st_blocks;
+  stat_out->st_flags = req_in->statbuf.st_flags;
+  stat_out->st_gen = req_in->statbuf.st_gen;
+  stat_out->st_atim.tv_sec = req_in->statbuf.st_atim.tv_sec;
+  stat_out->st_atim.tv_nsec = req_in->statbuf.st_atim.tv_nsec;
+  stat_out->st_mtim.tv_sec = req_in->statbuf.st_mtim.tv_sec;
+  stat_out->st_mtim.tv_nsec = req_in->statbuf.st_mtim.tv_nsec;
+  stat_out->st_ctim.tv_sec = req_in->statbuf.st_ctim.tv_sec;
+  stat_out->st_ctim.tv_nsec = req_in->statbuf.st_ctim.tv_nsec;
+  stat_out->st_birthtim.tv_sec = req_in->statbuf.st_birthtim.tv_sec;
+  stat_out->st_birthtim.tv_nsec = req_in->statbuf.st_birthtim.tv_nsec;
+}
+
+extern "C" int
+rust_uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) {
+  return uv_fs_mkdir(loop, req, path, mode, cb);
+}
+extern "C" int
+rust_uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
+  return uv_fs_rmdir(loop, req, path, cb);
+}
+
+extern "C" int
+rust_uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) {
+  return uv_fs_readdir(loop, req, path, flags, cb);
+}
+
+extern "C" int
+rust_uv_spawn(uv_loop_t *loop, uv_process_t *p, uv_process_options_t options) {
+  return uv_spawn(loop, p, options);
+}
+
+extern "C" int
+rust_uv_process_kill(uv_process_t *p, int signum) {
+  return uv_process_kill(p, signum);
+}
+
+extern "C" void
+rust_set_stdio_container_flags(uv_stdio_container_t *c, int flags) {
+  c->flags = (uv_stdio_flags) flags;
+}
+
+extern "C" void
+rust_set_stdio_container_fd(uv_stdio_container_t *c, int fd) {
+  c->data.fd = fd;
+}
+
+extern "C" void
+rust_set_stdio_container_stream(uv_stdio_container_t *c, uv_stream_t *stream) {
+  c->data.stream = stream;
+}
+
+extern "C" int
+rust_uv_process_pid(uv_process_t* p) {
+  return p->pid;
+}
+
+extern "C" int
+rust_uv_pipe_init(uv_loop_t *loop, uv_pipe_t* p, int ipc) {
+  return uv_pipe_init(loop, p, ipc);
+}
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 93e8d34ca5f..7a9149187d8 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -112,8 +112,15 @@ rust_uv_fs_write
 rust_uv_fs_read
 rust_uv_fs_close
 rust_uv_get_result_from_fs_req
+rust_uv_get_ptr_from_fs_req
 rust_uv_get_loop_from_fs_req
+rust_uv_fs_stat
+rust_uv_fs_fstat
 rust_uv_fs_req_cleanup
+rust_uv_populate_uv_stat
+rust_uv_fs_mkdir
+rust_uv_fs_rmdir
+rust_uv_fs_readdir
 rust_dbg_lock_create
 rust_dbg_lock_destroy
 rust_dbg_lock_lock
@@ -190,3 +197,10 @@ rust_drop_linenoise_lock
 rust_get_test_int
 rust_get_task
 rust_uv_get_loop_from_getaddrinfo_req
+rust_uv_spawn
+rust_uv_process_kill
+rust_set_stdio_container_flags
+rust_set_stdio_container_fd
+rust_set_stdio_container_stream
+rust_uv_process_pid
+rust_uv_pipe_init
diff --git a/src/snapshots.txt b/src/snapshots.txt
index ad170d9173f..705cf50632a 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,11 @@
+S 2013-09-17 cbd1eef
+  freebsd-x86_64 9166867a8859076343cb3e57da918b5c0eea720b
+  linux-i386 38347b579312ff30c36d257a1161660eb0ae8422
+  linux-x86_64 0c169bba5d6729d0c0f096d61d9274fb082b4b34
+  macos-i386 1eb229510dd12b91800674566b8dad401a3f80d3
+  macos-x86_64 1c5d8e29b9671af93963e1b5fa9fcca081124a39
+  winnt-i386 56baa04a1f02235ebc5a75be05aa65fdc822a4e6
+
 S 2013-08-14 e7b5729
   freebsd-x86_64 9de0b5583a5c4413f9e77df7071498385e936dd2
   linux-i386 29119a9072f74c639c2bad998edc40e582da540e
diff --git a/src/test/auxiliary/xcrate_address_insignificant.rs b/src/test/auxiliary/xcrate_address_insignificant.rs
new file mode 100644
index 00000000000..08e3eff0c8c
--- /dev/null
+++ b/src/test/auxiliary/xcrate_address_insignificant.rs
@@ -0,0 +1,19 @@
+// 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 fn foo<T>() -> int {
+    #[address_insignificant]
+    static a: int = 3;
+    a
+}
+
+pub fn bar() -> int {
+    foo::<int>()
+}
diff --git a/src/test/pretty/path-type-bounds.rs b/src/test/pretty/path-type-bounds.rs
new file mode 100644
index 00000000000..a62fbdeeb18
--- /dev/null
+++ b/src/test/pretty/path-type-bounds.rs
@@ -0,0 +1,13 @@
+// pp-exact
+
+trait Tr { }
+impl Tr for int;
+
+fn foo(x: ~Tr: Freeze) -> ~Tr: Freeze { x }
+
+fn main() {
+    let x: ~Tr: Freeze;
+
+    ~1 as ~Tr: Freeze;
+}
+
diff --git a/src/test/run-pass/extern-pass-TwoU64s-ref.rs b/src/test/run-pass/extern-pass-TwoU64s-ref.rs
index 1937c366831..ed9871b5edb 100644
--- a/src/test/run-pass/extern-pass-TwoU64s-ref.rs
+++ b/src/test/run-pass/extern-pass-TwoU64s-ref.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // Test that we ignore modes when calling extern functions.
+// xfail-fast #9205
 
 #[deriving(Eq)]
 struct TwoU64s {
diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs
index b543099b3b8..772970ce8a3 100644
--- a/src/test/run-pass/extern-pass-TwoU64s.rs
+++ b/src/test/run-pass/extern-pass-TwoU64s.rs
@@ -14,6 +14,7 @@
 // xfail-fast This works standalone on windows but not with check-fast.
 // possibly because there is another test that uses this extern fn but gives it
 // a different signature
+// xfail-fast #9205
 
 #[deriving(Eq)]
 struct TwoU64s {
diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs
index 4dc31d71526..7fcbe3670fc 100644
--- a/src/test/run-pass/extern-return-TwoU64s.rs
+++ b/src/test/run-pass/extern-return-TwoU64s.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// xfail-fast #9205
+
 struct TwoU64s {
     one: u64, two: u64
 }
diff --git a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs
index 1492b5895ba..2f2b736294a 100644
--- a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs
+++ b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-pretty #9253 pretty printer doesn't preserve the bounds on trait objects
-
 /*
 
 #7673 Polymorphically creating traits barely works
diff --git a/src/test/run-pass/nul-characters.rs b/src/test/run-pass/nul-characters.rs
new file mode 100644
index 00000000000..2a301d0b0fd
--- /dev/null
+++ b/src/test/run-pass/nul-characters.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.
+
+pub fn main()
+{
+    let all_nuls1 = "\0\x00\u0000\U00000000";
+    let all_nuls2 = "\U00000000\u0000\x00\0";
+    let all_nuls3 = "\u0000\U00000000\x00\0";
+    let all_nuls4 = "\x00\u0000\0\U00000000";
+
+    // sizes for two should suffice
+    assert_eq!(all_nuls1.len(), 4); 
+    assert_eq!(all_nuls2.len(), 4);
+
+    // string equality should pass between the strings
+    assert_eq!(all_nuls1, all_nuls2);
+    assert_eq!(all_nuls2, all_nuls3);
+    assert_eq!(all_nuls3, all_nuls4);
+    
+    // all extracted characters in all_nuls are equivalent to each other
+    for c1 in all_nuls1.iter()
+    {
+        for c2 in all_nuls1.iter()
+        {
+            assert_eq!(c1,c2);
+        }
+    }
+    
+    // testing equality between explicit character literals
+    assert_eq!('\0', '\x00');
+    assert_eq!('\u0000', '\x00');
+    assert_eq!('\u0000', '\U00000000');
+
+    // NUL characters should make a difference
+    assert!("Hello World" != "Hello \0World");
+    assert!("Hello World" != "Hello World\0");
+}
diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs
index 3f63902eb31..a1f5a2392b1 100644
--- a/src/test/run-pass/struct-return.rs
+++ b/src/test/run-pass/struct-return.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// xfail-fast #9205
+
 pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
 pub struct Floats { a: f64, b: u8, c: f64 }
 
diff --git a/src/test/run-pass/xcrate-address-insignificant.rs b/src/test/run-pass/xcrate-address-insignificant.rs
new file mode 100644
index 00000000000..1bf3763834a
--- /dev/null
+++ b/src/test/run-pass/xcrate-address-insignificant.rs
@@ -0,0 +1,18 @@
+// 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-fast windows doesn't like aux-build
+// aux-build:xcrate_address_insignificant.rs
+
+extern mod foo(name = "xcrate_address_insignificant");
+
+fn main() {
+    assert_eq!(foo::foo::<float>(), foo::bar());
+}