about summary refs log tree commit diff
path: root/src/libextra
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-02-03 10:41:34 -0800
committerbors <bors@rust-lang.org>2014-02-03 10:41:34 -0800
commitcb40eba4b1ce12914612914b94bdccd251a9f554 (patch)
tree5cb922f942920dc7d6b0f3606e9cd914360b2707 /src/libextra
parentbe4fc638092bf896c5c6c0672136b83b71e491ee (diff)
parentc765a8e7ad314651b92ff860cda0159c79dbec6e (diff)
auto merge of #11946 : alexcrichton/rust/no-io-error, r=brson
Turns out this was a little more far-reaching than I thought it was.

The first commit is the crux of this stack of commits. The `io::io_error` condition is completely removed and the `read` and `write` methods are altered to return `IoResult<T>`. This turned out to be an incredibly far-reaching change!

Overall, I'm very happy with how this turned out (in addition with the `unused_must_use` lint). I had to almost rewrite the pretty printer in `libsyntax` as well as the the formatting in `librustdoc` (as one would expect). These two modules do *tons* of I/O, and I believe that it's definitely improved.

This pull request also introduces the `if_ok!()` macro for returning-early from something that returns a result. I made quite liberal use of this in mostly the pretty printer and html renderer, and I found its usage generally quite pleasant and convenient to have. I didn't really feel like adding any other macro while I was using it, and I figured that pretty printing could be nicer, but it's nowhere near horrid today.

This may be a controversial issue closing, but I'm going to say it.

Closes #6163
Diffstat (limited to 'src/libextra')
-rw-r--r--src/libextra/arc.rs20
-rw-r--r--src/libextra/base64.rs2
-rw-r--r--src/libextra/ebml.rs34
-rw-r--r--src/libextra/hex.rs2
-rw-r--r--src/libextra/json.rs145
-rw-r--r--src/libextra/lib.rs5
-rw-r--r--src/libextra/stats.rs43
-rw-r--r--src/libextra/sync.rs2
-rw-r--r--src/libextra/tempfile.rs5
-rw-r--r--src/libextra/test.rs211
-rw-r--r--src/libextra/time.rs16
-rw-r--r--src/libextra/url.rs26
-rw-r--r--src/libextra/uuid.rs2
-rw-r--r--src/libextra/workcache.rs23
14 files changed, 304 insertions, 232 deletions
diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs
index 43366d2aa6d..9615bdc2ad7 100644
--- a/src/libextra/arc.rs
+++ b/src/libextra/arc.rs
@@ -637,7 +637,7 @@ mod tests {
     fn test_mutex_arc_poison() {
         let arc = ~MutexArc::new(1);
         let arc2 = ~arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.access(|one| {
                 assert_eq!(*one, 2);
             })
@@ -668,7 +668,7 @@ mod tests {
     fn test_mutex_arc_access_in_unwind() {
         let arc = MutexArc::new(1i);
         let arc2 = arc.clone();
-        task::try::<()>(proc() {
+        let _ = task::try::<()>(proc() {
             struct Unwinder {
                 i: MutexArc<int>
             }
@@ -687,7 +687,7 @@ mod tests {
     fn test_rw_arc_poison_wr() {
         let arc = RWArc::new(1);
         let arc2 = arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.write(|one| {
                 assert_eq!(*one, 2);
             })
@@ -701,7 +701,7 @@ mod tests {
     fn test_rw_arc_poison_ww() {
         let arc = RWArc::new(1);
         let arc2 = arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.write(|one| {
                 assert_eq!(*one, 2);
             })
@@ -714,7 +714,7 @@ mod tests {
     fn test_rw_arc_poison_dw() {
         let arc = RWArc::new(1);
         let arc2 = arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.write_downgrade(|mut write_mode| {
                 write_mode.write(|one| {
                     assert_eq!(*one, 2);
@@ -729,7 +729,7 @@ mod tests {
     fn test_rw_arc_no_poison_rr() {
         let arc = RWArc::new(1);
         let arc2 = arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.read(|one| {
                 assert_eq!(*one, 2);
             })
@@ -742,7 +742,7 @@ mod tests {
     fn test_rw_arc_no_poison_rw() {
         let arc = RWArc::new(1);
         let arc2 = arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.read(|one| {
                 assert_eq!(*one, 2);
             })
@@ -755,7 +755,7 @@ mod tests {
     fn test_rw_arc_no_poison_dr() {
         let arc = RWArc::new(1);
         let arc2 = arc.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             arc2.write_downgrade(|write_mode| {
                 let read_mode = arc2.downgrade(write_mode);
                 read_mode.read(|one| {
@@ -800,7 +800,7 @@ mod tests {
 
         // Wait for children to pass their asserts
         for r in children.mut_iter() {
-            r.recv();
+            let _ = r.recv();
         }
 
         // Wait for writer to finish
@@ -814,7 +814,7 @@ mod tests {
     fn test_rw_arc_access_in_unwind() {
         let arc = RWArc::new(1i);
         let arc2 = arc.clone();
-        task::try::<()>(proc() {
+        let _ = task::try::<()>(proc() {
             struct Unwinder {
                 i: RWArc<int>
             }
diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs
index 738afcd5c5f..556032af1ac 100644
--- a/src/libextra/base64.rs
+++ b/src/libextra/base64.rs
@@ -359,7 +359,7 @@ mod test {
                  ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
         let b = s.as_bytes().to_base64(STANDARD);
         bh.iter(|| {
-            b.from_base64();
+            b.from_base64().unwrap();
         });
         bh.bytes = b.len() as u64;
     }
diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs
index 5bbea491ac2..1900313ab6c 100644
--- a/src/libextra/ebml.rs
+++ b/src/libextra/ebml.rs
@@ -12,6 +12,10 @@
 
 use std::str;
 
+macro_rules! if_ok( ($e:expr) => (
+    match $e { Ok(e) => e, Err(e) => { self.last_error = Err(e); return } }
+) )
+
 // Simple Extensible Binary Markup Language (ebml) reader and writer on a
 // cursor model. See the specification here:
 //     http://www.matroska.org/technical/specs/rfc/index.html
@@ -595,9 +599,15 @@ pub mod writer {
 
     // ebml writing
     pub struct Encoder<'a> {
-        // FIXME(#5665): this should take a trait object
+        // FIXME(#5665): this should take a trait object. Note that if you
+        //               delete this comment you should consider removing the
+        //               unwrap()'s below of the results of the calls to
+        //               write(). We're guaranteed that writing into a MemWriter
+        //               won't fail, but this is not true for all I/O streams in
+        //               general.
         writer: &'a mut MemWriter,
         priv size_positions: ~[uint],
+        last_error: io::IoResult<()>,
     }
 
     fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) {
@@ -609,7 +619,7 @@ pub mod writer {
             4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
                             (n >> 8_u) as u8, n as u8]),
             _ => fail!("vint to write too big: {}", n)
-        };
+        }.unwrap()
     }
 
     fn write_vuint(w: &mut MemWriter, n: uint) {
@@ -624,7 +634,8 @@ pub mod writer {
         let size_positions: ~[uint] = ~[];
         Encoder {
             writer: w,
-            size_positions: size_positions
+            size_positions: size_positions,
+            last_error: Ok(()),
         }
     }
 
@@ -635,6 +646,7 @@ pub mod writer {
             Encoder {
                 writer: cast::transmute_copy(&self.writer),
                 size_positions: self.size_positions.clone(),
+                last_error: Ok(()),
             }
         }
 
@@ -645,18 +657,18 @@ pub mod writer {
             write_vuint(self.writer, tag_id);
 
             // Write a placeholder four-byte size.
-            self.size_positions.push(self.writer.tell() as uint);
+            self.size_positions.push(if_ok!(self.writer.tell()) as uint);
             let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
-            self.writer.write(zeroes);
+            if_ok!(self.writer.write(zeroes));
         }
 
         pub fn end_tag(&mut self) {
             let last_size_pos = self.size_positions.pop().unwrap();
-            let cur_pos = self.writer.tell();
-            self.writer.seek(last_size_pos as i64, io::SeekSet);
+            let cur_pos = if_ok!(self.writer.tell());
+            if_ok!(self.writer.seek(last_size_pos as i64, io::SeekSet));
             let size = (cur_pos as uint - last_size_pos - 4);
             write_sized_vuint(self.writer, size, 4u);
-            self.writer.seek(cur_pos as i64, io::SeekSet);
+            if_ok!(self.writer.seek(cur_pos as i64, io::SeekSet));
 
             debug!("End tag (size = {})", size);
         }
@@ -670,7 +682,7 @@ pub mod writer {
         pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
             write_vuint(self.writer, tag_id);
             write_vuint(self.writer, b.len());
-            self.writer.write(b);
+            self.writer.write(b).unwrap();
         }
 
         pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
@@ -723,12 +735,12 @@ pub mod writer {
 
         pub fn wr_bytes(&mut self, b: &[u8]) {
             debug!("Write {} bytes", b.len());
-            self.writer.write(b);
+            self.writer.write(b).unwrap();
         }
 
         pub fn wr_str(&mut self, s: &str) {
             debug!("Write str: {}", s);
-            self.writer.write(s.as_bytes());
+            self.writer.write(s.as_bytes()).unwrap();
         }
     }
 
diff --git a/src/libextra/hex.rs b/src/libextra/hex.rs
index 4fd59bb3aa5..d4e1ae12337 100644
--- a/src/libextra/hex.rs
+++ b/src/libextra/hex.rs
@@ -201,7 +201,7 @@ mod tests {
                  ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
         let b = s.as_bytes().to_hex();
         bh.iter(|| {
-            b.from_hex();
+            b.from_hex().unwrap();
         });
         bh.bytes = b.len() as u64;
     }
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index f8b1c216529..ef8e0999521 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -234,6 +234,10 @@ use serialize::Encodable;
 use serialize;
 use treemap::TreeMap;
 
+macro_rules! if_ok( ($e:expr) => (
+    match $e { Ok(e) => e, Err(e) => { self.error = Err(e); return } }
+) )
+
 /// Represents a json value
 #[deriving(Clone, Eq)]
 pub enum Json {
@@ -260,6 +264,14 @@ pub struct Error {
     priv msg: ~str,
 }
 
+fn io_error_to_error(io: io::IoError) -> Error {
+    Error {
+        line: 0,
+        col: 0,
+        msg: format!("io error: {}", io)
+    }
+}
+
 fn escape_str(s: &str) -> ~str {
     let mut escaped = ~"\"";
     for c in s.chars() {
@@ -289,13 +301,14 @@ fn spaces(n: uint) -> ~str {
 /// A structure for implementing serialization to JSON.
 pub struct Encoder<'a> {
     priv wr: &'a mut io::Writer,
+    priv error: io::IoResult<()>,
 }
 
 impl<'a> Encoder<'a> {
     /// Creates a new JSON encoder whose output will be written to the writer
     /// specified.
     pub fn new<'a>(wr: &'a mut io::Writer) -> Encoder<'a> {
-        Encoder { wr: wr }
+        Encoder { wr: wr, error: Ok(()) }
     }
 
     /// Encode the specified struct into a json [u8]
@@ -317,7 +330,7 @@ impl<'a> Encoder<'a> {
 }
 
 impl<'a> serialize::Encoder for Encoder<'a> {
-    fn emit_nil(&mut self) { write!(self.wr, "null") }
+    fn emit_nil(&mut self) { if_ok!(write!(self.wr, "null")) }
 
     fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
     fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
@@ -333,20 +346,20 @@ impl<'a> serialize::Encoder for Encoder<'a> {
 
     fn emit_bool(&mut self, v: bool) {
         if v {
-            write!(self.wr, "true");
+            if_ok!(write!(self.wr, "true"));
         } else {
-            write!(self.wr, "false");
+            if_ok!(write!(self.wr, "false"));
         }
     }
 
     fn emit_f64(&mut self, v: f64) {
-        write!(self.wr, "{}", f64::to_str_digits(v, 6u))
+        if_ok!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)))
     }
     fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
 
     fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
     fn emit_str(&mut self, v: &str) {
-        write!(self.wr, "{}", escape_str(v))
+        if_ok!(write!(self.wr, "{}", escape_str(v)))
     }
 
     fn emit_enum(&mut self, _name: &str, f: |&mut Encoder<'a>|) { f(self) }
@@ -360,19 +373,19 @@ impl<'a> serialize::Encoder for Encoder<'a> {
         // Bunny => "Bunny"
         // Kangaroo(34,"William") => {"variant": "Kangaroo", "fields": [34,"William"]}
         if cnt == 0 {
-            write!(self.wr, "{}", escape_str(name));
+            if_ok!(write!(self.wr, "{}", escape_str(name)));
         } else {
-            write!(self.wr, "\\{\"variant\":");
-            write!(self.wr, "{}", escape_str(name));
-            write!(self.wr, ",\"fields\":[");
+            if_ok!(write!(self.wr, "\\{\"variant\":"));
+            if_ok!(write!(self.wr, "{}", escape_str(name)));
+            if_ok!(write!(self.wr, ",\"fields\":["));
             f(self);
-            write!(self.wr, "]\\}");
+            if_ok!(write!(self.wr, "]\\}"));
         }
     }
 
     fn emit_enum_variant_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
         if idx != 0 {
-            write!(self.wr, ",");
+            if_ok!(write!(self.wr, ","));
         }
         f(self);
     }
@@ -393,17 +406,17 @@ impl<'a> serialize::Encoder for Encoder<'a> {
     }
 
     fn emit_struct(&mut self, _: &str, _: uint, f: |&mut Encoder<'a>|) {
-        write!(self.wr, r"\{");
+        if_ok!(write!(self.wr, r"\{"));
         f(self);
-        write!(self.wr, r"\}");
+        if_ok!(write!(self.wr, r"\}"));
     }
 
     fn emit_struct_field(&mut self,
                          name: &str,
                          idx: uint,
                          f: |&mut Encoder<'a>|) {
-        if idx != 0 { write!(self.wr, ",") }
-        write!(self.wr, "{}:", escape_str(name));
+        if idx != 0 { if_ok!(write!(self.wr, ",")) }
+        if_ok!(write!(self.wr, "{}:", escape_str(name)));
         f(self);
     }
 
@@ -429,31 +442,31 @@ impl<'a> serialize::Encoder for Encoder<'a> {
     fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { f(self); }
 
     fn emit_seq(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
-        write!(self.wr, "[");
+        if_ok!(write!(self.wr, "["));
         f(self);
-        write!(self.wr, "]");
+        if_ok!(write!(self.wr, "]"));
     }
 
     fn emit_seq_elt(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
         if idx != 0 {
-            write!(self.wr, ",");
+            if_ok!(write!(self.wr, ","));
         }
         f(self)
     }
 
     fn emit_map(&mut self, _len: uint, f: |&mut Encoder<'a>|) {
-        write!(self.wr, r"\{");
+        if_ok!(write!(self.wr, r"\{"));
         f(self);
-        write!(self.wr, r"\}");
+        if_ok!(write!(self.wr, r"\}"));
     }
 
     fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
-        if idx != 0 { write!(self.wr, ",") }
+        if idx != 0 { if_ok!(write!(self.wr, ",")) }
         f(self)
     }
 
     fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
-        write!(self.wr, ":");
+        if_ok!(write!(self.wr, ":"));
         f(self)
     }
 }
@@ -463,6 +476,7 @@ impl<'a> serialize::Encoder for Encoder<'a> {
 pub struct PrettyEncoder<'a> {
     priv wr: &'a mut io::Writer,
     priv indent: uint,
+    priv error: io::IoResult<()>,
 }
 
 impl<'a> PrettyEncoder<'a> {
@@ -471,12 +485,13 @@ impl<'a> PrettyEncoder<'a> {
         PrettyEncoder {
             wr: wr,
             indent: 0,
+            error: Ok(())
         }
     }
 }
 
 impl<'a> serialize::Encoder for PrettyEncoder<'a> {
-    fn emit_nil(&mut self) { write!(self.wr, "null") }
+    fn emit_nil(&mut self) { if_ok!(write!(self.wr, "null")); }
 
     fn emit_uint(&mut self, v: uint) { self.emit_f64(v as f64); }
     fn emit_u64(&mut self, v: u64) { self.emit_f64(v as f64); }
@@ -492,19 +507,21 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
 
     fn emit_bool(&mut self, v: bool) {
         if v {
-            write!(self.wr, "true");
+            if_ok!(write!(self.wr, "true"));
         } else {
-            write!(self.wr, "false");
+            if_ok!(write!(self.wr, "false"));
         }
     }
 
     fn emit_f64(&mut self, v: f64) {
-        write!(self.wr, "{}", f64::to_str_digits(v, 6u))
+        if_ok!(write!(self.wr, "{}", f64::to_str_digits(v, 6u)));
     }
     fn emit_f32(&mut self, v: f32) { self.emit_f64(v as f64); }
 
     fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
-    fn emit_str(&mut self, v: &str) { write!(self.wr, "{}", escape_str(v)); }
+    fn emit_str(&mut self, v: &str) {
+        if_ok!(write!(self.wr, "{}", escape_str(v)));
+    }
 
     fn emit_enum(&mut self, _name: &str, f: |&mut PrettyEncoder<'a>|) {
         f(self)
@@ -516,13 +533,14 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
                          cnt: uint,
                          f: |&mut PrettyEncoder<'a>|) {
         if cnt == 0 {
-            write!(self.wr, "{}", escape_str(name));
+            if_ok!(write!(self.wr, "{}", escape_str(name)));
         } else {
             self.indent += 2;
-            write!(self.wr, "[\n{}{},\n", spaces(self.indent), escape_str(name));
+            if_ok!(write!(self.wr, "[\n{}{},\n", spaces(self.indent),
+                          escape_str(name)));
             f(self);
             self.indent -= 2;
-            write!(self.wr, "\n{}]", spaces(self.indent));
+            if_ok!(write!(self.wr, "\n{}]", spaces(self.indent)));
         }
     }
 
@@ -530,9 +548,9 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
                              idx: uint,
                              f: |&mut PrettyEncoder<'a>|) {
         if idx != 0 {
-            write!(self.wr, ",\n");
+            if_ok!(write!(self.wr, ",\n"));
         }
-        write!(self.wr, "{}", spaces(self.indent));
+        if_ok!(write!(self.wr, "{}", spaces(self.indent)));
         f(self)
     }
 
@@ -557,13 +575,13 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
                    len: uint,
                    f: |&mut PrettyEncoder<'a>|) {
         if len == 0 {
-            write!(self.wr, "\\{\\}");
+            if_ok!(write!(self.wr, "\\{\\}"));
         } else {
-            write!(self.wr, "\\{");
+            if_ok!(write!(self.wr, "\\{"));
             self.indent += 2;
             f(self);
             self.indent -= 2;
-            write!(self.wr, "\n{}\\}", spaces(self.indent));
+            if_ok!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
         }
     }
 
@@ -572,11 +590,11 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
                          idx: uint,
                          f: |&mut PrettyEncoder<'a>|) {
         if idx == 0 {
-            write!(self.wr, "\n");
+            if_ok!(write!(self.wr, "\n"));
         } else {
-            write!(self.wr, ",\n");
+            if_ok!(write!(self.wr, ",\n"));
         }
-        write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name));
+        if_ok!(write!(self.wr, "{}{}: ", spaces(self.indent), escape_str(name)));
         f(self);
     }
 
@@ -605,50 +623,50 @@ impl<'a> serialize::Encoder for PrettyEncoder<'a> {
 
     fn emit_seq(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
         if len == 0 {
-            write!(self.wr, "[]");
+            if_ok!(write!(self.wr, "[]"));
         } else {
-            write!(self.wr, "[");
+            if_ok!(write!(self.wr, "["));
             self.indent += 2;
             f(self);
             self.indent -= 2;
-            write!(self.wr, "\n{}]", spaces(self.indent));
+            if_ok!(write!(self.wr, "\n{}]", spaces(self.indent)));
         }
     }
 
     fn emit_seq_elt(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
         if idx == 0 {
-            write!(self.wr, "\n");
+            if_ok!(write!(self.wr, "\n"));
         } else {
-            write!(self.wr, ",\n");
+            if_ok!(write!(self.wr, ",\n"));
         }
-        write!(self.wr, "{}", spaces(self.indent));
+        if_ok!(write!(self.wr, "{}", spaces(self.indent)));
         f(self)
     }
 
     fn emit_map(&mut self, len: uint, f: |&mut PrettyEncoder<'a>|) {
         if len == 0 {
-            write!(self.wr, "\\{\\}");
+            if_ok!(write!(self.wr, "\\{\\}"));
         } else {
-            write!(self.wr, "\\{");
+            if_ok!(write!(self.wr, "\\{"));
             self.indent += 2;
             f(self);
             self.indent -= 2;
-            write!(self.wr, "\n{}\\}", spaces(self.indent));
+            if_ok!(write!(self.wr, "\n{}\\}", spaces(self.indent)));
         }
     }
 
     fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
         if idx == 0 {
-            write!(self.wr, "\n");
+            if_ok!(write!(self.wr, "\n"));
         } else {
-            write!(self.wr, ",\n");
+            if_ok!(write!(self.wr, ",\n"));
         }
-        write!(self.wr, "{}", spaces(self.indent));
+        if_ok!(write!(self.wr, "{}", spaces(self.indent)));
         f(self);
     }
 
     fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
-        write!(self.wr, ": ");
+        if_ok!(write!(self.wr, ": "));
         f(self);
     }
 }
@@ -668,22 +686,24 @@ impl<E: serialize::Encoder> serialize::Encodable<E> for Json {
 
 impl Json{
     /// Encodes a json value into a io::writer.  Uses a single line.
-    pub fn to_writer(&self, wr: &mut io::Writer) {
+    pub fn to_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
         let mut encoder = Encoder::new(wr);
-        self.encode(&mut encoder)
+        self.encode(&mut encoder);
+        encoder.error
     }
 
     /// Encodes a json value into a io::writer.
     /// Pretty-prints in a more readable format.
-    pub fn to_pretty_writer(&self, wr: &mut io::Writer) {
+    pub fn to_pretty_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> {
         let mut encoder = PrettyEncoder::new(wr);
-        self.encode(&mut encoder)
+        self.encode(&mut encoder);
+        encoder.error
     }
 
     /// Encodes a json value into a string
     pub fn to_pretty_str(&self) -> ~str {
         let mut s = MemWriter::new();
-        self.to_pretty_writer(&mut s as &mut io::Writer);
+        self.to_pretty_writer(&mut s as &mut io::Writer).unwrap();
         str::from_utf8_owned(s.unwrap()).unwrap()
     }
 }
@@ -1067,7 +1087,14 @@ impl<T : Iterator<char>> Parser<T> {
 
 /// Decodes a json value from an `&mut io::Reader`
 pub fn from_reader(rdr: &mut io::Reader) -> Result<Json, Error> {
-    let s = str::from_utf8_owned(rdr.read_to_end()).unwrap();
+    let contents = match rdr.read_to_end() {
+        Ok(c) => c,
+        Err(e) => return Err(io_error_to_error(e))
+    };
+    let s = match str::from_utf8_owned(contents) {
+        Some(s) => s,
+        None => return Err(Error { line: 0, col: 0, msg: ~"contents not utf-8" })
+    };
     let mut parser = Parser::new(s.chars());
     parser.parse()
 }
@@ -1540,7 +1567,7 @@ impl to_str::ToStr for Json {
     /// Encodes a json value into a string
     fn to_str(&self) -> ~str {
         let mut s = MemWriter::new();
-        self.to_writer(&mut s as &mut io::Writer);
+        self.to_writer(&mut s as &mut io::Writer).unwrap();
         str::from_utf8_owned(s.unwrap()).unwrap()
     }
 }
diff --git a/src/libextra/lib.rs b/src/libextra/lib.rs
index e2a4b52c810..358dca5e5ac 100644
--- a/src/libextra/lib.rs
+++ b/src/libextra/lib.rs
@@ -34,6 +34,11 @@ Rust extras are part of the standard Rust distribution.
 #[deny(non_camel_case_types)];
 #[deny(missing_doc)];
 
+#[cfg(stage0)]
+macro_rules! if_ok (
+    ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
+)
+
 // Utility modules
 
 pub mod c_vec;
diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs
index 096e5882774..8752020f564 100644
--- a/src/libextra/stats.rs
+++ b/src/libextra/stats.rs
@@ -322,14 +322,15 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
 }
 
 /// Render writes the min, max and quartiles of the provided `Summary` to the provided `Writer`.
-pub fn write_5_number_summary(w: &mut io::Writer, s: &Summary) {
+pub fn write_5_number_summary(w: &mut io::Writer,
+                              s: &Summary) -> io::IoResult<()> {
     let (q1,q2,q3) = s.quartiles;
     write!(w, "(min={}, q1={}, med={}, q3={}, max={})",
                      s.min,
                      q1,
                      q2,
                      q3,
-                     s.max);
+                     s.max)
 }
 
 /// Render a boxplot to the provided writer. The boxplot shows the min, max and quartiles of the
@@ -344,7 +345,8 @@ pub fn write_5_number_summary(w: &mut io::Writer, s: &Summary) {
 ///   10 |        [--****#******----------]          | 40
 /// ~~~~
 
-pub fn write_boxplot(w: &mut io::Writer, s: &Summary, width_hint: uint) {
+pub fn write_boxplot(w: &mut io::Writer, s: &Summary,
+                     width_hint: uint) -> io::IoResult<()> {
 
     let (q1,q2,q3) = s.quartiles;
 
@@ -374,48 +376,49 @@ pub fn write_boxplot(w: &mut io::Writer, s: &Summary, width_hint: uint) {
     let range_width = width_hint - overhead_width;;
     let char_step = range / (range_width as f64);
 
-    write!(w, "{} |", lostr);
+    if_ok!(write!(w, "{} |", lostr));
 
     let mut c = 0;
     let mut v = lo;
 
     while c < range_width && v < s.min {
-        write!(w, " ");
+        if_ok!(write!(w, " "));
         v += char_step;
         c += 1;
     }
-    write!(w, "[");
+    if_ok!(write!(w, "["));
     c += 1;
     while c < range_width && v < q1 {
-        write!(w, "-");
+        if_ok!(write!(w, "-"));
         v += char_step;
         c += 1;
     }
     while c < range_width && v < q2 {
-        write!(w, "*");
+        if_ok!(write!(w, "*"));
         v += char_step;
         c += 1;
     }
-    write!(w, r"\#");
+    if_ok!(write!(w, r"\#"));
     c += 1;
     while c < range_width && v < q3 {
-        write!(w, "*");
+        if_ok!(write!(w, "*"));
         v += char_step;
         c += 1;
     }
     while c < range_width && v < s.max {
-        write!(w, "-");
+        if_ok!(write!(w, "-"));
         v += char_step;
         c += 1;
     }
-    write!(w, "]");
+    if_ok!(write!(w, "]"));
     while c < range_width {
-        write!(w, " ");
+        if_ok!(write!(w, " "));
         v += char_step;
         c += 1;
     }
 
-    write!(w, "| {}", histr);
+    if_ok!(write!(w, "| {}", histr));
+    Ok(())
 }
 
 /// Returns a HashMap with the number of occurrences of every element in the
@@ -453,11 +456,11 @@ mod tests {
 
         let mut w = io::stdout();
         let w = &mut w as &mut io::Writer;
-        write!(w, "\n");
-        write_5_number_summary(w, &summ2);
-        write!(w, "\n");
-        write_boxplot(w, &summ2, 50);
-        write!(w, "\n");
+        (write!(w, "\n")).unwrap();
+        write_5_number_summary(w, &summ2).unwrap();
+        (write!(w, "\n")).unwrap();
+        write_boxplot(w, &summ2, 50).unwrap();
+        (write!(w, "\n")).unwrap();
 
         assert_eq!(summ.sum, summ2.sum);
         assert_eq!(summ.min, summ2.min);
@@ -1000,7 +1003,7 @@ mod tests {
         fn t(s: &Summary, expected: ~str) {
             use std::io::MemWriter;
             let mut m = MemWriter::new();
-            write_boxplot(&mut m as &mut io::Writer, s, 30);
+            write_boxplot(&mut m as &mut io::Writer, s, 30).unwrap();
             let out = str::from_utf8_owned(m.unwrap()).unwrap();
             assert_eq!(out, expected);
         }
diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs
index 26a555a646c..0a29fd18982 100644
--- a/src/libextra/sync.rs
+++ b/src/libextra/sync.rs
@@ -959,7 +959,7 @@ mod tests {
     fn test_mutex_cond_no_waiter() {
         let m = Mutex::new();
         let m2 = m.clone();
-        task::try(proc() {
+        let _ = task::try(proc() {
             m.lock_cond(|_x| { })
         });
         m2.lock_cond(|cond| {
diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs
index c9ea556f23a..5948f356a65 100644
--- a/src/libextra/tempfile.rs
+++ b/src/libextra/tempfile.rs
@@ -38,7 +38,7 @@ impl TempDir {
         let mut r = rand::rng();
         for _ in range(0u, 1000) {
             let p = tmpdir.join(r.gen_ascii_str(16) + suffix);
-            match io::result(|| fs::mkdir(&p, io::UserRWX)) {
+            match fs::mkdir(&p, io::UserRWX) {
                 Err(..) => {}
                 Ok(()) => return Some(TempDir { path: Some(p) })
             }
@@ -73,7 +73,8 @@ impl Drop for TempDir {
     fn drop(&mut self) {
         for path in self.path.iter() {
             if path.exists() {
-                fs::rmdir_recursive(path);
+                // FIXME: is failing the right thing to do?
+                fs::rmdir_recursive(path).unwrap();
             }
         }
     }
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index ef5a05b6a3e..c4d27b25b55 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -163,7 +163,11 @@ pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
             Some(Err(msg)) => fail!("{}", msg),
             None => return
         };
-    if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
+    match run_tests_console(&opts, tests) {
+        Ok(true) => {}
+        Ok(false) => fail!("Some tests failed"),
+        Err(e) => fail!("io error when running tests: {}", e),
+    }
 }
 
 // A variant optimized for invocation with a static test vector.
@@ -359,16 +363,17 @@ struct ConsoleTestState<T> {
 }
 
 impl<T: Writer> ConsoleTestState<T> {
-    pub fn new(opts: &TestOpts, _: Option<T>) -> ConsoleTestState<StdWriter> {
+    pub fn new(opts: &TestOpts,
+               _: Option<T>) -> io::IoResult<ConsoleTestState<StdWriter>> {
         let log_out = match opts.logfile {
-            Some(ref path) => File::create(path),
+            Some(ref path) => Some(if_ok!(File::create(path))),
             None => None
         };
         let out = match term::Terminal::new(io::stdout()) {
             Err(_) => Raw(io::stdout()),
             Ok(t) => Pretty(t)
         };
-        ConsoleTestState {
+        Ok(ConsoleTestState {
             out: out,
             log_out: log_out,
             use_color: use_color(),
@@ -380,100 +385,103 @@ impl<T: Writer> ConsoleTestState<T> {
             metrics: MetricMap::new(),
             failures: ~[],
             max_name_len: 0u,
-        }
+        })
     }
 
-    pub fn write_ok(&mut self) {
-        self.write_pretty("ok", term::color::GREEN);
+    pub fn write_ok(&mut self) -> io::IoResult<()> {
+        self.write_pretty("ok", term::color::GREEN)
     }
 
-    pub fn write_failed(&mut self) {
-        self.write_pretty("FAILED", term::color::RED);
+    pub fn write_failed(&mut self) -> io::IoResult<()> {
+        self.write_pretty("FAILED", term::color::RED)
     }
 
-    pub fn write_ignored(&mut self) {
-        self.write_pretty("ignored", term::color::YELLOW);
+    pub fn write_ignored(&mut self) -> io::IoResult<()> {
+        self.write_pretty("ignored", term::color::YELLOW)
     }
 
-    pub fn write_metric(&mut self) {
-        self.write_pretty("metric", term::color::CYAN);
+    pub fn write_metric(&mut self) -> io::IoResult<()> {
+        self.write_pretty("metric", term::color::CYAN)
     }
 
-    pub fn write_bench(&mut self) {
-        self.write_pretty("bench", term::color::CYAN);
+    pub fn write_bench(&mut self) -> io::IoResult<()> {
+        self.write_pretty("bench", term::color::CYAN)
     }
 
-    pub fn write_added(&mut self) {
-        self.write_pretty("added", term::color::GREEN);
+    pub fn write_added(&mut self) -> io::IoResult<()> {
+        self.write_pretty("added", term::color::GREEN)
     }
 
-    pub fn write_improved(&mut self) {
-        self.write_pretty("improved", term::color::GREEN);
+    pub fn write_improved(&mut self) -> io::IoResult<()> {
+        self.write_pretty("improved", term::color::GREEN)
     }
 
-    pub fn write_removed(&mut self) {
-        self.write_pretty("removed", term::color::YELLOW);
+    pub fn write_removed(&mut self) -> io::IoResult<()> {
+        self.write_pretty("removed", term::color::YELLOW)
     }
 
-    pub fn write_regressed(&mut self) {
-        self.write_pretty("regressed", term::color::RED);
+    pub fn write_regressed(&mut self) -> io::IoResult<()> {
+        self.write_pretty("regressed", term::color::RED)
     }
 
     pub fn write_pretty(&mut self,
                         word: &str,
-                        color: term::color::Color) {
+                        color: term::color::Color) -> io::IoResult<()> {
         match self.out {
             Pretty(ref mut term) => {
                 if self.use_color {
-                    term.fg(color);
+                    if_ok!(term.fg(color));
                 }
-                term.write(word.as_bytes());
+                if_ok!(term.write(word.as_bytes()));
                 if self.use_color {
-                    term.reset();
+                    if_ok!(term.reset());
                 }
+                Ok(())
             }
             Raw(ref mut stdout) => stdout.write(word.as_bytes())
         }
     }
 
-    pub fn write_plain(&mut self, s: &str) {
+    pub fn write_plain(&mut self, s: &str) -> io::IoResult<()> {
         match self.out {
             Pretty(ref mut term) => term.write(s.as_bytes()),
             Raw(ref mut stdout) => stdout.write(s.as_bytes())
         }
     }
 
-    pub fn write_run_start(&mut self, len: uint) {
+    pub fn write_run_start(&mut self, len: uint) -> io::IoResult<()> {
         self.total = len;
         let noun = if len != 1 { &"tests" } else { &"test" };
-        self.write_plain(format!("\nrunning {} {}\n", len, noun));
+        self.write_plain(format!("\nrunning {} {}\n", len, noun))
     }
 
-    pub fn write_test_start(&mut self, test: &TestDesc, align: NamePadding) {
+    pub fn write_test_start(&mut self, test: &TestDesc,
+                            align: NamePadding) -> io::IoResult<()> {
         let name = test.padded_name(self.max_name_len, align);
-        self.write_plain(format!("test {} ... ", name));
+        self.write_plain(format!("test {} ... ", name))
     }
 
-    pub fn write_result(&mut self, result: &TestResult) {
-        match *result {
+    pub fn write_result(&mut self, result: &TestResult) -> io::IoResult<()> {
+        if_ok!(match *result {
             TrOk => self.write_ok(),
             TrFailed => self.write_failed(),
             TrIgnored => self.write_ignored(),
             TrMetrics(ref mm) => {
-                self.write_metric();
-                self.write_plain(format!(": {}", fmt_metrics(mm)));
+                if_ok!(self.write_metric());
+                self.write_plain(format!(": {}", fmt_metrics(mm)))
             }
             TrBench(ref bs) => {
-                self.write_bench();
-                self.write_plain(format!(": {}", fmt_bench_samples(bs)));
+                if_ok!(self.write_bench());
+                self.write_plain(format!(": {}", fmt_bench_samples(bs)))
             }
-        }
-        self.write_plain("\n");
+        });
+        self.write_plain("\n")
     }
 
-    pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) {
+    pub fn write_log(&mut self, test: &TestDesc,
+                     result: &TestResult) -> io::IoResult<()> {
         match self.log_out {
-            None => (),
+            None => Ok(()),
             Some(ref mut o) => {
                 let s = format!("{} {}\n", match *result {
                         TrOk => ~"ok",
@@ -482,24 +490,25 @@ impl<T: Writer> ConsoleTestState<T> {
                         TrMetrics(ref mm) => fmt_metrics(mm),
                         TrBench(ref bs) => fmt_bench_samples(bs)
                     }, test.name.to_str());
-                o.write(s.as_bytes());
+                o.write(s.as_bytes())
             }
         }
     }
 
-    pub fn write_failures(&mut self) {
-        self.write_plain("\nfailures:\n");
+    pub fn write_failures(&mut self) -> io::IoResult<()> {
+        if_ok!(self.write_plain("\nfailures:\n"));
         let mut failures = ~[];
         for f in self.failures.iter() {
             failures.push(f.name.to_str());
         }
         failures.sort();
         for name in failures.iter() {
-            self.write_plain(format!("    {}\n", name.to_str()));
+            if_ok!(self.write_plain(format!("    {}\n", name.to_str())));
         }
+        Ok(())
     }
 
-    pub fn write_metric_diff(&mut self, diff: &MetricDiff) {
+    pub fn write_metric_diff(&mut self, diff: &MetricDiff) -> io::IoResult<()> {
         let mut noise = 0;
         let mut improved = 0;
         let mut regressed = 0;
@@ -511,77 +520,82 @@ impl<T: Writer> ConsoleTestState<T> {
                 LikelyNoise => noise += 1,
                 MetricAdded => {
                     added += 1;
-                    self.write_added();
-                    self.write_plain(format!(": {}\n", *k));
+                    if_ok!(self.write_added());
+                    if_ok!(self.write_plain(format!(": {}\n", *k)));
                 }
                 MetricRemoved => {
                     removed += 1;
-                    self.write_removed();
-                    self.write_plain(format!(": {}\n", *k));
+                    if_ok!(self.write_removed());
+                    if_ok!(self.write_plain(format!(": {}\n", *k)));
                 }
                 Improvement(pct) => {
                     improved += 1;
-                    self.write_plain(format!(": {}", *k));
-                    self.write_improved();
-                    self.write_plain(format!(" by {:.2f}%\n", pct as f64));
+                    if_ok!(self.write_plain(format!(": {}", *k)));
+                    if_ok!(self.write_improved());
+                    if_ok!(self.write_plain(format!(" by {:.2f}%\n", pct as f64)));
                 }
                 Regression(pct) => {
                     regressed += 1;
-                    self.write_plain(format!(": {}", *k));
-                    self.write_regressed();
-                    self.write_plain(format!(" by {:.2f}%\n", pct as f64));
+                    if_ok!(self.write_plain(format!(": {}", *k)));
+                    if_ok!(self.write_regressed());
+                    if_ok!(self.write_plain(format!(" by {:.2f}%\n", pct as f64)));
                 }
             }
         }
-        self.write_plain(format!("result of ratchet: {} matrics added, {} removed, \
-                                  {} improved, {} regressed, {} noise\n",
-                                 added, removed, improved, regressed, noise));
+        if_ok!(self.write_plain(format!("result of ratchet: {} matrics added, \
+                                        {} removed, {} improved, {} regressed, \
+                                        {} noise\n",
+                                       added, removed, improved, regressed,
+                                       noise)));
         if regressed == 0 {
-            self.write_plain("updated ratchet file\n");
+            if_ok!(self.write_plain("updated ratchet file\n"));
         } else {
-            self.write_plain("left ratchet file untouched\n");
+            if_ok!(self.write_plain("left ratchet file untouched\n"));
         }
+        Ok(())
     }
 
     pub fn write_run_finish(&mut self,
                             ratchet_metrics: &Option<Path>,
-                            ratchet_pct: Option<f64>) -> bool {
+                            ratchet_pct: Option<f64>) -> io::IoResult<bool> {
         assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
 
         let ratchet_success = match *ratchet_metrics {
             None => true,
             Some(ref pth) => {
-                self.write_plain(format!("\nusing metrics ratcher: {}\n", pth.display()));
+                if_ok!(self.write_plain(format!("\nusing metrics ratcher: {}\n",
+                                        pth.display())));
                 match ratchet_pct {
                     None => (),
                     Some(pct) =>
-                        self.write_plain(format!("with noise-tolerance forced to: {}%\n",
-                                                 pct))
+                        if_ok!(self.write_plain(format!("with noise-tolerance \
+                                                         forced to: {}%\n",
+                                                        pct)))
                 }
                 let (diff, ok) = self.metrics.ratchet(pth, ratchet_pct);
-                self.write_metric_diff(&diff);
+                if_ok!(self.write_metric_diff(&diff));
                 ok
             }
         };
 
         let test_success = self.failed == 0u;
         if !test_success {
-            self.write_failures();
+            if_ok!(self.write_failures());
         }
 
         let success = ratchet_success && test_success;
 
-        self.write_plain("\ntest result: ");
+        if_ok!(self.write_plain("\ntest result: "));
         if success {
             // There's no parallelism at this point so it's safe to use color
-            self.write_ok();
+            if_ok!(self.write_ok());
         } else {
-            self.write_failed();
+            if_ok!(self.write_failed());
         }
         let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n",
                         self.passed, self.failed, self.ignored, self.measured);
-        self.write_plain(s);
-        return success;
+        if_ok!(self.write_plain(s));
+        return Ok(success);
     }
 }
 
@@ -611,15 +625,16 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> ~str {
 
 // A simple console test runner
 pub fn run_tests_console(opts: &TestOpts,
-                         tests: ~[TestDescAndFn]) -> bool {
-    fn callback<T: Writer>(event: &TestEvent, st: &mut ConsoleTestState<T>) {
+                         tests: ~[TestDescAndFn]) -> io::IoResult<bool> {
+    fn callback<T: Writer>(event: &TestEvent,
+                           st: &mut ConsoleTestState<T>) -> io::IoResult<()> {
         debug!("callback(event={:?})", event);
         match (*event).clone() {
             TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
             TeWait(ref test, padding) => st.write_test_start(test, padding),
             TeResult(test, result) => {
-                st.write_log(&test, &result);
-                st.write_result(&result);
+                if_ok!(st.write_log(&test, &result));
+                if_ok!(st.write_result(&result));
                 match result {
                     TrOk => st.passed += 1,
                     TrIgnored => st.ignored += 1,
@@ -643,10 +658,11 @@ pub fn run_tests_console(opts: &TestOpts,
                         st.failures.push(test);
                     }
                 }
+                Ok(())
             }
         }
     }
-    let mut st = ConsoleTestState::new(opts, None::<StdWriter>);
+    let mut st = if_ok!(ConsoleTestState::new(opts, None::<StdWriter>));
     fn len_if_padded(t: &TestDescAndFn) -> uint {
         match t.testfn.padding() {
             PadNone => 0u,
@@ -661,12 +677,13 @@ pub fn run_tests_console(opts: &TestOpts,
         },
         None => {}
     }
-    run_tests(opts, tests, |x| callback(&x, &mut st));
+    if_ok!(run_tests(opts, tests, |x| callback(&x, &mut st)));
     match opts.save_metrics {
         None => (),
         Some(ref pth) => {
-            st.metrics.save(pth);
-            st.write_plain(format!("\nmetrics saved to: {}", pth.display()));
+            if_ok!(st.metrics.save(pth));
+            if_ok!(st.write_plain(format!("\nmetrics saved to: {}",
+                                          pth.display())));
         }
     }
     return st.write_run_finish(&opts.ratchet_metrics, opts.ratchet_noise_percent);
@@ -703,7 +720,7 @@ fn should_sort_failures_before_printing_them() {
         failures: ~[test_b, test_a]
     };
 
-    st.write_failures();
+    st.write_failures().unwrap();
     let s = match st.out {
         Raw(ref m) => str::from_utf8(m.get_ref()).unwrap(),
         Pretty(_) => unreachable!()
@@ -728,11 +745,11 @@ pub type MonitorMsg = (TestDesc, TestResult);
 
 fn run_tests(opts: &TestOpts,
              tests: ~[TestDescAndFn],
-             callback: |e: TestEvent|) {
+             callback: |e: TestEvent| -> io::IoResult<()>) -> io::IoResult<()> {
     let filtered_tests = filter_tests(opts, tests);
     let filtered_descs = filtered_tests.map(|t| t.desc.clone());
 
-    callback(TeFiltered(filtered_descs));
+    if_ok!(callback(TeFiltered(filtered_descs)));
 
     let (filtered_tests, filtered_benchs_and_metrics) =
         filtered_tests.partition(|e| {
@@ -760,7 +777,7 @@ fn run_tests(opts: &TestOpts,
                 // We are doing one test at a time so we can print the name
                 // of the test before we run it. Useful for debugging tests
                 // that hang forever.
-                callback(TeWait(test.desc.clone(), test.testfn.padding()));
+                if_ok!(callback(TeWait(test.desc.clone(), test.testfn.padding())));
             }
             run_test(!opts.run_tests, test, ch.clone());
             pending += 1;
@@ -768,20 +785,21 @@ fn run_tests(opts: &TestOpts,
 
         let (desc, result) = p.recv();
         if concurrency != 1 {
-            callback(TeWait(desc.clone(), PadNone));
+            if_ok!(callback(TeWait(desc.clone(), PadNone)));
         }
-        callback(TeResult(desc, result));
+        if_ok!(callback(TeResult(desc, result)));
         pending -= 1;
     }
 
     // All benchmarks run at the end, in serial.
     // (this includes metric fns)
     for b in filtered_benchs_and_metrics.move_iter() {
-        callback(TeWait(b.desc.clone(), b.testfn.padding()));
+        if_ok!(callback(TeWait(b.desc.clone(), b.testfn.padding())));
         run_test(!opts.run_benchmarks, b, ch.clone());
         let (test, result) = p.recv();
-        callback(TeResult(test, result));
+        if_ok!(callback(TeResult(test, result)));
     }
+    Ok(())
 }
 
 fn get_concurrency() -> uint {
@@ -943,17 +961,22 @@ impl MetricMap {
     }
 
     /// Load MetricDiff from a file.
+    ///
+    /// # Failure
+    ///
+    /// This function will fail if the path does not exist or the path does not
+    /// contain a valid metric map.
     pub fn load(p: &Path) -> MetricMap {
         assert!(p.exists());
-        let mut f = File::open(p);
+        let mut f = File::open(p).unwrap();
         let value = json::from_reader(&mut f as &mut io::Reader).unwrap();
         let mut decoder = json::Decoder::new(value);
         MetricMap(Decodable::decode(&mut decoder))
     }
 
     /// Write MetricDiff to a file.
-    pub fn save(&self, p: &Path) {
-        let mut file = File::create(p);
+    pub fn save(&self, p: &Path) -> io::IoResult<()> {
+        let mut file = if_ok!(File::create(p));
         let MetricMap(ref map) = *self;
         map.to_json().to_pretty_writer(&mut file)
     }
@@ -1060,7 +1083,7 @@ impl MetricMap {
 
         if ok {
             debug!("rewriting file '{:?}' with updated metrics", p);
-            self.save(p);
+            self.save(p).unwrap();
         }
         return (diff, ok)
     }
@@ -1462,7 +1485,7 @@ mod tests {
         m2.insert_metric("runtime", 1100.0, 2.0);
         m2.insert_metric("throughput", 50.0, 2.0);
 
-        m1.save(&pth);
+        m1.save(&pth).unwrap();
 
         // Ask for a ratchet that should fail to advance.
         let (diff1, ok1) = m2.ratchet(&pth, None);
diff --git a/src/libextra/time.rs b/src/libextra/time.rs
index 3e5b9b797d3..0a122ad58bd 100644
--- a/src/libextra/time.rs
+++ b/src/libextra/time.rs
@@ -766,14 +766,14 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
 
         let mut buf = [0];
         let c = match rdr.read(buf) {
-            Some(..) => buf[0] as char,
-            None => break
+            Ok(..) => buf[0] as char,
+            Err(..) => break
         };
         match c {
             '%' => {
                 let ch = match rdr.read(buf) {
-                    Some(..) => buf[0] as char,
-                    None => break
+                    Ok(..) => buf[0] as char,
+                    Err(..) => break
                 };
                 match parse_type(s, pos, ch, &mut tm) {
                     Ok(next) => pos = next,
@@ -787,7 +787,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
         }
     }
 
-    if pos == len && rdr.tell() as uint == format.len() {
+    if pos == len && rdr.tell().unwrap() == format.len() as u64 {
         Ok(Tm {
             tm_sec: tm.tm_sec,
             tm_min: tm.tm_min,
@@ -1017,12 +1017,12 @@ pub fn strftime(format: &str, tm: &Tm) -> ~str {
     loop {
         let mut b = [0];
         let ch = match rdr.read(b) {
-            Some(..) => b[0],
-            None => break,
+            Ok(..) => b[0],
+            Err(..) => break,
         };
         match ch as char {
             '%' => {
-                rdr.read(b);
+                rdr.read(b).unwrap();
                 let s = parse_type(b[0] as char, tm);
                 buf.push_all(s.as_bytes());
             }
diff --git a/src/libextra/url.rs b/src/libextra/url.rs
index 35c53c9307c..6138c5416f2 100644
--- a/src/libextra/url.rs
+++ b/src/libextra/url.rs
@@ -102,8 +102,8 @@ fn encode_inner(s: &str, full_url: bool) -> ~str {
     loop {
         let mut buf = [0];
         let ch = match rdr.read(buf) {
-            None => break,
-            Some(..) => buf[0] as char,
+            Err(..) => break,
+            Ok(..) => buf[0] as char,
         };
 
         match ch {
@@ -166,14 +166,14 @@ fn decode_inner(s: &str, full_url: bool) -> ~str {
     loop {
         let mut buf = [0];
         let ch = match rdr.read(buf) {
-            None => break,
-            Some(..) => buf[0] as char
+            Err(..) => break,
+            Ok(..) => buf[0] as char
         };
         match ch {
           '%' => {
             let mut bytes = [0, 0];
             match rdr.read(bytes) {
-                Some(2) => {}
+                Ok(2) => {}
                 _ => fail!() // FIXME: malformed url?
             }
             let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
@@ -228,8 +228,8 @@ fn encode_plus(s: &str) -> ~str {
     loop {
         let mut buf = [0];
         let ch = match rdr.read(buf) {
-            Some(..) => buf[0] as char,
-            None => break,
+            Ok(..) => buf[0] as char,
+            Err(..) => break,
         };
         match ch {
           'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
@@ -282,8 +282,8 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
     loop {
         let mut buf = [0];
         let ch = match rdr.read(buf) {
-            Some(..) => buf[0] as char,
-            None => break,
+            Ok(..) => buf[0] as char,
+            Err(..) => break,
         };
         match ch {
             '&' | ';' => {
@@ -307,7 +307,7 @@ pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
                     '%' => {
                         let mut bytes = [0, 0];
                         match rdr.read(bytes) {
-                            Some(2) => {}
+                            Ok(2) => {}
                             _ => fail!() // FIXME: malformed?
                         }
                         uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
@@ -347,12 +347,12 @@ fn split_char_first(s: &str, c: char) -> (~str, ~str) {
     loop {
         let mut buf = [0];
         let ch = match rdr.read(buf) {
-            Some(..) => buf[0] as char,
-            None => break,
+            Ok(..) => buf[0] as char,
+            Err(..) => break,
         };
         if ch == c {
             // found a match, adjust markers
-            index = (rdr.tell() as uint) - 1;
+            index = (rdr.tell().unwrap() as uint) - 1;
             mat = 1;
             break;
         }
diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs
index 9163a892039..29d3066b2f5 100644
--- a/src/libextra/uuid.rs
+++ b/src/libextra/uuid.rs
@@ -821,7 +821,7 @@ mod bench {
     pub fn parse_str(bh: &mut BenchHarness) {
         let s = "urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4";
         bh.iter(|| {
-            Uuid::parse_string(s);
+            Uuid::parse_string(s).unwrap();
         })
     }
 }
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index 70bbe02d32f..4d8e7e50dcf 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -172,20 +172,19 @@ impl Database {
     }
 
     // FIXME #4330: This should have &mut self and should set self.db_dirty to false.
-    fn save(&self) {
+    fn save(&self) -> io::IoResult<()> {
         let mut f = File::create(&self.db_filename);
-        self.db_cache.to_json().to_pretty_writer(&mut f);
+        self.db_cache.to_json().to_pretty_writer(&mut f)
     }
 
     fn load(&mut self) {
         assert!(!self.db_dirty);
         assert!(self.db_filename.exists());
-        match io::result(|| File::open(&self.db_filename)) {
+        match File::open(&self.db_filename) {
             Err(e) => fail!("Couldn't load workcache database {}: {}",
                             self.db_filename.display(),
-                            e.desc),
-            Ok(r) => {
-                let mut stream = r.unwrap();
+                            e),
+            Ok(mut stream) => {
                 match json::from_reader(&mut stream) {
                     Err(e) => fail!("Couldn't parse workcache database (from file {}): {}",
                                     self.db_filename.display(), e.to_str()),
@@ -203,7 +202,8 @@ impl Database {
 impl Drop for Database {
     fn drop(&mut self) {
         if self.db_dirty {
-            self.save();
+            // FIXME: is failing the right thing to do here
+            self.save().unwrap();
         }
     }
 }
@@ -473,13 +473,13 @@ fn test() {
     fn make_path(filename: ~str) -> Path {
         let pth = os::self_exe_path().expect("workcache::test failed").with_filename(filename);
         if pth.exists() {
-            fs::unlink(&pth);
+            fs::unlink(&pth).unwrap();
         }
         return pth;
     }
 
     let pth = make_path(~"foo.c");
-    File::create(&pth).write(bytes!("int main() { return 0; }"));
+    File::create(&pth).write(bytes!("int main() { return 0; }")).unwrap();
 
     let db_path = make_path(~"db.json");
 
@@ -491,7 +491,8 @@ fn test() {
         let subcx = cx.clone();
         let pth = pth.clone();
 
-        let file_content = from_utf8_owned(File::open(&pth).read_to_end()).unwrap();
+        let contents = File::open(&pth).read_to_end().unwrap();
+        let file_content = from_utf8_owned(contents).unwrap();
 
         // FIXME (#9639): This needs to handle non-utf8 paths
         prep.declare_input("file", pth.as_str().unwrap(), file_content);
@@ -500,7 +501,7 @@ fn test() {
             // FIXME (#9639): This needs to handle non-utf8 paths
             run::process_status("gcc", [pth.as_str().unwrap().to_owned(),
                                         ~"-o",
-                                        out.as_str().unwrap().to_owned()]);
+                                        out.as_str().unwrap().to_owned()]).unwrap();
 
             let _proof_of_concept = subcx.prep("subfn");
             // Could run sub-rules inside here.