about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-19 01:41:43 +0000
committerbors <bors@rust-lang.org>2014-06-19 01:41:43 +0000
commit3770c42a4959cbabc73da52abc7e3db96657974e (patch)
treef16e89715388b6ac30e01c68bee674dafefa8a26 /src/libstd
parent0dcc9554599750e237119756e03a62fd0a9d8970 (diff)
parent2c3bf8836f6f0cd18d8ac4f7189615f7f4098f5d (diff)
downloadrust-3770c42a4959cbabc73da52abc7e3db96657974e.tar.gz
rust-3770c42a4959cbabc73da52abc7e3db96657974e.zip
auto merge of #15025 : alexcrichton/rust/rollup, r=alexcrichton
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/buffered.rs4
-rw-r--r--src/libstd/io/fs.rs30
-rw-r--r--src/libstd/io/mem.rs4
-rw-r--r--src/libstd/io/mod.rs28
-rw-r--r--src/libstd/io/pipe.rs2
-rw-r--r--src/libstd/io/stdio.rs2
-rw-r--r--src/libstd/num/mod.rs2
-rw-r--r--src/libstd/path/mod.rs4
-rw-r--r--src/libstd/path/posix.rs265
-rw-r--r--src/libstd/path/windows.rs107
-rw-r--r--src/libstd/task.rs841
11 files changed, 669 insertions, 620 deletions
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 9450f7798ed..4f355502eb8 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -535,7 +535,7 @@ mod test {
 
     #[test]
     fn test_read_line() {
-        let in_buf = MemReader::new(Vec::from_slice(bytes!("a\nb\nc")));
+        let in_buf = MemReader::new(Vec::from_slice(b"a\nb\nc"));
         let mut reader = BufferedReader::with_capacity(2, in_buf);
         assert_eq!(reader.read_line(), Ok("a\n".to_string()));
         assert_eq!(reader.read_line(), Ok("b\n".to_string()));
@@ -545,7 +545,7 @@ mod test {
 
     #[test]
     fn test_lines() {
-        let in_buf = MemReader::new(Vec::from_slice(bytes!("a\nb\nc")));
+        let in_buf = MemReader::new(Vec::from_slice(b"a\nb\nc"));
         let mut reader = BufferedReader::with_capacity(2, in_buf);
         let mut it = reader.lines();
         assert_eq!(it.next(), Some(Ok("a\n".to_string())));
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index 20187a6dcde..a801dd0e7cb 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -35,7 +35,7 @@ let path = Path::new("foo.txt");
 
 // create the file, whether it exists or not
 let mut file = File::create(&path);
-file.write(bytes!("foobar"));
+file.write(b"foobar");
 # drop(file);
 
 // open the file in read-only mode
@@ -186,7 +186,7 @@ impl File {
     /// use std::io::File;
     ///
     /// let mut f = File::create(&Path::new("foo.txt"));
-    /// f.write(bytes!("This is a sample file"));
+    /// f.write(b"This is a sample file");
     /// # drop(f);
     /// # ::std::io::fs::unlink(&Path::new("foo.txt"));
     /// ```
@@ -1141,7 +1141,7 @@ mod test {
     iotest!(fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
         let tmpdir = tmpdir();
         let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt");
-        check!(File::create(file).write(bytes!("foo")));
+        check!(File::create(file).write(b"foo"));
         assert!(file.exists());
         check!(unlink(file));
         assert!(!file.exists());
@@ -1253,7 +1253,7 @@ mod test {
         let canary = d2.join("do_not_delete");
         check!(mkdir_recursive(&dtt, io::UserRWX));
         check!(mkdir_recursive(&d2, io::UserRWX));
-        check!(File::create(&canary).write(bytes!("foo")));
+        check!(File::create(&canary).write(b"foo"));
         check!(symlink(&d2, &dt.join("d2")));
         check!(rmdir_recursive(&d1));
 
@@ -1314,10 +1314,10 @@ mod test {
         let input = tmpdir.join("in.txt");
         let out = tmpdir.join("out.txt");
 
-        check!(File::create(&input).write(bytes!("hello")));
+        check!(File::create(&input).write(b"hello"));
         check!(copy(&input, &out));
         let contents = check!(File::open(&out).read_to_end());
-        assert_eq!(contents.as_slice(), bytes!("hello"));
+        assert_eq!(contents.as_slice(), b"hello");
 
         assert_eq!(check!(input.stat()).perm, check!(out.stat()).perm);
     })
@@ -1342,7 +1342,7 @@ mod test {
         check!(copy(&input, &output));
 
         assert_eq!(check!(File::open(&output).read_to_end()),
-                   (Vec::from_slice(bytes!("foo"))));
+                   (Vec::from_slice(b"foo")));
     })
 
     iotest!(fn copy_file_src_dir() {
@@ -1383,7 +1383,7 @@ mod test {
         }
         assert_eq!(check!(stat(&out)).size, check!(stat(&input)).size);
         assert_eq!(check!(File::open(&out).read_to_end()),
-                   (Vec::from_slice(bytes!("foobar"))));
+                   (Vec::from_slice(b"foobar")));
     })
 
     #[cfg(not(windows))] // apparently windows doesn't like symlinks
@@ -1418,7 +1418,7 @@ mod test {
         assert_eq!(check!(stat(&out)).size, check!(stat(&input)).size);
         assert_eq!(check!(stat(&out)).size, check!(input.stat()).size);
         assert_eq!(check!(File::open(&out).read_to_end()),
-                   (Vec::from_slice(bytes!("foobar"))));
+                   (Vec::from_slice(b"foobar")));
 
         // can't link to yourself
         match link(&input, &input) {
@@ -1456,7 +1456,7 @@ mod test {
         let mut file = check!(File::open_mode(&path, io::Open, io::ReadWrite));
         check!(file.fsync());
         check!(file.datasync());
-        check!(file.write(bytes!("foo")));
+        check!(file.write(b"foo"));
         check!(file.fsync());
         check!(file.datasync());
         drop(file);
@@ -1467,29 +1467,29 @@ mod test {
         let path = tmpdir.join("in.txt");
 
         let mut file = check!(File::open_mode(&path, io::Open, io::ReadWrite));
-        check!(file.write(bytes!("foo")));
+        check!(file.write(b"foo"));
         check!(file.fsync());
 
         // Do some simple things with truncation
         assert_eq!(check!(file.stat()).size, 3);
         check!(file.truncate(10));
         assert_eq!(check!(file.stat()).size, 10);
-        check!(file.write(bytes!("bar")));
+        check!(file.write(b"bar"));
         check!(file.fsync());
         assert_eq!(check!(file.stat()).size, 10);
         assert_eq!(check!(File::open(&path).read_to_end()),
-                   (Vec::from_slice(bytes!("foobar", 0, 0, 0, 0))));
+                   (Vec::from_slice(b"foobar\0\0\0\0")));
 
         // Truncate to a smaller length, don't seek, and then write something.
         // Ensure that the intermediate zeroes are all filled in (we're seeked
         // past the end of the file).
         check!(file.truncate(2));
         assert_eq!(check!(file.stat()).size, 2);
-        check!(file.write(bytes!("wut")));
+        check!(file.write(b"wut"));
         check!(file.fsync());
         assert_eq!(check!(file.stat()).size, 9);
         assert_eq!(check!(File::open(&path).read_to_end()),
-                   (Vec::from_slice(bytes!("fo", 0, 0, 0, 0, "wut"))));
+                   (Vec::from_slice(b"fo\0\0\0\0wut")));
         drop(file);
     })
 
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index 71a967bb8dc..5eca5361835 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -474,7 +474,7 @@ mod test {
 
     #[test]
     fn test_read_char() {
-        let b = bytes!("Việt");
+        let b = b"Vi\xE1\xBB\x87t";
         let mut r = BufReader::new(b);
         assert_eq!(r.read_char(), Ok('V'));
         assert_eq!(r.read_char(), Ok('i'));
@@ -485,7 +485,7 @@ mod test {
 
     #[test]
     fn test_read_bad_char() {
-        let b = bytes!(0x80);
+        let b = b"\x80";
         let mut r = BufReader::new(b);
         assert!(r.read_char().is_err());
     }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index a7f84899a62..d9755cdce1a 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -50,7 +50,7 @@ Some examples of obvious things you might want to do
     use std::io::File;
 
     let mut file = File::create(&Path::new("message.txt"));
-    file.write(bytes!("hello, file!\n"));
+    file.write(b"hello, file!\n");
     # drop(file);
     # ::std::io::fs::unlink(&Path::new("message.txt"));
     ```
@@ -90,7 +90,7 @@ Some examples of obvious things you might want to do
     # // just stop it running (#11576)
     # if false {
     let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap();
-    socket.write(bytes!("GET / HTTP/1.0\n\n"));
+    socket.write(b"GET / HTTP/1.0\n\n");
     let response = socket.read_to_end();
     # }
     ```
@@ -151,7 +151,7 @@ while still providing feedback about errors. The basic strategy:
   to be 'unwrapped' before use.
 
 These features combine in the API to allow for expressions like
-`File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n"))`
+`File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")`
 without having to worry about whether "diary.txt" exists or whether
 the write succeeds. As written, if either `new` or `write_line`
 encounters an error then the result of the entire expression will
@@ -163,7 +163,7 @@ If you wanted to handle the error though you might write:
 # #![allow(unused_must_use)]
 use std::io::File;
 
-match File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")) {
+match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") {
     Ok(()) => (), // succeeded
     Err(e) => println!("failed to write to my diary: {}", e),
 }
@@ -1839,55 +1839,55 @@ mod tests {
 
     #[test]
     fn test_read_at_least() {
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([GoodBehavior(uint::MAX)]));
         let mut buf = [0u8, ..5];
         assert!(r.read_at_least(1, buf).unwrap() >= 1);
         assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least
         assert!(r.read_at_least(0, buf).is_ok());
 
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([BadBehavior(50), GoodBehavior(uint::MAX)]));
         assert!(r.read_at_least(1, buf).unwrap() >= 1);
 
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([BadBehavior(1), GoodBehavior(1),
                                                     BadBehavior(50), GoodBehavior(uint::MAX)]));
         assert!(r.read_at_least(1, buf).unwrap() >= 1);
         assert!(r.read_at_least(1, buf).unwrap() >= 1);
 
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([BadBehavior(uint::MAX)]));
         assert_eq!(r.read_at_least(1, buf).unwrap_err().kind, NoProgress);
 
-        let mut r = MemReader::new(Vec::from_slice(bytes!("hello, world!")));
+        let mut r = MemReader::new(Vec::from_slice(b"hello, world!"));
         assert_eq!(r.read_at_least(5, buf).unwrap(), 5);
         assert_eq!(r.read_at_least(6, buf).unwrap_err().kind, InvalidInput);
     }
 
     #[test]
     fn test_push_at_least() {
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([GoodBehavior(uint::MAX)]));
         let mut buf = Vec::new();
         assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
         assert!(r.push_at_least(0, 5, &mut buf).is_ok());
 
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([BadBehavior(50), GoodBehavior(uint::MAX)]));
         assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
 
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([BadBehavior(1), GoodBehavior(1),
                                                     BadBehavior(50), GoodBehavior(uint::MAX)]));
         assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
         assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
 
-        let mut r = BadReader::new(MemReader::new(Vec::from_slice(bytes!("hello, world!"))),
+        let mut r = BadReader::new(MemReader::new(Vec::from_slice(b"hello, world!")),
                                    Vec::from_slice([BadBehavior(uint::MAX)]));
         assert_eq!(r.push_at_least(1, 5, &mut buf).unwrap_err().kind, NoProgress);
 
-        let mut r = MemReader::new(Vec::from_slice(bytes!("hello, world!")));
+        let mut r = MemReader::new(Vec::from_slice(b"hello, world!"));
         assert_eq!(r.push_at_least(5, 1, &mut buf).unwrap_err().kind, InvalidInput);
     }
 }
diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs
index 84d388c1136..a968f41a915 100644
--- a/src/libstd/io/pipe.rs
+++ b/src/libstd/io/pipe.rs
@@ -52,7 +52,7 @@ impl PipeStream {
     ///
     /// fn main() {
     ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
-    ///     pipe.write(bytes!("Hello, stderr!"));
+    ///     pipe.write(b"Hello, stderr!");
     /// }
     /// ```
     pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index c989dcc3d29..e5a64f785ce 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -22,7 +22,7 @@ about the stream or terminal to which it is attached.
 use std::io;
 
 let mut out = io::stdout();
-out.write(bytes!("Hello, world!"));
+out.write(b"Hello, world!");
 ```
 
 */
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index 602a2240f39..7301f9b08e9 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -22,7 +22,7 @@ use string::String;
 
 pub use core::num::{Num, div_rem, Zero, zero, One, one};
 pub use core::num::{Signed, abs, abs_sub, signum};
-pub use core::num::{Unsigned, pow, Bounded, Bitwise};
+pub use core::num::{Unsigned, pow, Bounded};
 pub use core::num::{Primitive, Int, Saturating};
 pub use core::num::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
 pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive};
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index 7d15893af24..e55dc165895 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -219,7 +219,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
                 let dot = '.' as u8;
                 match name.rposition_elem(&dot) {
                     None | Some(0) => name,
-                    Some(1) if name == bytes!("..") => name,
+                    Some(1) if name == b".." => name,
                     Some(pos) => name.slice_to(pos)
                 }
             })
@@ -242,7 +242,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
                 let dot = '.' as u8;
                 match name.rposition_elem(&dot) {
                     None | Some(0) => None,
-                    Some(1) if name == bytes!("..") => None,
+                    Some(1) if name == b".." => None,
                     Some(pos) => Some(name.slice_from(pos+1))
                 }
             }
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 494428de3a5..d98cfb7d8ee 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -142,7 +142,7 @@ impl GenericPathUnsafe for Path {
     unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
         let filename = filename.container_as_bytes();
         match self.sepidx {
-            None if bytes!("..") == self.repr.as_slice() => {
+            None if b".." == self.repr.as_slice() => {
                 let mut v = Vec::with_capacity(3 + filename.len());
                 v.push_all(dot_dot_static);
                 v.push(SEP_BYTE);
@@ -153,7 +153,7 @@ impl GenericPathUnsafe for Path {
             None => {
                 self.repr = Path::normalize(filename);
             }
-            Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => {
+            Some(idx) if self.repr.slice_from(idx+1) == b".." => {
                 let mut v = Vec::with_capacity(self.repr.len() + 1 + filename.len());
                 v.push_all(self.repr.as_slice());
                 v.push(SEP_BYTE);
@@ -202,20 +202,20 @@ impl GenericPath for Path {
 
     fn dirname<'a>(&'a self) -> &'a [u8] {
         match self.sepidx {
-            None if bytes!("..") == self.repr.as_slice() => self.repr.as_slice(),
+            None if b".." == self.repr.as_slice() => self.repr.as_slice(),
             None => dot_static,
             Some(0) => self.repr.slice_to(1),
-            Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => self.repr.as_slice(),
+            Some(idx) if self.repr.slice_from(idx+1) == b".." => self.repr.as_slice(),
             Some(idx) => self.repr.slice_to(idx)
         }
     }
 
     fn filename<'a>(&'a self) -> Option<&'a [u8]> {
         match self.sepidx {
-            None if bytes!(".") == self.repr.as_slice() ||
-                bytes!("..") == self.repr.as_slice() => None,
+            None if b"." == self.repr.as_slice() ||
+                b".." == self.repr.as_slice() => None,
             None => Some(self.repr.as_slice()),
-            Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => None,
+            Some(idx) if self.repr.slice_from(idx+1) == b".." => None,
             Some(0) if self.repr.slice_from(1).is_empty() => None,
             Some(idx) => Some(self.repr.slice_from(idx+1))
         }
@@ -223,13 +223,13 @@ impl GenericPath for Path {
 
     fn pop(&mut self) -> bool {
         match self.sepidx {
-            None if bytes!(".") == self.repr.as_slice() => false,
+            None if b"." == self.repr.as_slice() => false,
             None => {
                 self.repr = vec!['.' as u8];
                 self.sepidx = None;
                 true
             }
-            Some(0) if bytes!("/") == self.repr.as_slice() => false,
+            Some(0) if b"/" == self.repr.as_slice() => false,
             Some(idx) => {
                 if idx == 0 {
                     self.repr.truncate(idx+1);
@@ -261,19 +261,19 @@ impl GenericPath for Path {
         } else {
             let mut ita = self.components();
             let mut itb = other.components();
-            if bytes!(".") == self.repr.as_slice() {
+            if b"." == self.repr.as_slice() {
                 return match itb.next() {
                     None => true,
-                    Some(b) => b != bytes!("..")
+                    Some(b) => b != b".."
                 };
             }
             loop {
                 match (ita.next(), itb.next()) {
                     (None, _) => break,
                     (Some(a), Some(b)) if a == b => { continue },
-                    (Some(a), _) if a == bytes!("..") => {
+                    (Some(a), _) if a == b".." => {
                         // if ita contains only .. components, it's an ancestor
-                        return ita.all(|x| x == bytes!(".."));
+                        return ita.all(|x| x == b"..");
                     }
                     _ => return false
                 }
@@ -303,8 +303,8 @@ impl GenericPath for Path {
                     }
                     (None, _) => comps.push(dot_dot_static),
                     (Some(a), Some(b)) if comps.is_empty() && a == b => (),
-                    (Some(a), Some(b)) if b == bytes!(".") => comps.push(a),
-                    (Some(_), Some(b)) if b == bytes!("..") => return None,
+                    (Some(a), Some(b)) if b == b"." => comps.push(a),
+                    (Some(_), Some(b)) if b == b".." => return None,
                     (Some(a), Some(_)) => {
                         comps.push(dot_dot_static);
                         for _ in itb {
@@ -425,8 +425,8 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
     let mut changed = false;
     for comp in v.split(is_sep_byte) {
         if comp.is_empty() { changed = true }
-        else if comp == bytes!(".") { changed = true }
-        else if comp == bytes!("..") {
+        else if comp == b"." { changed = true }
+        else if comp == b".." {
             if is_abs && comps.is_empty() { changed = true }
             else if comps.len() == n_up { comps.push(dot_dot_static); n_up += 1 }
             else { comps.pop().unwrap(); changed = true }
@@ -434,7 +434,7 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
     }
     if changed {
         if comps.is_empty() && !is_abs {
-            if v == bytes!(".") {
+            if v == b"." {
                 return None;
             }
             comps.push(dot_static);
@@ -445,8 +445,8 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
     }
 }
 
-static dot_static: &'static [u8] = bytes!(".");
-static dot_dot_static: &'static [u8] = bytes!("..");
+static dot_static: &'static [u8] = b".";
+static dot_dot_static: &'static [u8] = b"..";
 
 #[cfg(test)]
 mod tests {
@@ -470,24 +470,15 @@ mod tests {
         )
     )
 
-    macro_rules! b(
-        ($($arg:expr),+) => (
-            {
-                static the_bytes: &'static [u8] = bytes!($($arg),+);
-                the_bytes
-            }
-        )
-    )
-
     #[test]
     fn test_paths() {
         let empty: &[u8] = [];
-        t!(v: Path::new(empty), b!("."));
-        t!(v: Path::new(b!("/")), b!("/"));
-        t!(v: Path::new(b!("a/b/c")), b!("a/b/c"));
-        t!(v: Path::new(b!("a/b/c", 0xff)), b!("a/b/c", 0xff));
-        t!(v: Path::new(b!(0xff, "/../foo", 0x80)), b!("foo", 0x80));
-        let p = Path::new(b!("a/b/c", 0xff));
+        t!(v: Path::new(empty), b".");
+        t!(v: Path::new(b"/"), b"/");
+        t!(v: Path::new(b"a/b/c"), b"a/b/c");
+        t!(v: Path::new(b"a/b/c\xFF"), b"a/b/c\xFF");
+        t!(v: Path::new(b"\xFF/../foo\x80"), b"foo\x80");
+        let p = Path::new(b"a/b/c\xFF");
         assert!(p.as_str() == None);
 
         t!(s: Path::new(""), ".");
@@ -513,18 +504,18 @@ mod tests {
         t!(s: Path::new("foo/../../.."), "../..");
         t!(s: Path::new("foo/../../bar"), "../bar");
 
-        assert_eq!(Path::new(b!("foo/bar")).into_vec().as_slice(), b!("foo/bar"));
-        assert_eq!(Path::new(b!("/foo/../../bar")).into_vec().as_slice(),
-                   b!("/bar"));
+        assert_eq!(Path::new(b"foo/bar").into_vec().as_slice(), b"foo/bar");
+        assert_eq!(Path::new(b"/foo/../../bar").into_vec().as_slice(),
+                   b"/bar");
 
-        let p = Path::new(b!("foo/bar", 0x80));
+        let p = Path::new(b"foo/bar\x80");
         assert!(p.as_str() == None);
     }
 
     #[test]
     fn test_opt_paths() {
-        assert!(Path::new_opt(b!("foo/bar", 0)) == None);
-        t!(v: Path::new_opt(b!("foo/bar")).unwrap(), b!("foo/bar"));
+        assert!(Path::new_opt(b"foo/bar\0") == None);
+        t!(v: Path::new_opt(b"foo/bar").unwrap(), b"foo/bar");
         assert!(Path::new_opt("foo/bar\0") == None);
         t!(s: Path::new_opt("foo/bar").unwrap(), "foo/bar");
     }
@@ -533,17 +524,17 @@ mod tests {
     fn test_null_byte() {
         use task;
         let result = task::try(proc() {
-            Path::new(b!("foo/bar", 0))
+            Path::new(b"foo/bar\0")
         });
         assert!(result.is_err());
 
         let result = task::try(proc() {
-            Path::new("test").set_filename(b!("f", 0, "o"))
+            Path::new("test").set_filename(b"f\0o")
         });
         assert!(result.is_err());
 
         let result = task::try(proc() {
-            Path::new("test").push(b!("f", 0, "o"));
+            Path::new("test").push(b"f\0o");
         });
         assert!(result.is_err());
     }
@@ -559,11 +550,11 @@ mod tests {
             )
         )
         t!("foo", display, "foo");
-        t!(b!("foo", 0x80), display, "foo\uFFFD");
-        t!(b!("foo", 0xff, "bar"), display, "foo\uFFFDbar");
-        t!(b!("foo", 0xff, "/bar"), filename_display, "bar");
-        t!(b!("foo/", 0xff, "bar"), filename_display, "\uFFFDbar");
-        t!(b!("/"), filename_display, "");
+        t!(b"foo\x80", display, "foo\uFFFD");
+        t!(b"foo\xFFbar", display, "foo\uFFFDbar");
+        t!(b"foo\xFF/bar", filename_display, "bar");
+        t!(b"foo/\xFFbar", filename_display, "\uFFFDbar");
+        t!(b"/", filename_display, "");
 
         macro_rules! t(
             ($path:expr, $exp:expr) => (
@@ -583,11 +574,11 @@ mod tests {
         )
 
         t!("foo", "foo");
-        t!(b!("foo", 0x80), "foo\uFFFD");
-        t!(b!("foo", 0xff, "bar"), "foo\uFFFDbar");
-        t!(b!("foo", 0xff, "/bar"), "bar", filename);
-        t!(b!("foo/", 0xff, "bar"), "\uFFFDbar", filename);
-        t!(b!("/"), "", filename);
+        t!(b"foo\x80", "foo\uFFFD");
+        t!(b"foo\xFFbar", "foo\uFFFDbar");
+        t!(b"foo\xFF/bar", "bar", filename);
+        t!(b"foo/\xFFbar", "\uFFFDbar", filename);
+        t!(b"/", "", filename);
     }
 
     #[test]
@@ -604,13 +595,13 @@ mod tests {
             )
         )
 
-        t!(b!("foo"), "foo", "foo");
-        t!(b!("foo/bar"), "foo/bar", "bar");
-        t!(b!("/"), "/", "");
-        t!(b!("foo", 0xff), "foo\uFFFD", "foo\uFFFD");
-        t!(b!("foo", 0xff, "/bar"), "foo\uFFFD/bar", "bar");
-        t!(b!("foo/", 0xff, "bar"), "foo/\uFFFDbar", "\uFFFDbar");
-        t!(b!(0xff, "foo/bar", 0xff), "\uFFFDfoo/bar\uFFFD", "bar\uFFFD");
+        t!(b"foo", "foo", "foo");
+        t!(b"foo/bar", "foo/bar", "bar");
+        t!(b"/", "/", "");
+        t!(b"foo\xFF", "foo\uFFFD", "foo\uFFFD");
+        t!(b"foo\xFF/bar", "foo\uFFFD/bar", "bar");
+        t!(b"foo/\xFFbar", "foo/\uFFFDbar", "\uFFFDbar");
+        t!(b"\xFFfoo/bar\xFF", "\uFFFDfoo/bar\uFFFD", "bar\uFFFD");
     }
 
     #[test]
@@ -638,9 +629,9 @@ mod tests {
             );
         )
 
-        t!(v: b!("a/b/c"), filename, Some(b!("c")));
-        t!(v: b!("a/b/c", 0xff), filename, Some(b!("c", 0xff)));
-        t!(v: b!("a/b", 0xff, "/c"), filename, Some(b!("c")));
+        t!(v: b"a/b/c", filename, Some(b"c"));
+        t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF"));
+        t!(v: b"a/b\xFF/c", filename, Some(b"c"));
         t!(s: "a/b/c", filename, Some("c"), opt);
         t!(s: "/a/b/c", filename, Some("c"), opt);
         t!(s: "a", filename, Some("a"), opt);
@@ -650,9 +641,9 @@ mod tests {
         t!(s: "..", filename, None, opt);
         t!(s: "../..", filename, None, opt);
 
-        t!(v: b!("a/b/c"), dirname, b!("a/b"));
-        t!(v: b!("a/b/c", 0xff), dirname, b!("a/b"));
-        t!(v: b!("a/b", 0xff, "/c"), dirname, b!("a/b", 0xff));
+        t!(v: b"a/b/c", dirname, b"a/b");
+        t!(v: b"a/b/c\xFF", dirname, b"a/b");
+        t!(v: b"a/b\xFF/c", dirname, b"a/b\xFF");
         t!(s: "a/b/c", dirname, "a/b");
         t!(s: "/a/b/c", dirname, "/a/b");
         t!(s: "a", dirname, ".");
@@ -662,9 +653,9 @@ mod tests {
         t!(s: "..", dirname, "..");
         t!(s: "../..", dirname, "../..");
 
-        t!(v: b!("hi/there.txt"), filestem, Some(b!("there")));
-        t!(v: b!("hi/there", 0x80, ".txt"), filestem, Some(b!("there", 0x80)));
-        t!(v: b!("hi/there.t", 0x80, "xt"), filestem, Some(b!("there")));
+        t!(v: b"hi/there.txt", filestem, Some(b"there"));
+        t!(v: b"hi/there\x80.txt", filestem, Some(b"there\x80"));
+        t!(v: b"hi/there.t\x80xt", filestem, Some(b"there"));
         t!(s: "hi/there.txt", filestem, Some("there"), opt);
         t!(s: "hi/there", filestem, Some("there"), opt);
         t!(s: "there.txt", filestem, Some("there"), opt);
@@ -678,11 +669,11 @@ mod tests {
         t!(s: "..", filestem, None, opt);
         t!(s: "../..", filestem, None, opt);
 
-        t!(v: b!("hi/there.txt"), extension, Some(b!("txt")));
-        t!(v: b!("hi/there", 0x80, ".txt"), extension, Some(b!("txt")));
-        t!(v: b!("hi/there.t", 0x80, "xt"), extension, Some(b!("t", 0x80, "xt")));
-        t!(v: b!("hi/there"), extension, None);
-        t!(v: b!("hi/there", 0x80), extension, None);
+        t!(v: b"hi/there.txt", extension, Some(b"txt"));
+        t!(v: b"hi/there\x80.txt", extension, Some(b"txt"));
+        t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt"));
+        t!(v: b"hi/there", extension, None);
+        t!(v: b"hi/there\x80", extension, None);
         t!(s: "hi/there.txt", extension, Some("txt"), opt);
         t!(s: "hi/there", extension, None, opt);
         t!(s: "there.txt", extension, Some("txt"), opt);
@@ -762,9 +753,9 @@ mod tests {
         t!(s: "a/b/c", ["d", "/e"], "/e");
         t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
         t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
-        t!(v: b!("a/b/c"), [b!("d"), b!("e")], b!("a/b/c/d/e"));
-        t!(v: b!("a/b/c"), [b!("d"), b!("/e"), b!("f")], b!("/e/f"));
-        t!(v: b!("a/b/c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))], b!("a/b/c/d/e"));
+        t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
+        t!(v: b"a/b/c", [b"d", b"/e", b"f"], b"/e/f");
+        t!(v: b"a/b/c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")], b"a/b/c/d/e");
     }
 
     #[test]
@@ -778,25 +769,25 @@ mod tests {
                     assert!(result == $right);
                 }
             );
-            (v: [$($path:expr),+], [$($left:expr),+], $right:expr) => (
+            (b: $path:expr, $left:expr, $right:expr) => (
                 {
-                    let mut p = Path::new(b!($($path),+));
+                    let mut p = Path::new($path);
                     let result = p.pop();
-                    assert!(p.as_vec() == b!($($left),+));
+                    assert!(p.as_vec() == $left);
                     assert!(result == $right);
                 }
             )
         )
 
-        t!(v: ["a/b/c"], ["a/b"], true);
-        t!(v: ["a"], ["."], true);
-        t!(v: ["."], ["."], false);
-        t!(v: ["/a"], ["/"], true);
-        t!(v: ["/"], ["/"], false);
-        t!(v: ["a/b/c", 0x80], ["a/b"], true);
-        t!(v: ["a/b", 0x80, "/c"], ["a/b", 0x80], true);
-        t!(v: [0xff], ["."], true);
-        t!(v: ["/", 0xff], ["/"], true);
+        t!(b: b"a/b/c", b"a/b", true);
+        t!(b: b"a", b".", true);
+        t!(b: b".", b".", false);
+        t!(b: b"/a", b"/", true);
+        t!(b: b"/", b"/", false);
+        t!(b: b"a/b/c\x80", b"a/b", true);
+        t!(b: b"a/b\x80/c", b"a/b\x80", true);
+        t!(b: b"\xFF", b".", true);
+        t!(b: b"/\xFF", b"/", true);
         t!(s: "a/b/c", "a/b", true);
         t!(s: "a", ".", true);
         t!(s: ".", ".", false);
@@ -806,15 +797,15 @@ mod tests {
 
     #[test]
     fn test_root_path() {
-        assert!(Path::new(b!("a/b/c")).root_path() == None);
-        assert!(Path::new(b!("/a/b/c")).root_path() == Some(Path::new("/")));
+        assert!(Path::new(b"a/b/c").root_path() == None);
+        assert!(Path::new(b"/a/b/c").root_path() == Some(Path::new("/")));
     }
 
     #[test]
     fn test_join() {
-        t!(v: Path::new(b!("a/b/c")).join(b!("..")), b!("a/b"));
-        t!(v: Path::new(b!("/a/b/c")).join(b!("d")), b!("/a/b/c/d"));
-        t!(v: Path::new(b!("a/", 0x80, "/c")).join(b!(0xff)), b!("a/", 0x80, "/c/", 0xff));
+        t!(v: Path::new(b"a/b/c").join(b".."), b"a/b");
+        t!(v: Path::new(b"/a/b/c").join(b"d"), b"/a/b/c/d");
+        t!(v: Path::new(b"a/\x80/c").join(b"\xFF"), b"a/\x80/c/\xFF");
         t!(s: Path::new("a/b/c").join(".."), "a/b");
         t!(s: Path::new("/a/b/c").join("d"), "/a/b/c/d");
         t!(s: Path::new("a/b").join("c/d"), "a/b/c/d");
@@ -867,18 +858,18 @@ mod tests {
         t!(s: "a/b/c", ["..", "d"], "a/b/d");
         t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
         t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
-        t!(v: b!("a/b/c"), [b!("d"), b!("e")], b!("a/b/c/d/e"));
-        t!(v: b!("a/b/c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))], b!("a/b/c/d/e"));
+        t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
+        t!(v: b"a/b/c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")], b"a/b/c/d/e");
     }
 
     #[test]
     fn test_with_helpers() {
         let empty: &[u8] = [];
 
-        t!(v: Path::new(b!("a/b/c")).with_filename(b!("d")), b!("a/b/d"));
-        t!(v: Path::new(b!("a/b/c", 0xff)).with_filename(b!(0x80)), b!("a/b/", 0x80));
-        t!(v: Path::new(b!("/", 0xff, "/foo")).with_filename(b!(0xcd)),
-              b!("/", 0xff, "/", 0xcd));
+        t!(v: Path::new(b"a/b/c").with_filename(b"d"), b"a/b/d");
+        t!(v: Path::new(b"a/b/c\xFF").with_filename(b"\x80"), b"a/b/\x80");
+        t!(v: Path::new(b"/\xFF/foo").with_filename(b"\xCD"),
+              b"/\xFF/\xCD");
         t!(s: Path::new("a/b/c").with_filename("d"), "a/b/d");
         t!(s: Path::new(".").with_filename("foo"), "foo");
         t!(s: Path::new("/a/b/c").with_filename("d"), "/a/b/d");
@@ -899,13 +890,13 @@ mod tests {
         t!(s: Path::new("..").with_filename(""), "..");
         t!(s: Path::new("../..").with_filename(""), "../..");
 
-        t!(v: Path::new(b!("hi/there", 0x80, ".txt")).with_extension(b!("exe")),
-              b!("hi/there", 0x80, ".exe"));
-        t!(v: Path::new(b!("hi/there.txt", 0x80)).with_extension(b!(0xff)),
-              b!("hi/there.", 0xff));
-        t!(v: Path::new(b!("hi/there", 0x80)).with_extension(b!(0xff)),
-              b!("hi/there", 0x80, ".", 0xff));
-        t!(v: Path::new(b!("hi/there.", 0xff)).with_extension(empty), b!("hi/there"));
+        t!(v: Path::new(b"hi/there\x80.txt").with_extension(b"exe"),
+              b"hi/there\x80.exe");
+        t!(v: Path::new(b"hi/there.txt\x80").with_extension(b"\xFF"),
+              b"hi/there.\xFF");
+        t!(v: Path::new(b"hi/there\x80").with_extension(b"\xFF"),
+              b"hi/there\x80.\xFF");
+        t!(v: Path::new(b"hi/there.\xFF").with_extension(empty), b"hi/there");
         t!(s: Path::new("hi/there.txt").with_extension("exe"), "hi/there.exe");
         t!(s: Path::new("hi/there.txt").with_extension(""), "hi/there");
         t!(s: Path::new("hi/there.txt").with_extension("."), "hi/there..");
@@ -947,17 +938,17 @@ mod tests {
             )
         )
 
-        t!(v: b!("a/b/c"), set_filename, with_filename, b!("d"));
-        t!(v: b!("/"), set_filename, with_filename, b!("foo"));
-        t!(v: b!(0x80), set_filename, with_filename, b!(0xff));
+        t!(v: b"a/b/c", set_filename, with_filename, b"d");
+        t!(v: b"/", set_filename, with_filename, b"foo");
+        t!(v: b"\x80", set_filename, with_filename, b"\xFF");
         t!(s: "a/b/c", set_filename, with_filename, "d");
         t!(s: "/", set_filename, with_filename, "foo");
         t!(s: ".", set_filename, with_filename, "foo");
         t!(s: "a/b", set_filename, with_filename, "");
         t!(s: "a", set_filename, with_filename, "");
 
-        t!(v: b!("hi/there.txt"), set_extension, with_extension, b!("exe"));
-        t!(v: b!("hi/there.t", 0x80, "xt"), set_extension, with_extension, b!("exe", 0xff));
+        t!(v: b"hi/there.txt", set_extension, with_extension, b"exe");
+        t!(v: b"hi/there.t\x80xt", set_extension, with_extension, b"exe\xFF");
         t!(s: "hi/there.txt", set_extension, with_extension, "exe");
         t!(s: "hi/there.", set_extension, with_extension, "txt");
         t!(s: "hi/there", set_extension, with_extension, "txt");
@@ -1001,10 +992,10 @@ mod tests {
             )
         )
 
-        t!(v: Path::new(b!("a/b/c")), Some(b!("c")), b!("a/b"), Some(b!("c")), None);
-        t!(v: Path::new(b!("a/b/", 0xff)), Some(b!(0xff)), b!("a/b"), Some(b!(0xff)), None);
-        t!(v: Path::new(b!("hi/there.", 0xff)), Some(b!("there.", 0xff)), b!("hi"),
-              Some(b!("there")), Some(b!(0xff)));
+        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
+        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
+        t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi",
+              Some(b"there"), Some(b"\xFF"));
         t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
         t!(s: Path::new("."), None, Some("."), None, None);
         t!(s: Path::new("/"), None, Some("/"), None, None);
@@ -1018,16 +1009,16 @@ mod tests {
         t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None);
         t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"),
               Some("."), Some("there"));
-        t!(s: Path::new(b!("a/b/", 0xff)), None, Some("a/b"), None, None);
-        t!(s: Path::new(b!("a/b/", 0xff, ".txt")), None, Some("a/b"), None, Some("txt"));
-        t!(s: Path::new(b!("a/b/c.", 0x80)), None, Some("a/b"), Some("c"), None);
-        t!(s: Path::new(b!(0xff, "/b")), Some("b"), None, Some("b"), None);
+        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None);
+        t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt"));
+        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None);
+        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None);
     }
 
     #[test]
     fn test_dir_path() {
-        t!(v: Path::new(b!("hi/there", 0x80)).dir_path(), b!("hi"));
-        t!(v: Path::new(b!("hi", 0xff, "/there")).dir_path(), b!("hi", 0xff));
+        t!(v: Path::new(b"hi/there\x80").dir_path(), b"hi");
+        t!(v: Path::new(b"hi\xFF/there").dir_path(), b"hi\xFF");
         t!(s: Path::new("hi/there").dir_path(), "hi");
         t!(s: Path::new("hi").dir_path(), ".");
         t!(s: Path::new("/hi").dir_path(), "/");
@@ -1125,9 +1116,9 @@ mod tests {
         t!(s: "/a/b/c", "d/e/f", false);
         t!(s: "a/b/c", "a/b", false);
         t!(s: "a/b/c", "b", false);
-        t!(v: b!("a/b/c"), b!("b/c"), true);
-        t!(v: b!("a/b/", 0xff), b!(0xff), true);
-        t!(v: b!("a/b/", 0xff), b!("b/", 0xff), true);
+        t!(v: b"a/b/c", b"b/c", true);
+        t!(v: b"a/b/\xFF", b"\xFF", true);
+        t!(v: b"a/b/\xFF", b"b/\xFF", true);
     }
 
     #[test]
@@ -1192,11 +1183,11 @@ mod tests {
                             comps, exps);
                 }
             );
-            (v: [$($arg:expr),+], [$([$($exp:expr),*]),*]) => (
+            (b: $arg:expr, [$($exp:expr),*]) => (
                 {
-                    let path = Path::new(b!($($arg),+));
+                    let path = Path::new($arg);
                     let comps = path.components().collect::<Vec<&[u8]>>();
-                    let exp: &[&[u8]] = [$(b!($($exp),*)),*];
+                    let exp: &[&[u8]] = [$($exp),*];
                     assert_eq!(comps.as_slice(), exp);
                     let comps = path.components().rev().collect::<Vec<&[u8]>>();
                     let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
@@ -1205,9 +1196,9 @@ mod tests {
             )
         )
 
-        t!(v: ["a/b/c"], [["a"], ["b"], ["c"]]);
-        t!(v: ["/", 0xff, "/a/", 0x80], [[0xff], ["a"], [0x80]]);
-        t!(v: ["../../foo", 0xcd, "bar"], [[".."], [".."], ["foo", 0xcd, "bar"]]);
+        t!(b: b"a/b/c", [b"a", b"b", b"c"]);
+        t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]);
+        t!(b: b"../../foo\xCDbar", [b"..", b"..", b"foo\xCDbar"]);
         t!(s: "a/b/c", ["a", "b", "c"]);
         t!(s: "a/b/d", ["a", "b", "d"]);
         t!(s: "a/b/cd", ["a", "b", "cd"]);
@@ -1224,9 +1215,9 @@ mod tests {
     #[test]
     fn test_str_components() {
         macro_rules! t(
-            (v: [$($arg:expr),+], $exp:expr) => (
+            (b: $arg:expr, $exp:expr) => (
                 {
-                    let path = Path::new(b!($($arg),+));
+                    let path = Path::new($arg);
                     let comps = path.str_components().collect::<Vec<Option<&str>>>();
                     let exp: &[Option<&str>] = $exp;
                     assert_eq!(comps.as_slice(), exp);
@@ -1237,9 +1228,9 @@ mod tests {
             )
         )
 
-        t!(v: ["a/b/c"], [Some("a"), Some("b"), Some("c")]);
-        t!(v: ["/", 0xff, "/a/", 0x80], [None, Some("a"), None]);
-        t!(v: ["../../foo", 0xcd, "bar"], [Some(".."), Some(".."), None]);
+        t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]);
+        t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]);
+        t!(b: b"../../foo\xCDbar", [Some(".."), Some(".."), None]);
         // str_components is a wrapper around components, so no need to do
         // the full set of tests
     }
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 553c7af18cb..4d6f8d0888f 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -1123,15 +1123,6 @@ mod tests {
         )
     )
 
-    macro_rules! b(
-        ($($arg:expr),+) => (
-            {
-                static the_bytes: &'static [u8] = bytes!($($arg),+);
-                the_bytes
-            }
-        )
-    )
-
     #[test]
     fn test_parse_prefix() {
         macro_rules! t(
@@ -1196,9 +1187,9 @@ mod tests {
     #[test]
     fn test_paths() {
         let empty: &[u8] = [];
-        t!(v: Path::new(empty), b!("."));
-        t!(v: Path::new(b!("\\")), b!("\\"));
-        t!(v: Path::new(b!("a\\b\\c")), b!("a\\b\\c"));
+        t!(v: Path::new(empty), b".");
+        t!(v: Path::new(b"\\"), b"\\");
+        t!(v: Path::new(b"a\\b\\c"), b"a\\b\\c");
 
         t!(s: Path::new(""), ".");
         t!(s: Path::new("\\"), "\\");
@@ -1230,8 +1221,8 @@ mod tests {
         t!(s: Path::new("foo\\..\\..\\.."), "..\\..");
         t!(s: Path::new("foo\\..\\..\\bar"), "..\\bar");
 
-        assert_eq!(Path::new(b!("foo\\bar")).into_vec().as_slice(), b!("foo\\bar"));
-        assert_eq!(Path::new(b!("\\foo\\..\\..\\bar")).into_vec().as_slice(), b!("\\bar"));
+        assert_eq!(Path::new(b"foo\\bar").into_vec().as_slice(), b"foo\\bar");
+        assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec().as_slice(), b"\\bar");
 
         t!(s: Path::new("\\\\a"), "\\a");
         t!(s: Path::new("\\\\a\\"), "\\a");
@@ -1284,9 +1275,9 @@ mod tests {
 
     #[test]
     fn test_opt_paths() {
-        assert!(Path::new_opt(b!("foo\\bar", 0)) == None);
-        assert!(Path::new_opt(b!("foo\\bar", 0x80)) == None);
-        t!(v: Path::new_opt(b!("foo\\bar")).unwrap(), b!("foo\\bar"));
+        assert!(Path::new_opt(b"foo\\bar\0") == None);
+        assert!(Path::new_opt(b"foo\\bar\x80") == None);
+        t!(v: Path::new_opt(b"foo\\bar").unwrap(), b"foo\\bar");
         assert!(Path::new_opt("foo\\bar\0") == None);
         t!(s: Path::new_opt("foo\\bar").unwrap(), "foo\\bar");
     }
@@ -1295,17 +1286,17 @@ mod tests {
     fn test_null_byte() {
         use task;
         let result = task::try(proc() {
-            Path::new(b!("foo/bar", 0))
+            Path::new(b"foo/bar\0")
         });
         assert!(result.is_err());
 
         let result = task::try(proc() {
-            Path::new("test").set_filename(b!("f", 0, "o"))
+            Path::new("test").set_filename(b"f\0o")
         });
         assert!(result.is_err());
 
         let result = task::try(proc() {
-            Path::new("test").push(b!("f", 0, "o"));
+            Path::new("test").push(b"f\0o");
         });
         assert!(result.is_err());
     }
@@ -1313,20 +1304,20 @@ mod tests {
     #[test]
     #[should_fail]
     fn test_not_utf8_fail() {
-        Path::new(b!("hello", 0x80, ".txt"));
+        Path::new(b"hello\x80.txt");
     }
 
     #[test]
     fn test_display_str() {
         let path = Path::new("foo");
         assert_eq!(path.display().to_str(), "foo".to_string());
-        let path = Path::new(b!("\\"));
+        let path = Path::new(b"\\");
         assert_eq!(path.filename_display().to_str(), "".to_string());
 
         let path = Path::new("foo");
         let mo = path.display().as_maybe_owned();
         assert_eq!(mo.as_slice(), "foo");
-        let path = Path::new(b!("\\"));
+        let path = Path::new(b"\\");
         let mo = path.filename_display().as_maybe_owned();
         assert_eq!(mo.as_slice(), "");
     }
@@ -1377,7 +1368,7 @@ mod tests {
             )
         )
 
-        t!(v: b!("a\\b\\c"), filename, Some(b!("c")));
+        t!(v: b"a\\b\\c", filename, Some(b"c"));
         t!(s: "a\\b\\c", filename_str, "c");
         t!(s: "\\a\\b\\c", filename_str, "c");
         t!(s: "a", filename_str, "a");
@@ -1410,7 +1401,7 @@ mod tests {
         t!(s: "\\\\.\\", filename_str, None, opt);
         t!(s: "\\\\?\\a\\b\\", filename_str, "b");
 
-        t!(v: b!("a\\b\\c"), dirname, b!("a\\b"));
+        t!(v: b"a\\b\\c", dirname, b"a\\b");
         t!(s: "a\\b\\c", dirname_str, "a\\b");
         t!(s: "\\a\\b\\c", dirname_str, "\\a\\b");
         t!(s: "a", dirname_str, ".");
@@ -1441,7 +1432,7 @@ mod tests {
         t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo");
         t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a");
 
-        t!(v: b!("hi\\there.txt"), filestem, Some(b!("there")));
+        t!(v: b"hi\\there.txt", filestem, Some(b"there"));
         t!(s: "hi\\there.txt", filestem_str, "there");
         t!(s: "hi\\there", filestem_str, "there");
         t!(s: "there.txt", filestem_str, "there");
@@ -1456,8 +1447,8 @@ mod tests {
         t!(s: "..\\..", filestem_str, None, opt);
         // filestem is based on filename, so we don't need the full set of prefix tests
 
-        t!(v: b!("hi\\there.txt"), extension, Some(b!("txt")));
-        t!(v: b!("hi\\there"), extension, None);
+        t!(v: b"hi\\there.txt", extension, Some(b"txt"));
+        t!(v: b"hi\\there", extension, None);
         t!(s: "hi\\there.txt", extension_str, Some("txt"), opt);
         t!(s: "hi\\there", extension_str, None, opt);
         t!(s: "there.txt", extension_str, Some("txt"), opt);
@@ -1583,10 +1574,10 @@ mod tests {
         t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
         t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
         t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
-        t!(v: b!("a\\b\\c"), [b!("d"), b!("e")], b!("a\\b\\c\\d\\e"));
-        t!(v: b!("a\\b\\c"), [b!("d"), b!("\\e"), b!("f")], b!("\\e\\f"));
-        t!(v: b!("a\\b\\c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))],
-           b!("a\\b\\c\\d\\e"));
+        t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
+        t!(v: b"a\\b\\c", [b"d", b"\\e", b"f"], b"\\e\\f");
+        t!(v: b"a\\b\\c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")],
+           b"a\\b\\c\\d\\e");
     }
 
     #[test]
@@ -1604,11 +1595,11 @@ mod tests {
                     assert!(result == $right);
                 }
             );
-            (v: [$($path:expr),+], [$($left:expr),+], $right:expr) => (
+            (b: $path:expr, $left:expr, $right:expr) => (
                 {
-                    let mut p = Path::new(b!($($path),+));
+                    let mut p = Path::new($path);
                     let result = p.pop();
-                    assert_eq!(p.as_vec(), b!($($left),+));
+                    assert_eq!(p.as_vec(), $left);
                     assert!(result == $right);
                 }
             )
@@ -1619,11 +1610,11 @@ mod tests {
         t!(s: ".", ".", false);
         t!(s: "\\a", "\\", true);
         t!(s: "\\", "\\", false);
-        t!(v: ["a\\b\\c"], ["a\\b"], true);
-        t!(v: ["a"], ["."], true);
-        t!(v: ["."], ["."], false);
-        t!(v: ["\\a"], ["\\"], true);
-        t!(v: ["\\"], ["\\"], false);
+        t!(b: b"a\\b\\c", b"a\\b", true);
+        t!(b: b"a", b".", true);
+        t!(b: b".", b".", false);
+        t!(b: b"\\a", b"\\", true);
+        t!(b: b"\\", b"\\", false);
 
         t!(s: "C:\\a\\b", "C:\\a", true);
         t!(s: "C:\\a", "C:\\", true);
@@ -1672,8 +1663,8 @@ mod tests {
         t!(s: Path::new("a\\b").join("\\c\\d"), "\\c\\d");
         t!(s: Path::new(".").join("a\\b"), "a\\b");
         t!(s: Path::new("\\").join("a\\b"), "\\a\\b");
-        t!(v: Path::new(b!("a\\b\\c")).join(b!("..")), b!("a\\b"));
-        t!(v: Path::new(b!("\\a\\b\\c")).join(b!("d")), b!("\\a\\b\\c\\d"));
+        t!(v: Path::new(b"a\\b\\c").join(b".."), b"a\\b");
+        t!(v: Path::new(b"\\a\\b\\c").join(b"d"), b"\\a\\b\\c\\d");
         // full join testing is covered under test_push_path, so no need for
         // the full set of prefix tests
     }
@@ -1724,9 +1715,9 @@ mod tests {
         t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d");
         t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
         t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
-        t!(v: b!("a\\b\\c"), [b!("d"), b!("e")], b!("a\\b\\c\\d\\e"));
-        t!(v: b!("a\\b\\c"), [Vec::from_slice(b!("d")), Vec::from_slice(b!("e"))],
-           b!("a\\b\\c\\d\\e"));
+        t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
+        t!(v: b"a\\b\\c", [Vec::from_slice(b"d"), Vec::from_slice(b"e")],
+           b"a\\b\\c\\d\\e");
     }
 
     #[test]
@@ -1839,15 +1830,15 @@ mod tests {
             )
         )
 
-        t!(v: b!("a\\b\\c"), set_filename, with_filename, b!("d"));
-        t!(v: b!("\\"), set_filename, with_filename, b!("foo"));
+        t!(v: b"a\\b\\c", set_filename, with_filename, b"d");
+        t!(v: b"\\", set_filename, with_filename, b"foo");
         t!(s: "a\\b\\c", set_filename, with_filename, "d");
         t!(s: "\\", set_filename, with_filename, "foo");
         t!(s: ".", set_filename, with_filename, "foo");
         t!(s: "a\\b", set_filename, with_filename, "");
         t!(s: "a", set_filename, with_filename, "");
 
-        t!(v: b!("hi\\there.txt"), set_extension, with_extension, b!("exe"));
+        t!(v: b"hi\\there.txt", set_extension, with_extension, b"exe");
         t!(s: "hi\\there.txt", set_extension, with_extension, "exe");
         t!(s: "hi\\there.", set_extension, with_extension, "txt");
         t!(s: "hi\\there", set_extension, with_extension, "txt");
@@ -1894,7 +1885,7 @@ mod tests {
             )
         )
 
-        t!(v: Path::new(b!("a\\b\\c")), Some(b!("c")), b!("a\\b"), Some(b!("c")), None);
+        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
         t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
         t!(s: Path::new("."), None, Some("."), None, None);
         t!(s: Path::new("\\"), None, Some("\\"), None, None);
@@ -2250,21 +2241,9 @@ mod tests {
                     assert_eq!(comps, exp);
                 }
             );
-            (v: [$($arg:expr),+], $exp:expr) => (
-                {
-                    let path = Path::new(b!($($arg),+));
-                    let comps = path.str_components().map(|x|x.unwrap()).collect::<Vec<&str>>();
-                    let exp: &[&str] = $exp;
-                    assert_eq!(comps.as_slice(), exp);
-                    let comps = path.str_components().rev().map(|x|x.unwrap())
-                                .collect::<Vec<&str>>();
-                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&str>>();
-                    assert_eq!(comps, exp);
-                }
-            )
         )
 
-        t!(v: ["a\\b\\c"], ["a", "b", "c"]);
+        t!(s: b"a\\b\\c", ["a", "b", "c"]);
         t!(s: "a\\b\\c", ["a", "b", "c"]);
         t!(s: "a\\b\\d", ["a", "b", "d"]);
         t!(s: "a\\b\\cd", ["a", "b", "cd"]);
@@ -2320,8 +2299,8 @@ mod tests {
             )
         )
 
-        t!(s: "a\\b\\c", [b!("a"), b!("b"), b!("c")]);
-        t!(s: ".", [b!(".")]);
+        t!(s: "a\\b\\c", [b"a", b"b", b"c"]);
+        t!(s: ".", [b"."]);
         // since this is really a wrapper around str_components, those tests suffice
     }
 
diff --git a/src/libstd/task.rs b/src/libstd/task.rs
index f543188af42..0ead8fa6c0c 100644
--- a/src/libstd/task.rs
+++ b/src/libstd/task.rs
@@ -8,71 +8,110 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
- * Utilities for managing and scheduling tasks
- *
- * An executing Rust program consists of a collection of tasks, each with their
- * own stack, and sole ownership of their allocated heap data. Tasks communicate
- * with each other using channels (see `std::comm` for more info about how
- * communication works).
- *
- * Failure in one task does not propagate to any others (not to parent, not to
- * child).  Failure propagation is instead handled by using the channel send()
- * and recv() methods which will fail if the other end has hung up already.
- *
- * Task Scheduling:
- *
- * By default, every task is created with the same "flavor" as the calling task.
- * This flavor refers to the scheduling mode, with two possibilities currently
- * being 1:1 and M:N modes. Green (M:N) tasks are cooperatively scheduled and
- * native (1:1) tasks are scheduled by the OS kernel.
- *
- * # Example
- *
- * ```rust
- * spawn(proc() {
- *     println!("Hello, World!");
- * })
- * ```
- */
+//! Utilities for managing and scheduling tasks
+//!
+//! An executing Rust program consists of a collection of lightweight tasks,
+//! each with their own stack. Tasks communicate with each other using channels
+//! (see `std::comm`) or other forms of synchronization (see `std::sync`) that
+//! ensure data-race freedom.
+//!
+//! Failure in one task does immediately propagate to any others (not to parent,
+//! not to child). Failure propagation is instead handled as part of task
+//! synchronization. For example, the channel `send()` and `recv()` methods will
+//! fail if the other end has hung up already.
+//!
+//! # Basic task scheduling
+//!
+//! By default, every task is created with the same "flavor" as the calling task.
+//! This flavor refers to the scheduling mode, with two possibilities currently
+//! being 1:1 and M:N modes. Green (M:N) tasks are cooperatively scheduled and
+//! native (1:1) tasks are scheduled by the OS kernel.
+//!
+//! ## Example
+//!
+//! ```rust
+//! spawn(proc() {
+//!     println!("Hello, World!");
+//! })
+//! ```
+//!
+//! # Advanced task scheduling
+//!
+//! Task spawning can also be configured to use a particular scheduler, to
+//! redirect the new task's output, or to yield a `future` representing the
+//! task's final result. The configuration is established using the
+//! `TaskBuilder` API:
+//!
+//! ## Example
+//!
+//! ```rust
+//! extern crate green;
+//! extern crate native;
+//!
+//! use std::task::TaskBuilder;
+//! use green::{SchedPool, PoolConfig, GreenTaskBuilder};
+//! use native::NativeTaskBuilder;
+//!
+//! # fn main() {
+//! // Create a green scheduler pool with the default configuration
+//! let mut pool = SchedPool::new(PoolConfig::new());
+//!
+//! // Spawn a task in the green pool
+//! let mut fut_green = TaskBuilder::new().green(&mut pool).try_future(proc() {
+//!     /* ... */
+//! });
+//!
+//! // Spawn a native task
+//! let mut fut_native = TaskBuilder::new().native().try_future(proc() {
+//!     /* ... */
+//! });
+//!
+//! // Wait for both tasks to finish, recording their outcome
+//! let res_green  = fut_green.unwrap();
+//! let res_native = fut_native.unwrap();
+//!
+//! // Shut down the green scheduler pool
+//! pool.shutdown();
+//! # }
+//! ```
 
 use any::Any;
-use comm::{Sender, Receiver, channel};
+use comm::channel;
 use io::{Writer, stdio};
 use kinds::{Send, marker};
 use option::{None, Some, Option};
 use owned::Box;
-use result::{Result, Ok, Err};
+use result::Result;
 use rt::local::Local;
 use rt::task;
 use rt::task::Task;
 use str::{Str, SendStr, IntoMaybeOwned};
+use sync::Future;
 
-#[cfg(test)] use any::AnyRefExt;
-#[cfg(test)] use owned::AnyOwnExt;
-#[cfg(test)] use result;
-#[cfg(test)] use str::StrAllocating;
-#[cfg(test)] use string::String;
-
-/// Task configuration options
-pub struct TaskOpts {
-    /// Enable lifecycle notifications on the given channel
-    pub notify_chan: Option<Sender<task::Result>>,
-    /// A name for the task-to-be, for identification in failure messages
-    pub name: Option<SendStr>,
-    /// The size of the stack for the spawned task
-    pub stack_size: Option<uint>,
-    /// Task-local stdout
-    pub stdout: Option<Box<Writer + Send>>,
-    /// Task-local stderr
-    pub stderr: Option<Box<Writer + Send>>,
+/// A means of spawning a task
+pub trait Spawner {
+    /// Spawn a task, given low-level task options.
+    fn spawn(self, opts: task::TaskOpts, f: proc():Send);
 }
 
-/**
- * The task builder type.
- *
- * Provides detailed control over the properties and behavior of new tasks.
- */
+/// The default task spawner, which spawns siblings to the current task.
+pub struct SiblingSpawner;
+
+impl Spawner for SiblingSpawner {
+    fn spawn(self, opts: task::TaskOpts, f: proc():Send) {
+        // bind tb to provide type annotation
+        let tb: Option<Box<Task>> = Local::try_take();
+        match tb {
+            Some(t) => t.spawn_sibling(opts, f),
+            None => fail!("need a local task to spawn a sibling task"),
+        };
+    }
+}
+
+/// The task builder type.
+///
+/// Provides detailed control over the properties and behavior of new tasks.
+
 // NB: Builders are designed to be single-use because they do stateful
 // things that get weird when reusing - e.g. if you create a result future
 // it only applies to a single task, so then you have to maintain Some
@@ -80,75 +119,102 @@ pub struct TaskOpts {
 // when you try to reuse the builder to spawn a new task. We'll just
 // sidestep that whole issue by making builders uncopyable and making
 // the run function move them in.
-pub struct TaskBuilder {
-    /// Options to spawn the new task with
-    pub opts: TaskOpts,
-    gen_body: Option<proc(v: proc(): Send): Send -> proc(): Send>,
+pub struct TaskBuilder<S = SiblingSpawner> {
+    // A name for the task-to-be, for identification in failure messages
+    name: Option<SendStr>,
+    // The size of the stack for the spawned task
+    stack_size: Option<uint>,
+    // Task-local stdout
+    stdout: Option<Box<Writer + Send>>,
+    // Task-local stderr
+    stderr: Option<Box<Writer + Send>>,
+    // The mechanics of actually spawning the task (i.e.: green or native)
+    spawner: S,
+    // Optionally wrap the eventual task body
+    gen_body: Option<proc(v: proc():Send):Send -> proc():Send>,
     nocopy: marker::NoCopy,
 }
 
-impl TaskBuilder {
-     /// Generate the base configuration for spawning a task, off of which more
-     /// configuration methods can be chained.
-    pub fn new() -> TaskBuilder {
+impl TaskBuilder<SiblingSpawner> {
+    /// Generate the base configuration for spawning a task, off of which more
+    /// configuration methods can be chained.
+    pub fn new() -> TaskBuilder<SiblingSpawner> {
         TaskBuilder {
-            opts: TaskOpts::new(),
+            name: None,
+            stack_size: None,
+            stdout: None,
+            stderr: None,
+            spawner: SiblingSpawner,
             gen_body: None,
             nocopy: marker::NoCopy,
         }
     }
+}
 
-    /// Get a future representing the exit status of the task.
-    ///
-    /// Taking the value of the future will block until the child task
-    /// terminates. The future result return value will be created *before* the task is
-    /// spawned; as such, do not invoke .get() on it directly;
-    /// rather, store it in an outer variable/list for later use.
-    ///
-    /// # Failure
-    /// Fails if a future_result was already set for this task.
-    pub fn future_result(&mut self) -> Receiver<task::Result> {
-        // FIXME (#3725): Once linked failure and notification are
-        // handled in the library, I can imagine implementing this by just
-        // registering an arbitrary number of task::on_exit handlers and
-        // sending out messages.
-
-        if self.opts.notify_chan.is_some() {
-            fail!("Can't set multiple future_results for one task!");
-        }
-
-        // Construct the future and give it to the caller.
-        let (tx, rx) = channel();
+impl<S: Spawner> TaskBuilder<S> {
+    /// Name the task-to-be. Currently the name is used for identification
+    /// only in failure messages.
+    pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder<S> {
+        self.name = Some(name.into_maybe_owned());
+        self
+    }
 
-        // Reconfigure self to use a notify channel.
-        self.opts.notify_chan = Some(tx);
+    /// Set the size of the stack for the new task.
+    pub fn stack_size(mut self, size: uint) -> TaskBuilder<S> {
+        self.stack_size = Some(size);
+        self
+    }
 
-        rx
+    /// Redirect task-local stdout.
+    pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder<S> {
+        self.stdout = Some(stdout);
+        self
     }
 
-    /// Name the task-to-be. Currently the name is used for identification
-    /// only in failure messages.
-    pub fn named<S: IntoMaybeOwned<'static>>(mut self, name: S) -> TaskBuilder {
-        self.opts.name = Some(name.into_maybe_owned());
+    /// Redirect task-local stderr.
+    pub fn stderr(mut self, stderr: Box<Writer + Send>) -> TaskBuilder<S> {
+        self.stderr = Some(stderr);
         self
     }
 
-    /**
-     * Add a wrapper to the body of the spawned task.
-     *
-     * Before the task is spawned it is passed through a 'body generator'
-     * function that may perform local setup operations as well as wrap
-     * the task body in remote setup operations. With this the behavior
-     * of tasks can be extended in simple ways.
-     *
-     * This function augments the current body generator with a new body
-     * generator by applying the task body which results from the
-     * existing body generator to the new body generator.
-     */
-    pub fn with_wrapper(mut self,
-                        wrapper: proc(v: proc(): Send): Send -> proc(): Send)
-        -> TaskBuilder
-    {
+    /// Set the spawning mechanism for the task.
+    ///
+    /// The `TaskBuilder` API configures a task to be spawned, but defers to the
+    /// "spawner" to actually create and spawn the task. The `spawner` method
+    /// should not be called directly by `TaskBuiler` clients. It is intended
+    /// for use by downstream crates (like `native` and `green`) that implement
+    /// tasks. These downstream crates then add extension methods to the
+    /// builder, like `.native()` and `.green(pool)`, that actually set the
+    /// spawner.
+    pub fn spawner<T: Spawner>(self, spawner: T) -> TaskBuilder<T> {
+        // repackage the entire TaskBuilder since its type is changing.
+        let TaskBuilder {
+            name, stack_size, stdout, stderr, spawner: _, gen_body, nocopy
+        } = self;
+        TaskBuilder {
+            name: name,
+            stack_size: stack_size,
+            stdout: stdout,
+            stderr: stderr,
+            spawner: spawner,
+            gen_body: gen_body,
+            nocopy: nocopy,
+        }
+    }
+
+    /// Add a wrapper to the body of the spawned task.
+    ///
+    /// Before the task is spawned it is passed through a 'body generator'
+    /// function that may perform local setup operations as well as wrap
+    /// the task body in remote setup operations. With this the behavior
+    /// of tasks can be extended in simple ways.
+    ///
+    /// This function augments the current body generator with a new body
+    /// generator by applying the task body which results from the
+    /// existing body generator to the new body generator.
+    #[deprecated = "this function will be removed soon"]
+    pub fn with_wrapper(mut self, wrapper: proc(v: proc():Send):Send -> proc():Send)
+                        -> TaskBuilder<S> {
         self.gen_body = match self.gen_body.take() {
             Some(prev) => Some(proc(body) { wrapper(prev(body)) }),
             None => Some(wrapper)
@@ -156,90 +222,80 @@ impl TaskBuilder {
         self
     }
 
-    /**
-     * Creates and executes a new child task
-     *
-     * Sets up a new task with its own call stack and schedules it to run
-     * the provided unique closure. The task has the properties and behavior
-     * specified by the task_builder.
-     */
-    pub fn spawn(mut self, f: proc(): Send) {
-        let gen_body = self.gen_body.take();
-        let f = match gen_body {
+    // Where spawning actually happens (whether yielding a future or not)
+    fn spawn_internal(self, f: proc():Send,
+                      on_exit: Option<proc(Result<(), Box<Any + Send>>):Send>) {
+        let TaskBuilder {
+            name, stack_size, stdout, stderr, spawner, mut gen_body, nocopy: _
+        } = self;
+        let f = match gen_body.take() {
             Some(gen) => gen(f),
             None => f
         };
-        let t: Box<Task> = match Local::try_take() {
-            Some(t) => t,
-            None => fail!("need a local task to spawn a new task"),
-        };
-        let TaskOpts { notify_chan, name, stack_size, stdout, stderr } = self.opts;
-
         let opts = task::TaskOpts {
-            on_exit: notify_chan.map(|c| proc(r) c.send(r)),
+            on_exit: on_exit,
             name: name,
             stack_size: stack_size,
         };
         if stdout.is_some() || stderr.is_some() {
-            t.spawn_sibling(opts, proc() {
+            spawner.spawn(opts, proc() {
                 let _ = stdout.map(stdio::set_stdout);
                 let _ = stderr.map(stdio::set_stderr);
                 f();
-            });
+            })
         } else {
-            t.spawn_sibling(opts, f);
+            spawner.spawn(opts, f)
         }
     }
 
-    /**
-     * Execute a function in another task and return either the return value
-     * of the function or result::err.
-     *
-     * # Return value
-     *
-     * If the function executed successfully then try returns result::ok
-     * containing the value returned by the function. If the function fails
-     * then try returns result::err containing nil.
-     *
-     * # Failure
-     * Fails if a future_result was already set for this task.
-     */
-    pub fn try<T: Send>(mut self, f: proc(): Send -> T)
-               -> Result<T, Box<Any + Send>> {
-        let (tx, rx) = channel();
-
-        let result = self.future_result();
-
-        self.spawn(proc() {
-            tx.send(f());
-        });
-
-        match result.recv() {
-            Ok(())     => Ok(rx.recv()),
-            Err(cause) => Err(cause)
-        }
+    /// Creates and executes a new child task.
+    ///
+    /// Sets up a new task with its own call stack and schedules it to run
+    /// the provided proc. The task has the properties and behavior
+    /// specified by the `TaskBuilder`.
+    pub fn spawn(self, f: proc():Send) {
+        self.spawn_internal(f, None)
     }
-}
-
-/* Task construction */
 
-impl TaskOpts {
-    pub fn new() -> TaskOpts {
-        /*!
-         * The default task options
-         */
+    /// Execute a proc in a newly-spawned task and return a future representing
+    /// the task's result. The task has the properties and behavior
+    /// specified by the `TaskBuilder`.
+    ///
+    /// Taking the value of the future will block until the child task
+    /// terminates.
+    ///
+    /// # Return value
+    ///
+    /// If the child task executes successfully (without failing) then the
+    /// future returns `result::Ok` containing the value returned by the
+    /// function. If the child task fails then the future returns `result::Err`
+    /// containing the argument to `fail!(...)` as an `Any` trait object.
+    pub fn try_future<T:Send>(self, f: proc():Send -> T)
+                              -> Future<Result<T, Box<Any + Send>>> {
+        // currently, the on_exit proc provided by librustrt only works for unit
+        // results, so we use an additional side-channel to communicate the
+        // result.
+
+        let (tx_done, rx_done) = channel(); // signal that task has exited
+        let (tx_retv, rx_retv) = channel(); // return value from task
+
+        let on_exit = proc(res) { tx_done.send(res) };
+        self.spawn_internal(proc() { tx_retv.send(f()) },
+                            Some(on_exit));
+
+        Future::from_fn(proc() {
+            rx_done.recv().map(|_| rx_retv.recv())
+        })
+    }
 
-        TaskOpts {
-            notify_chan: None,
-            name: None,
-            stack_size: None,
-            stdout: None,
-            stderr: None,
-        }
+    /// Execute a function in a newly-spawnedtask and block until the task
+    /// completes or fails. Equivalent to `.try_future(f).unwrap()`.
+    pub fn try<T:Send>(self, f: proc():Send -> T) -> Result<T, Box<Any + Send>> {
+        self.try_future(f).unwrap()
     }
 }
 
-/* Spawn convenience functions */
+/* Convenience functions */
 
 /// Creates and executes a new child task
 ///
@@ -251,14 +307,22 @@ pub fn spawn(f: proc(): Send) {
     TaskBuilder::new().spawn(f)
 }
 
-/// Execute a function in another task and return either the return value of
-/// the function or an error if the task failed
+/// Execute a function in a newly-spawned task and return either the return
+/// value of the function or an error if the task failed.
 ///
-/// This is equivalent to TaskBuilder::new().try
+/// This is equivalent to `TaskBuilder::new().try`.
 pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
     TaskBuilder::new().try(f)
 }
 
+/// Execute a function in another task and return a future representing the
+/// task's result.
+///
+/// This is equivalent to `TaskBuilder::new().try_future`.
+pub fn try_future<T:Send>(f: proc():Send -> T) -> Future<Result<T, Box<Any + Send>>> {
+    TaskBuilder::new().try_future(f)
+}
+
 
 /* Lifecycle functions */
 
@@ -273,9 +337,8 @@ pub fn with_task_name<U>(blk: |Option<&str>| -> U) -> U {
     }
 }
 
+/// Yield control to the task scheduler.
 pub fn deschedule() {
-    //! Yield control to the task scheduler
-
     use rt::local::Local;
 
     // FIXME(#7544): Optimize this, since we know we won't block.
@@ -283,266 +346,282 @@ pub fn deschedule() {
     task.yield_now();
 }
 
+/// True if the running task is currently failing (e.g. will return `true` inside a
+/// destructor that is run while unwinding the stack after a call to `fail!()`).
 pub fn failing() -> bool {
-    //! True if the running task has failed
     use rt::task::Task;
     Local::borrow(None::<Task>).unwinder.unwinding()
 }
 
-// The following 8 tests test the following 2^3 combinations:
-// {un,}linked {un,}supervised failure propagation {up,down}wards.
-
-// !!! These tests are dangerous. If Something is buggy, they will hang, !!!
-// !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
-
-#[test]
-fn test_unnamed_task() {
-    spawn(proc() {
-        with_task_name(|name| {
-            assert!(name.is_none());
+#[cfg(test)]
+mod test {
+    use any::{Any, AnyRefExt};
+    use owned::AnyOwnExt;
+    use result;
+    use result::{Ok, Err};
+    use str::StrAllocating;
+    use string::String;
+    use std::io::{ChanReader, ChanWriter};
+    use prelude::*;
+    use super::*;
+
+    // !!! These tests are dangerous. If something is buggy, they will hang, !!!
+    // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
+
+    #[test]
+    fn test_unnamed_task() {
+        spawn(proc() {
+            with_task_name(|name| {
+                assert!(name.is_none());
+            })
         })
-    })
-}
+    }
 
-#[test]
-fn test_owned_named_task() {
-    TaskBuilder::new().named("ada lovelace".to_string()).spawn(proc() {
-        with_task_name(|name| {
-            assert!(name.unwrap() == "ada lovelace");
+    #[test]
+    fn test_owned_named_task() {
+        TaskBuilder::new().named("ada lovelace".to_string()).spawn(proc() {
+            with_task_name(|name| {
+                assert!(name.unwrap() == "ada lovelace");
+            })
         })
-    })
-}
+    }
 
-#[test]
-fn test_static_named_task() {
-    TaskBuilder::new().named("ada lovelace").spawn(proc() {
-        with_task_name(|name| {
-            assert!(name.unwrap() == "ada lovelace");
+    #[test]
+    fn test_static_named_task() {
+        TaskBuilder::new().named("ada lovelace").spawn(proc() {
+            with_task_name(|name| {
+                assert!(name.unwrap() == "ada lovelace");
+            })
         })
-    })
-}
+    }
 
-#[test]
-fn test_send_named_task() {
-    TaskBuilder::new().named("ada lovelace".into_maybe_owned()).spawn(proc() {
-        with_task_name(|name| {
-            assert!(name.unwrap() == "ada lovelace");
+    #[test]
+    fn test_send_named_task() {
+        TaskBuilder::new().named("ada lovelace".into_maybe_owned()).spawn(proc() {
+            with_task_name(|name| {
+                assert!(name.unwrap() == "ada lovelace");
+            })
         })
-    })
-}
-
-#[test]
-fn test_run_basic() {
-    let (tx, rx) = channel();
-    TaskBuilder::new().spawn(proc() {
-        tx.send(());
-    });
-    rx.recv();
-}
+    }
 
-#[test]
-fn test_with_wrapper() {
-    let (tx, rx) = channel();
-    TaskBuilder::new().with_wrapper(proc(body) {
-        let result: proc(): Send = proc() {
-            body();
+    #[test]
+    fn test_run_basic() {
+        let (tx, rx) = channel();
+        TaskBuilder::new().spawn(proc() {
             tx.send(());
-        };
-        result
-    }).spawn(proc() { });
-    rx.recv();
-}
+        });
+        rx.recv();
+    }
 
-#[test]
-fn test_future_result() {
-    let mut builder = TaskBuilder::new();
-    let result = builder.future_result();
-    builder.spawn(proc() {});
-    assert!(result.recv().is_ok());
-
-    let mut builder = TaskBuilder::new();
-    let result = builder.future_result();
-    builder.spawn(proc() {
-        fail!();
-    });
-    assert!(result.recv().is_err());
-}
+    #[test]
+    fn test_with_wrapper() {
+        let (tx, rx) = channel();
+        TaskBuilder::new().with_wrapper(proc(body) {
+            let result: proc():Send = proc() {
+                body();
+                tx.send(());
+            };
+            result
+        }).spawn(proc() { });
+        rx.recv();
+    }
 
-#[test] #[should_fail]
-fn test_back_to_the_future_result() {
-    let mut builder = TaskBuilder::new();
-    builder.future_result();
-    builder.future_result();
-}
+    #[test]
+    fn test_try_future() {
+        let result = TaskBuilder::new().try_future(proc() {});
+        assert!(result.unwrap().is_ok());
 
-#[test]
-fn test_try_success() {
-    match try(proc() {
-        "Success!".to_string()
-    }).as_ref().map(|s| s.as_slice()) {
-        result::Ok("Success!") => (),
-        _ => fail!()
+        let result = TaskBuilder::new().try_future(proc() -> () {
+            fail!();
+        });
+        assert!(result.unwrap().is_err());
     }
-}
 
-#[test]
-fn test_try_fail() {
-    match try(proc() {
-        fail!()
-    }) {
-        result::Err(_) => (),
-        result::Ok(()) => fail!()
+    #[test]
+    fn test_try_success() {
+        match try(proc() {
+            "Success!".to_string()
+        }).as_ref().map(|s| s.as_slice()) {
+            result::Ok("Success!") => (),
+            _ => fail!()
+        }
     }
-}
 
-#[test]
-fn test_spawn_sched() {
-    use clone::Clone;
+    #[test]
+    fn test_try_fail() {
+        match try(proc() {
+            fail!()
+        }) {
+            result::Err(_) => (),
+            result::Ok(()) => fail!()
+        }
+    }
 
-    let (tx, rx) = channel();
+    #[test]
+    fn test_spawn_sched() {
+        use clone::Clone;
 
-    fn f(i: int, tx: Sender<()>) {
-        let tx = tx.clone();
-        spawn(proc() {
-            if i == 0 {
-                tx.send(());
-            } else {
-                f(i - 1, tx);
-            }
-        });
+        let (tx, rx) = channel();
 
+        fn f(i: int, tx: Sender<()>) {
+            let tx = tx.clone();
+            spawn(proc() {
+                if i == 0 {
+                    tx.send(());
+                } else {
+                    f(i - 1, tx);
+                }
+            });
+
+        }
+        f(10, tx);
+        rx.recv();
     }
-    f(10, tx);
-    rx.recv();
-}
 
-#[test]
-fn test_spawn_sched_childs_on_default_sched() {
-    let (tx, rx) = channel();
+    #[test]
+    fn test_spawn_sched_childs_on_default_sched() {
+        let (tx, rx) = channel();
 
-    spawn(proc() {
         spawn(proc() {
-            tx.send(());
+            spawn(proc() {
+                tx.send(());
+            });
         });
-    });
 
-    rx.recv();
-}
+        rx.recv();
+    }
 
-#[cfg(test)]
-fn avoid_copying_the_body(spawnfn: |v: proc(): Send|) {
-    let (tx, rx) = channel::<uint>();
+    fn avoid_copying_the_body(spawnfn: |v: proc():Send|) {
+        let (tx, rx) = channel::<uint>();
 
-    let x = box 1;
-    let x_in_parent = (&*x) as *int as uint;
+        let x = box 1;
+        let x_in_parent = (&*x) as *int as uint;
 
-    spawnfn(proc() {
-        let x_in_child = (&*x) as *int as uint;
-        tx.send(x_in_child);
-    });
+        spawnfn(proc() {
+            let x_in_child = (&*x) as *int as uint;
+            tx.send(x_in_child);
+        });
 
-    let x_in_child = rx.recv();
-    assert_eq!(x_in_parent, x_in_child);
-}
+        let x_in_child = rx.recv();
+        assert_eq!(x_in_parent, x_in_child);
+    }
 
-#[test]
-fn test_avoid_copying_the_body_spawn() {
-    avoid_copying_the_body(spawn);
-}
+    #[test]
+    fn test_avoid_copying_the_body_spawn() {
+        avoid_copying_the_body(spawn);
+    }
 
-#[test]
-fn test_avoid_copying_the_body_task_spawn() {
-    avoid_copying_the_body(|f| {
-        let builder = TaskBuilder::new();
-        builder.spawn(proc() {
-            f();
-        });
-    })
-}
+    #[test]
+    fn test_avoid_copying_the_body_task_spawn() {
+        avoid_copying_the_body(|f| {
+            let builder = TaskBuilder::new();
+            builder.spawn(proc() {
+                f();
+            });
+        })
+    }
 
-#[test]
-fn test_avoid_copying_the_body_try() {
-    avoid_copying_the_body(|f| {
-        let _ = try(proc() {
-            f()
-        });
-    })
-}
+    #[test]
+    fn test_avoid_copying_the_body_try() {
+        avoid_copying_the_body(|f| {
+            let _ = try(proc() {
+                f()
+            });
+        })
+    }
 
-#[test]
-fn test_child_doesnt_ref_parent() {
-    // If the child refcounts the parent task, this will stack overflow when
-    // climbing the task tree to dereference each ancestor. (See #1789)
-    // (well, it would if the constant were 8000+ - I lowered it to be more
-    // valgrind-friendly. try this at home, instead..!)
-    static generations: uint = 16;
-    fn child_no(x: uint) -> proc(): Send {
-        return proc() {
-            if x < generations {
-                TaskBuilder::new().spawn(child_no(x+1));
+    #[test]
+    fn test_child_doesnt_ref_parent() {
+        // If the child refcounts the parent task, this will stack overflow when
+        // climbing the task tree to dereference each ancestor. (See #1789)
+        // (well, it would if the constant were 8000+ - I lowered it to be more
+        // valgrind-friendly. try this at home, instead..!)
+        static generations: uint = 16;
+        fn child_no(x: uint) -> proc(): Send {
+            return proc() {
+                if x < generations {
+                    TaskBuilder::new().spawn(child_no(x+1));
+                }
             }
         }
+        TaskBuilder::new().spawn(child_no(0));
     }
-    TaskBuilder::new().spawn(child_no(0));
-}
 
-#[test]
-fn test_simple_newsched_spawn() {
-    spawn(proc()())
-}
+    #[test]
+    fn test_simple_newsched_spawn() {
+        spawn(proc()())
+    }
 
-#[test]
-fn test_try_fail_message_static_str() {
-    match try(proc() {
-        fail!("static string");
-    }) {
-        Err(e) => {
-            type T = &'static str;
-            assert!(e.is::<T>());
-            assert_eq!(*e.move::<T>().unwrap(), "static string");
+    #[test]
+    fn test_try_fail_message_static_str() {
+        match try(proc() {
+            fail!("static string");
+        }) {
+            Err(e) => {
+                type T = &'static str;
+                assert!(e.is::<T>());
+                assert_eq!(*e.move::<T>().unwrap(), "static string");
+            }
+            Ok(()) => fail!()
         }
-        Ok(()) => fail!()
     }
-}
 
-#[test]
-fn test_try_fail_message_owned_str() {
-    match try(proc() {
-        fail!("owned string".to_string());
-    }) {
-        Err(e) => {
-            type T = String;
-            assert!(e.is::<T>());
-            assert_eq!(*e.move::<T>().unwrap(), "owned string".to_string());
+    #[test]
+    fn test_try_fail_message_owned_str() {
+        match try(proc() {
+            fail!("owned string".to_string());
+        }) {
+            Err(e) => {
+                type T = String;
+                assert!(e.is::<T>());
+                assert_eq!(*e.move::<T>().unwrap(), "owned string".to_string());
+            }
+            Ok(()) => fail!()
         }
-        Ok(()) => fail!()
     }
-}
 
-#[test]
-fn test_try_fail_message_any() {
-    match try(proc() {
-        fail!(box 413u16 as Box<Any + Send>);
-    }) {
-        Err(e) => {
-            type T = Box<Any + Send>;
-            assert!(e.is::<T>());
-            let any = e.move::<T>().unwrap();
-            assert!(any.is::<u16>());
-            assert_eq!(*any.move::<u16>().unwrap(), 413u16);
+    #[test]
+    fn test_try_fail_message_any() {
+        match try(proc() {
+            fail!(box 413u16 as Box<Any + Send>);
+        }) {
+            Err(e) => {
+                type T = Box<Any + Send>;
+                assert!(e.is::<T>());
+                let any = e.move::<T>().unwrap();
+                assert!(any.is::<u16>());
+                assert_eq!(*any.move::<u16>().unwrap(), 413u16);
+            }
+            Ok(()) => fail!()
         }
-        Ok(()) => fail!()
     }
-}
 
-#[test]
-fn test_try_fail_message_unit_struct() {
-    struct Juju;
+    #[test]
+    fn test_try_fail_message_unit_struct() {
+        struct Juju;
+
+        match try(proc() {
+            fail!(Juju)
+        }) {
+            Err(ref e) if e.is::<Juju>() => {}
+            Err(_) | Ok(()) => fail!()
+        }
+    }
+
+    #[test]
+    fn test_stdout() {
+        let (tx, rx) = channel();
+        let mut reader = ChanReader::new(rx);
+        let stdout = ChanWriter::new(tx);
+
+        TaskBuilder::new().stdout(box stdout as Box<Writer + Send>).try(proc() {
+            print!("Hello, world!");
+        }).unwrap();
 
-    match try(proc() {
-        fail!(Juju)
-    }) {
-        Err(ref e) if e.is::<Juju>() => {}
-        Err(_) | Ok(()) => fail!()
+        let output = reader.read_to_str().unwrap();
+        assert_eq!(output, "Hello, world!".to_string());
     }
+
+    // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
+    // to the test harness apparently interfering with stderr configuration.
 }