diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index cbe4c52b47ebb..8896b44f06008 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -234,7 +234,13 @@ pub fn run_tests(config: &config) { // For context, see #8904 io::test::raise_fd_limit(); let res = test::run_tests_console(&opts, tests); - if !res { fail!("Some tests failed"); } + match res { + Ok(true) => {} + Ok(false) => fail!("Some tests failed"), + Err(e) => { + println!("I/O failure during tests: {}", e); + } + } } pub fn test_opts(config: &config) -> test::TestOpts { @@ -255,7 +261,7 @@ pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] { debug!("making tests from {}", config.src_base.display()); let mut tests = ~[]; - let dirs = fs::readdir(&config.src_base); + let dirs = fs::readdir(&config.src_base).unwrap(); for file in dirs.iter() { let file = file.clone(); debug!("inspecting file {}", file.display()); diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index 83fb267b0e720..019803a933779 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -58,9 +58,9 @@ pub fn run(lib_path: &str, }); match opt_process { - Some(ref mut process) => { + Ok(ref mut process) => { for input in input.iter() { - process.input().write(input.as_bytes()); + process.input().write(input.as_bytes()).unwrap(); } let run::ProcessOutput { status, output, error } = process.finish_with_output(); @@ -70,7 +70,7 @@ pub fn run(lib_path: &str, err: str::from_utf8_owned(error).unwrap() }) }, - None => None + Err(..) => None } } @@ -90,13 +90,13 @@ pub fn run_background(lib_path: &str, }); match opt_process { - Some(mut process) => { + Ok(mut process) => { for input in input.iter() { - process.input().write(input.as_bytes()); + process.input().write(input.as_bytes()).unwrap(); } Some(process) }, - None => None + Err(..) => None } } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index c57d2492d459c..0503790ae943c 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -153,7 +153,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) { let rounds = match props.pp_exact { Some(_) => 1, None => 2 }; - let src = File::open(testfile).read_to_end(); + let src = File::open(testfile).read_to_end().unwrap(); let src = str::from_utf8_owned(src).unwrap(); let mut srcs = ~[src]; @@ -175,7 +175,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) { let mut expected = match props.pp_exact { Some(ref file) => { let filepath = testfile.dir_path().join(file); - let s = File::open(&filepath).read_to_end(); + let s = File::open(&filepath).read_to_end().unwrap(); str::from_utf8_owned(s).unwrap() } None => { srcs[srcs.len() - 2u].clone() } @@ -318,8 +318,10 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) { //waiting 1 second for gdbserver start timer::sleep(1000); let result = task::try(proc() { - tcp::TcpStream::connect( - SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 5039 }); + tcp::TcpStream::connect(SocketAddr { + ip: Ipv4Addr(127, 0, 0, 1), + port: 5039, + }).unwrap(); }); if result.is_err() { continue; @@ -361,7 +363,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) { stdout: out, stderr: err, cmdline: cmdline}; - process.force_destroy(); + process.force_destroy().unwrap(); } _=> { @@ -727,7 +729,7 @@ fn compose_and_run_compiler( fn ensure_dir(path: &Path) { if path.is_dir() { return; } - fs::mkdir(path, io::UserRWX); + fs::mkdir(path, io::UserRWX).unwrap(); } fn compose_and_run(config: &config, testfile: &Path, @@ -852,7 +854,7 @@ fn dump_output(config: &config, testfile: &Path, out: &str, err: &str) { fn dump_output_file(config: &config, testfile: &Path, out: &str, extension: &str) { let outfile = make_out_name(config, testfile, extension); - File::create(&outfile).write(out.as_bytes()); + File::create(&outfile).write(out.as_bytes()).unwrap(); } fn make_out_name(config: &config, testfile: &Path, extension: &str) -> Path { @@ -1003,7 +1005,7 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps, fn _arm_push_aux_shared_library(config: &config, testfile: &Path) { let tdir = aux_output_dir_name(config, testfile); - let dirs = fs::readdir(&tdir); + let dirs = fs::readdir(&tdir).unwrap(); for file in dirs.iter() { if file.extension_str() == Some("so") { // FIXME (#9639): This needs to handle non-utf8 paths @@ -1099,7 +1101,7 @@ fn disassemble_extract(config: &config, _props: &TestProps, fn count_extracted_lines(p: &Path) -> uint { - let x = File::open(&p.with_extension("ll")).read_to_end(); + let x = File::open(&p.with_extension("ll")).read_to_end().unwrap(); let x = str::from_utf8_owned(x).unwrap(); x.lines().len() } diff --git a/src/doc/guide-conditions.md b/src/doc/guide-conditions.md index d97de7799024c..5b7494c061879 100644 --- a/src/doc/guide-conditions.md +++ b/src/doc/guide-conditions.md @@ -47,7 +47,7 @@ An example program that does this task reads like this: # #[allow(unused_imports)]; use std::io::{BufferedReader, File}; # mod BufferedReader { -# use std::io::File; +# use std::io::{File, IoResult}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -55,7 +55,7 @@ use std::io::{BufferedReader, File}; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -71,7 +71,6 @@ fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; // Path takes a generic by-value, rather than by reference -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); @@ -245,7 +244,7 @@ and trapping its exit status using `task::try`: use std::io::{BufferedReader, File}; use std::task; # mod BufferedReader { -# use std::io::File; +# use std::io::{File, IoResult}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -253,7 +252,7 @@ use std::task; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -277,7 +276,6 @@ fn main() { fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); @@ -347,7 +345,7 @@ but similarly clear as the version that used `fail!` in the logic where the erro # #[allow(unused_imports)]; use std::io::{BufferedReader, File}; # mod BufferedReader { -# use std::io::File; +# use std::io::{File, IoResult}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -355,7 +353,7 @@ use std::io::{BufferedReader, File}; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -374,7 +372,6 @@ fn main() { fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); @@ -415,7 +412,7 @@ and replaces bad input lines with the pair `(-1,-1)`: # #[allow(unused_imports)]; use std::io::{BufferedReader, File}; # mod BufferedReader { -# use std::io::File; +# use std::io::{File, IoResult}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -423,7 +420,7 @@ use std::io::{BufferedReader, File}; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -447,7 +444,6 @@ fn main() { fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); @@ -489,7 +485,7 @@ Changing the condition's return type from `(int,int)` to `Option<(int,int)>` wil # #[allow(unused_imports)]; use std::io::{BufferedReader, File}; # mod BufferedReader { -# use std::io::File; +# use std::io::{IoResult, File}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -497,7 +493,7 @@ use std::io::{BufferedReader, File}; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -522,7 +518,6 @@ fn main() { fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); @@ -573,7 +568,7 @@ This can be encoded in the handler API by introducing a helper type: `enum Malfo # #[allow(unused_imports)]; use std::io::{BufferedReader, File}; # mod BufferedReader { -# use std::io::File; +# use std::io::{File, IoResult}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -581,7 +576,7 @@ use std::io::{BufferedReader, File}; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -615,7 +610,6 @@ fn main() { fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); @@ -696,7 +690,7 @@ a second condition and a helper function will suffice: # #[allow(unused_imports)]; use std::io::{BufferedReader, File}; # mod BufferedReader { -# use std::io::File; +# use std::io::{File, IoResult}; # use std::io::MemReader; # use std::io::BufferedReader; # static s : &'static [u8] = bytes!("1 2\n\ @@ -704,7 +698,7 @@ use std::io::{BufferedReader, File}; # 789 123\n\ # 45 67\n\ # "); -# pub fn new(_inner: Option) -> BufferedReader { +# pub fn new(_inner: IoResult) -> BufferedReader { # BufferedReader::new(MemReader::new(s.to_owned())) # } # } @@ -752,7 +746,6 @@ fn parse_int(x: &str) -> int { fn read_int_pairs() -> ~[(int,int)] { let mut pairs = ~[]; -# let _g = std::io::ignore_io_error(); let path = Path::new(&"foo.txt"); let mut reader = BufferedReader::new(File::open(&path)); diff --git a/src/etc/combine-tests.py b/src/etc/combine-tests.py index e87187abbcbf4..457c0b683ac68 100755 --- a/src/etc/combine-tests.py +++ b/src/etc/combine-tests.py @@ -69,6 +69,7 @@ def scrub(b): use run_pass_stage2::*; use std::io; use std::io::Writer; +#[allow(warnings)] fn main() { let mut out = io::stdout(); """ diff --git a/src/libextra/arc.rs b/src/libextra/arc.rs index 43366d2aa6d84..9615bdc2ad731 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 } @@ -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 } diff --git a/src/libextra/base64.rs b/src/libextra/base64.rs index 738afcd5c5f93..556032af1ac84 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 5bbea491ac208..1900313ab6c8e 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 4fd59bb3aa503..d4e1ae123378e 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 f8b1c216529b1..ef8e0999521b8 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 serialize::Encodable 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> Parser { /// Decodes a json value from an `&mut io::Reader` pub fn from_reader(rdr: &mut io::Reader) -> Result { - 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 e2a4b52c810d2..358dca5e5ac47 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 096e588277468..8752020f564e0 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 26a555a646c58..0a29fd1898229 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 c9ea556f23a50..5948f356a651d 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 ef5a05b6a3e51..c4d27b25b5503 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 { } impl ConsoleTestState { - pub fn new(opts: &TestOpts, _: Option) -> ConsoleTestState { + pub fn new(opts: &TestOpts, + _: Option) -> io::IoResult> { 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 ConsoleTestState { 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 ConsoleTestState { 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 ConsoleTestState { 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, - ratchet_pct: Option) -> bool { + ratchet_pct: Option) -> io::IoResult { 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(event: &TestEvent, st: &mut ConsoleTestState) { + tests: ~[TestDescAndFn]) -> io::IoResult { + fn callback(event: &TestEvent, + st: &mut ConsoleTestState) -> 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::); + let mut st = if_ok!(ConsoleTestState::new(opts, None::)); 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 3e5b9b797d31b..0a122ad58bd33 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -766,14 +766,14 @@ pub fn strptime(s: &str, format: &str) -> Result { 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 { } } - 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 35c53c9307c49..6138c5416f2b4 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 9163a89203913..29d3066b2f590 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 70bbe02d32f17..4d8e7e50dcfd5 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. diff --git a/src/libglob/lib.rs b/src/libglob/lib.rs index 98bf5533210ee..c6ecb7697da4e 100644 --- a/src/libglob/lib.rs +++ b/src/libglob/lib.rs @@ -29,7 +29,6 @@ #[license = "MIT/ASL2"]; use std::{os, path}; -use std::io; use std::io::fs; use std::path::is_sep; @@ -153,7 +152,7 @@ impl Iterator for Paths { } fn list_dir_sorted(path: &Path) -> ~[Path] { - match io::result(|| fs::readdir(path)) { + match fs::readdir(path) { Ok(mut children) => { children.sort_by(|p1, p2| p2.filename().cmp(&p1.filename())); children diff --git a/src/libgreen/macros.rs b/src/libgreen/macros.rs index e07cc1ca00088..ef2c77fc8e25f 100644 --- a/src/libgreen/macros.rs +++ b/src/libgreen/macros.rs @@ -56,16 +56,17 @@ pub fn dumb_println(args: &fmt::Arguments) { struct Stderr; impl io::Writer for Stderr { - fn write(&mut self, data: &[u8]) { + fn write(&mut self, data: &[u8]) -> io::IoResult<()> { unsafe { libc::write(libc::STDERR_FILENO, data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } + Ok(()) // just ignore the result } } let mut w = Stderr; - fmt::writeln(&mut w as &mut io::Writer, args); + let _ = fmt::writeln(&mut w as &mut io::Writer, args); } pub fn abort(msg: &str) -> ! { diff --git a/src/libnative/bookkeeping.rs b/src/libnative/bookkeeping.rs index b07e4271ee448..868586b36911e 100644 --- a/src/libnative/bookkeeping.rs +++ b/src/libnative/bookkeeping.rs @@ -23,7 +23,7 @@ static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT; static mut TASK_LOCK: Mutex = MUTEX_INIT; pub fn increment() { - unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst); } + let _ = unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst) }; } pub fn decrement() { diff --git a/src/libnative/io/file.rs b/src/libnative/io/file.rs index acab7ce3a91b4..cc5b0770d4d20 100644 --- a/src/libnative/io/file.rs +++ b/src/libnative/io/file.rs @@ -111,17 +111,14 @@ impl FileDesc { } impl io::Reader for FileDesc { - fn read(&mut self, buf: &mut [u8]) -> Option { - match self.inner_read(buf) { Ok(n) => Some(n), Err(..) => None } + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { + self.inner_read(buf) } } impl io::Writer for FileDesc { - fn write(&mut self, buf: &[u8]) { - match self.inner_write(buf) { - Ok(()) => {} - Err(e) => { io::io_error::cond.raise(e); } - } + fn write(&mut self, buf: &[u8]) -> io::IoResult<()> { + self.inner_write(buf) } } @@ -425,7 +422,7 @@ impl rtio::RtioFileStream for CFile { impl Drop for CFile { fn drop(&mut self) { - unsafe { libc::fclose(self.file); } + unsafe { let _ = libc::fclose(self.file); } } } @@ -515,7 +512,7 @@ pub fn readdir(p: &CString) -> IoResult<~[Path]> { paths.push(Path::new(cstr)); entry_ptr = readdir(dir_ptr); } - closedir(dir_ptr); + assert_eq!(closedir(dir_ptr), 0); Ok(paths) } else { Err(super::last_error()) @@ -564,7 +561,7 @@ pub fn readdir(p: &CString) -> IoResult<~[Path]> { } more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE); } - FindClose(find_handle); + assert!(FindClose(find_handle) != 0); free(wfd_ptr as *mut c_void); Ok(paths) } else { @@ -686,7 +683,9 @@ pub fn readlink(p: &CString) -> IoResult { ptr::mut_null()) }) }; - if handle == ptr::mut_null() { return Err(super::last_error()) } + if handle as int == libc::INVALID_HANDLE_VALUE as int { + return Err(super::last_error()) + } let ret = fill_utf16_buf_and_decode(|buf, sz| { unsafe { libc::GetFinalPathNameByHandleW(handle, buf as *u16, sz, @@ -697,7 +696,7 @@ pub fn readlink(p: &CString) -> IoResult { Some(s) => Ok(Path::new(s)), None => Err(super::last_error()), }; - unsafe { libc::CloseHandle(handle) }; + assert!(unsafe { libc::CloseHandle(handle) } != 0); return ret; } @@ -935,7 +934,7 @@ mod tests { let mut reader = FileDesc::new(input, true); let mut writer = FileDesc::new(out, true); - writer.inner_write(bytes!("test")); + writer.inner_write(bytes!("test")).unwrap(); let mut buf = [0u8, ..4]; match reader.inner_read(buf) { Ok(4) => { @@ -960,9 +959,9 @@ mod tests { assert!(!f.is_null()); let mut file = CFile::new(f); - file.write(bytes!("test")); + file.write(bytes!("test")).unwrap(); let mut buf = [0u8, ..4]; - file.seek(0, io::SeekSet); + let _ = file.seek(0, io::SeekSet).unwrap(); match file.read(buf) { Ok(4) => { assert_eq!(buf[0], 't' as u8); diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 2f4bec22755f6..ac68b1523d7d9 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -112,8 +112,8 @@ fn setsockopt(fd: sock_t, opt: libc::c_int, val: libc::c_int, } } -#[cfg(windows)] unsafe fn close(sock: sock_t) { libc::closesocket(sock); } -#[cfg(unix)] unsafe fn close(sock: sock_t) { libc::close(sock); } +#[cfg(windows)] unsafe fn close(sock: sock_t) { let _ = libc::closesocket(sock); } +#[cfg(unix)] unsafe fn close(sock: sock_t) { let _ = libc::close(sock); } fn sockname(fd: sock_t, f: extern "system" unsafe fn(sock_t, *mut libc::sockaddr, diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index 13dd4298777c6..2a061c5f9b204 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -102,9 +102,9 @@ impl Process { cwd.as_ref(), in_fd, out_fd, err_fd); unsafe { - for pipe in in_pipe.iter() { libc::close(pipe.input); } - for pipe in out_pipe.iter() { libc::close(pipe.out); } - for pipe in err_pipe.iter() { libc::close(pipe.out); } + for pipe in in_pipe.iter() { let _ = libc::close(pipe.input); } + for pipe in out_pipe.iter() { let _ = libc::close(pipe.out); } + for pipe in err_pipe.iter() { let _ = libc::close(pipe.out); } } match res { @@ -149,9 +149,8 @@ impl rtio::RtioProcess for Process { unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> { match signal { io::process::PleaseExitSignal | io::process::MustDieSignal => { - libc::funcs::extra::kernel32::TerminateProcess( - cast::transmute(pid), 1); - Ok(()) + let ret = libc::TerminateProcess(pid as libc::HANDLE, 1); + super::mkerr_winbool(ret) } _ => Err(io::IoError { kind: io::OtherIoError, @@ -163,8 +162,8 @@ impl rtio::RtioProcess for Process { #[cfg(not(windows))] unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> { - libc::funcs::posix88::signal::kill(pid, signal as c_int); - Ok(()) + let r = libc::funcs::posix88::signal::kill(pid, signal as c_int); + super::mkerr_libc(r) } } } @@ -255,9 +254,9 @@ fn spawn_process_os(prog: &str, args: &[~str], }) }); - CloseHandle(si.hStdInput); - CloseHandle(si.hStdOutput); - CloseHandle(si.hStdError); + assert!(CloseHandle(si.hStdInput) != 0); + assert!(CloseHandle(si.hStdOutput) != 0); + assert!(CloseHandle(si.hStdError) != 0); match create_err { Some(err) => return Err(err), @@ -269,7 +268,7 @@ fn spawn_process_os(prog: &str, args: &[~str], // able to close it later. We don't close the process handle however // because std::we want the process id to stay valid at least until the // calling code closes the process handle. - CloseHandle(pi.hThread); + assert!(CloseHandle(pi.hThread) != 0); Ok(SpawnProcessResult { pid: pi.dwProcessId as pid_t, @@ -445,24 +444,24 @@ fn spawn_process_os(prog: &str, args: &[~str], rustrt::rust_unset_sigprocmask(); if in_fd == -1 { - libc::close(libc::STDIN_FILENO); + let _ = libc::close(libc::STDIN_FILENO); } else if retry(|| dup2(in_fd, 0)) == -1 { fail!("failure in dup2(in_fd, 0): {}", os::last_os_error()); } if out_fd == -1 { - libc::close(libc::STDOUT_FILENO); + let _ = libc::close(libc::STDOUT_FILENO); } else if retry(|| dup2(out_fd, 1)) == -1 { fail!("failure in dup2(out_fd, 1): {}", os::last_os_error()); } if err_fd == -1 { - libc::close(libc::STDERR_FILENO); + let _ = libc::close(libc::STDERR_FILENO); } else if retry(|| dup2(err_fd, 2)) == -1 { fail!("failure in dup3(err_fd, 2): {}", os::last_os_error()); } // close all other fds for fd in range(3, getdtablesize()).rev() { if fd != output.fd() { - close(fd as c_int); + let _ = close(fd as c_int); } } @@ -478,7 +477,7 @@ fn spawn_process_os(prog: &str, args: &[~str], } }); with_argv(prog, args, |argv| { - execvp(*argv, argv); + let _ = execvp(*argv, argv); let errno = os::errno(); let bytes = [ (errno << 24) as u8, @@ -576,9 +575,9 @@ fn with_dirp(d: Option<&Path>, cb: |*libc::c_char| -> T) -> T { #[cfg(windows)] fn free_handle(handle: *()) { - unsafe { - libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle)); - } + assert!(unsafe { + libc::CloseHandle(cast::transmute(handle)) != 0 + }) } #[cfg(unix)] @@ -629,15 +628,15 @@ fn waitpid(pid: pid_t) -> p::ProcessExit { loop { let mut status = 0; if GetExitCodeProcess(process, &mut status) == FALSE { - CloseHandle(process); + assert!(CloseHandle(process) != 0); fail!("failure in GetExitCodeProcess: {}", os::last_os_error()); } if status != STILL_ACTIVE { - CloseHandle(process); + assert!(CloseHandle(process) != 0); return p::ExitStatus(status as int); } if WaitForSingleObject(process, INFINITE) == WAIT_FAILED { - CloseHandle(process); + assert!(CloseHandle(process) != 0); fail!("failure in WaitForSingleObject: {}", os::last_os_error()); } } diff --git a/src/libnative/io/timer_helper.rs b/src/libnative/io/timer_helper.rs index 74759b467d4a7..7311be46e8bd2 100644 --- a/src/libnative/io/timer_helper.rs +++ b/src/libnative/io/timer_helper.rs @@ -126,11 +126,11 @@ mod imp { } pub fn signal(handle: HANDLE) { - unsafe { SetEvent(handle); } + assert!(unsafe { SetEvent(handle) != 0 }); } pub fn close(handle: HANDLE) { - unsafe { CloseHandle(handle); } + assert!(unsafe { CloseHandle(handle) != 0 }); } extern "system" { diff --git a/src/libnative/io/timer_other.rs b/src/libnative/io/timer_other.rs index bc005f2fe8dd3..cda239329dcc0 100644 --- a/src/libnative/io/timer_other.rs +++ b/src/libnative/io/timer_other.rs @@ -187,7 +187,7 @@ fn helper(input: libc::c_int, messages: Port) { // drain the file descriptor let mut buf = [0]; - fd.inner_read(buf).unwrap(); + assert_eq!(fd.inner_read(buf).unwrap(), 1); } -1 if os::errno() == libc::EINTR as int => {} @@ -216,7 +216,8 @@ impl Timer { } pub fn sleep(ms: u64) { - unsafe { libc::usleep((ms * 1000) as libc::c_uint); } + // FIXME: this can fail because of EINTR, what do do? + let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) }; } fn inner(&mut self) -> ~Inner { diff --git a/src/libnative/io/timer_timerfd.rs b/src/libnative/io/timer_timerfd.rs index ca20314997e8c..7c22e90bbffe2 100644 --- a/src/libnative/io/timer_timerfd.rs +++ b/src/libnative/io/timer_timerfd.rs @@ -96,7 +96,7 @@ fn helper(input: libc::c_int, messages: Port) { if fd == input { let mut buf = [0, ..1]; // drain the input file descriptor of its input - FileDesc::new(fd, false).inner_read(buf).unwrap(); + let _ = FileDesc::new(fd, false).inner_read(buf).unwrap(); incoming = true; } else { let mut bits = [0, ..8]; @@ -104,7 +104,7 @@ fn helper(input: libc::c_int, messages: Port) { // // FIXME: should this perform a send() this number of // times? - FileDesc::new(fd, false).inner_read(bits).unwrap(); + let _ = FileDesc::new(fd, false).inner_read(bits).unwrap(); let remove = { match map.find(&fd).expect("fd unregistered") { &(ref c, oneshot) => !c.try_send(()) || oneshot @@ -166,7 +166,8 @@ impl Timer { } pub fn sleep(ms: u64) { - unsafe { libc::usleep((ms * 1000) as libc::c_uint); } + // FIXME: this can fail because of EINTR, what do do? + let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) }; } fn remove(&mut self) { diff --git a/src/libnative/io/timer_win32.rs b/src/libnative/io/timer_win32.rs index e359d99eedf65..6b472d2f46d59 100644 --- a/src/libnative/io/timer_win32.rs +++ b/src/libnative/io/timer_win32.rs @@ -62,8 +62,8 @@ fn helper(input: libc::HANDLE, messages: Port) { c.send(()); match objs.iter().position(|&o| o == obj) { Some(i) => { - objs.remove(i); - chans.remove(i - 1); + drop(objs.remove(i)); + drop(chans.remove(i - 1)); } None => {} } @@ -83,8 +83,8 @@ fn helper(input: libc::HANDLE, messages: Port) { } }; if remove { - objs.remove(idx as uint); - chans.remove(idx as uint - 1); + drop(objs.remove(idx as uint)); + drop(chans.remove(idx as uint - 1)); } } } @@ -133,7 +133,7 @@ impl rtio::RtioTimer for Timer { ptr::mut_null(), 0) }, 1); - unsafe { imp::WaitForSingleObject(self.obj, libc::INFINITE); } + let _ = unsafe { imp::WaitForSingleObject(self.obj, libc::INFINITE) }; } fn oneshot(&mut self, msecs: u64) -> Port<()> { @@ -173,7 +173,7 @@ impl rtio::RtioTimer for Timer { impl Drop for Timer { fn drop(&mut self) { self.remove(); - unsafe { libc::CloseHandle(self.obj); } + assert!(unsafe { libc::CloseHandle(self.obj) != 0 }); } } diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index f69ad8fc1aa7f..1e4317af39758 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -21,6 +21,7 @@ #[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://static.rust-lang.org/doc/master")]; +#[deny(unused_result, unused_must_use)]; // NB this crate explicitly does *not* allow glob imports, please seriously // consider whether they're needed before adding that feature here (the @@ -61,9 +62,10 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int { rt::init(argc, argv); let mut exit_code = None; let mut main = Some(main); - task::new((my_stack_bottom, my_stack_top)).run(|| { + let t = task::new((my_stack_bottom, my_stack_top)).run(|| { exit_code = Some(run(main.take_unwrap())); }); + drop(t); unsafe { rt::cleanup(); } // If the exit code wasn't set, then the task block must have failed. return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE); diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 3742517970118..0def5cb405338 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -103,7 +103,8 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) { let mut f = Some(f); let mut task = task; task.put_runtime(ops as ~rt::Runtime); - task.run(|| { f.take_unwrap()() }); + let t = task.run(|| { f.take_unwrap()() }); + drop(t); bookkeeping::decrement(); }) } diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs index 661ae5b7297b2..18aef17b9eb77 100644 --- a/src/librustc/back/archive.rs +++ b/src/librustc/back/archive.rs @@ -17,6 +17,7 @@ use lib::llvm::{ArchiveRef, llvm}; use std::cast; use std::io::fs; +use std::io; use std::libc; use std::os; use std::run::{ProcessOptions, Process, ProcessOutput}; @@ -50,9 +51,8 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>, Some(p) => { debug!("inside {}", p.display()); } None => {} } - let mut opt_prog = Process::new(ar, args.as_slice(), opts); - match opt_prog { - Some(ref mut prog) => { + match Process::new(ar, args.as_slice(), opts) { + Ok(mut prog) => { let o = prog.finish_with_output(); if !o.status.success() { sess.err(format!("{} {} failed with: {}", ar, args.connect(" "), @@ -63,8 +63,8 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>, } o }, - None => { - sess.err(format!("could not exec `{}`", ar)); + Err(e) => { + sess.err(format!("could not exec `{}`: {}", ar, e)); sess.abort_if_errors(); fail!("rustc::back::archive::run_ar() should not reach this point"); } @@ -94,7 +94,7 @@ impl Archive { let archive = os::make_absolute(&self.dst); run_ar(self.sess, "x", Some(loc.path()), [&archive, &Path::new(file)]); - fs::File::open(&loc.path().join(file)).read_to_end() + fs::File::open(&loc.path().join(file)).read_to_end().unwrap() } else { run_ar(self.sess, "p", None, [&self.dst, &Path::new(file)]).output } @@ -102,9 +102,9 @@ impl Archive { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. - pub fn add_native_library(&mut self, name: &str) { + pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> { let location = self.find_library(name); - self.add_archive(&location, name, []); + self.add_archive(&location, name, []) } /// Adds all of the contents of the rlib at the specified path to this @@ -112,14 +112,15 @@ impl Archive { /// /// This ignores adding the bytecode from the rlib, and if LTO is enabled /// then the object file also isn't added. - pub fn add_rlib(&mut self, rlib: &Path, name: &str, lto: bool) { + pub fn add_rlib(&mut self, rlib: &Path, name: &str, + lto: bool) -> io::IoResult<()> { let object = format!("{}.o", name); let bytecode = format!("{}.bc", name); let mut ignore = ~[METADATA_FILENAME, bytecode.as_slice()]; if lto { ignore.push(object.as_slice()); } - self.add_archive(rlib, name, ignore); + self.add_archive(rlib, name, ignore) } /// Adds an arbitrary file to this archive @@ -144,7 +145,8 @@ impl Archive { str::from_utf8(output.output).unwrap().lines().map(|s| s.to_owned()).collect() } - fn add_archive(&mut self, archive: &Path, name: &str, skip: &[&str]) { + fn add_archive(&mut self, archive: &Path, name: &str, + skip: &[&str]) -> io::IoResult<()> { let loc = TempDir::new("rsar").unwrap(); // First, extract the contents of the archive to a temporary directory @@ -159,7 +161,7 @@ impl Archive { // We skip any files explicitly desired for skipping, and we also skip // all SYMDEF files as these are just magical placeholders which get // re-created when we make a new archive anyway. - let files = fs::readdir(loc.path()); + let files = if_ok!(fs::readdir(loc.path())); let mut inputs = ~[]; for file in files.iter() { let filename = file.filename_str().unwrap(); @@ -168,7 +170,7 @@ impl Archive { let filename = format!("r-{}-{}", name, filename); let new_filename = file.with_filename(filename); - fs::rename(file, &new_filename); + if_ok!(fs::rename(file, &new_filename)); inputs.push(new_filename); } @@ -176,6 +178,7 @@ impl Archive { let mut args = ~[&self.dst]; args.extend(&mut inputs.iter()); run_ar(self.sess, "r", None, args.as_slice()); + Ok(()) } fn find_library(&self, name: &str) -> Path { diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index fc38fa25a2146..4d6576fed3462 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -100,7 +100,6 @@ pub mod write { use util::common::time; use std::c_str::ToCStr; - use std::io; use std::libc::{c_uint, c_int}; use std::path::Path; use std::run; @@ -297,12 +296,8 @@ pub mod write { assembly.as_str().unwrap().to_owned()]; debug!("{} '{}'", cc, args.connect("' '")); - let opt_prog = { - let _guard = io::ignore_io_error(); - run::process_output(cc, args) - }; - match opt_prog { - Some(prog) => { + match run::process_output(cc, args) { + Ok(prog) => { if !prog.status.success() { sess.err(format!("linking with `{}` failed: {}", cc, prog.status)); sess.note(format!("{} arguments: '{}'", cc, args.connect("' '"))); @@ -310,8 +305,8 @@ pub mod write { sess.abort_if_errors(); } }, - None => { - sess.err(format!("could not exec the linker `{}`", cc)); + Err(e) => { + sess.err(format!("could not exec the linker `{}`: {}", cc, e)); sess.abort_if_errors(); } } @@ -768,6 +763,15 @@ fn get_system_tool(sess: Session, tool: &str) -> ~str { } } +fn remove(sess: Session, path: &Path) { + match fs::unlink(path) { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to remove {}: {}", path.display(), e)); + } + } +} + /// Perform the linkage portion of the compilation phase. This will generate all /// of the requested outputs for this compilation session. pub fn link_binary(sess: Session, @@ -785,17 +789,15 @@ pub fn link_binary(sess: Session, // Remove the temporary object file and metadata if we aren't saving temps if !sess.opts.save_temps { - fs::unlink(obj_filename); - fs::unlink(&obj_filename.with_extension("metadata.o")); + remove(sess, obj_filename); + remove(sess, &obj_filename.with_extension("metadata.o")); } out_filenames } fn is_writeable(p: &Path) -> bool { - use std::io; - - match io::result(|| p.stat()) { + match p.stat() { Err(..) => true, Ok(m) => m.perm & io::UserWrite == io::UserWrite } @@ -884,7 +886,7 @@ fn link_rlib(sess: Session, for &(ref l, kind) in used_libraries.get().iter() { match kind { cstore::NativeStatic => { - a.add_native_library(l.as_slice()); + a.add_native_library(l.as_slice()).unwrap(); } cstore::NativeFramework | cstore::NativeUnknown => {} } @@ -919,16 +921,23 @@ fn link_rlib(sess: Session, // the same filename for metadata (stomping over one another) let tmpdir = TempDir::new("rustc").expect("needs a temp dir"); let metadata = tmpdir.path().join(METADATA_FILENAME); - fs::File::create(&metadata).write(trans.metadata); + match fs::File::create(&metadata).write(trans.metadata) { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to write {}: {}", + metadata.display(), e)); + sess.abort_if_errors(); + } + } a.add_file(&metadata, false); - fs::unlink(&metadata); + remove(sess, &metadata); // For LTO purposes, the bytecode of this library is also inserted // into the archive. let bc = obj_filename.with_extension("bc"); a.add_file(&bc, false); if !sess.opts.save_temps { - fs::unlink(&bc); + remove(sess, &bc); } // After adding all files to the archive, we need to update the @@ -959,7 +968,7 @@ fn link_rlib(sess: Session, // metadata file). fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) { let mut a = link_rlib(sess, None, obj_filename, out_filename); - a.add_native_library("morestack"); + a.add_native_library("morestack").unwrap(); let crates = sess.cstore.get_used_crates(cstore::RequireStatic); for &(cnum, ref path) in crates.iter() { @@ -970,7 +979,7 @@ fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) { continue } }; - a.add_rlib(&p, name, sess.lto()); + a.add_rlib(&p, name, sess.lto()).unwrap(); let native_libs = csearch::get_native_libraries(sess.cstore, cnum); for &(kind, ref lib) in native_libs.iter() { let name = match kind { @@ -1004,14 +1013,10 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path, // Invoke the system linker debug!("{} {}", cc_prog, cc_args.connect(" ")); - let opt_prog = { - let _guard = io::ignore_io_error(); - time(sess.time_passes(), "running linker", (), |()| - run::process_output(cc_prog, cc_args)) - }; - - match opt_prog { - Some(prog) => { + let prog = time(sess.time_passes(), "running linker", (), |()| + run::process_output(cc_prog, cc_args)); + match prog { + Ok(prog) => { if !prog.status.success() { sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status)); sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '"))); @@ -1019,8 +1024,8 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path, sess.abort_if_errors(); } }, - None => { - sess.err(format!("could not exec the linker `{}`", cc_prog)); + Err(e) => { + sess.err(format!("could not exec the linker `{}`: {}", cc_prog, e)); sess.abort_if_errors(); } } @@ -1030,8 +1035,14 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path, // the symbols if sess.targ_cfg.os == abi::OsMacos && sess.opts.debuginfo { // FIXME (#9639): This needs to handle non-utf8 paths - run::process_status("dsymutil", - [out_filename.as_str().unwrap().to_owned()]); + match run::process_status("dsymutil", + [out_filename.as_str().unwrap().to_owned()]) { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to run dsymutil: {}", e)); + sess.abort_if_errors(); + } + } } } @@ -1225,7 +1236,16 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session, time(sess.time_passes(), format!("altering {}.rlib", name), (), |()| { let dst = tmpdir.join(cratepath.filename().unwrap()); - fs::copy(&cratepath, &dst); + match fs::copy(&cratepath, &dst) { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to copy {} to {}: {}", + cratepath.display(), + dst.display(), + e)); + sess.abort_if_errors(); + } + } let dst_str = dst.as_str().unwrap().to_owned(); let mut archive = Archive::open(sess, dst); archive.remove_file(format!("{}.o", name)); diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index b779c7e73b1c9..a61c297956d78 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -399,7 +399,7 @@ pub fn phase_5_run_llvm_passes(sess: Session, // Remove assembly source, unless --save-temps was specified if !sess.opts.save_temps { - fs::unlink(&asm_filename); + fs::unlink(&asm_filename).unwrap(); } } else { time(sess.time_passes(), "LLVM passes", (), |_| @@ -455,33 +455,39 @@ pub fn stop_after_phase_5(sess: Session) -> bool { return false; } -fn write_out_deps(sess: Session, input: &Input, outputs: &OutputFilenames, crate: &ast::Crate) +fn write_out_deps(sess: Session, input: &Input, outputs: &OutputFilenames, + crate: &ast::Crate) -> io::IoResult<()> { let lm = link::build_link_meta(sess, crate.attrs, &outputs.obj_filename, - &mut ::util::sha2::Sha256::new()); + &mut ::util::sha2::Sha256::new()); let sess_outputs = sess.outputs.borrow(); let out_filenames = sess_outputs.get().iter() - .map(|&output| link::filename_for_input(&sess, output, &lm, &outputs.out_filename)) + .map(|&output| link::filename_for_input(&sess, output, &lm, + &outputs.out_filename)) .to_owned_vec(); - // Write out dependency rules to the dep-info file if requested with --dep-info + // Write out dependency rules to the dep-info file if requested with + // --dep-info let deps_filename = match sess.opts.write_dependency_info { // Use filename from --dep-file argument if given (true, Some(ref filename)) => filename.clone(), - // Use default filename: crate source filename with extension replaced by ".d" + // Use default filename: crate source filename with extension replaced + // by ".d" (true, None) => match *input { FileInput(ref input_path) => { - let filestem = input_path.filestem().expect("input file must have stem"); - let filename = out_filenames[0].dir_path().join(filestem).with_extension("d"); - filename + let filestem = input_path.filestem().expect("input file must \ + have stem"); + let filename = out_filenames[0].dir_path().join(filestem); + filename.with_extension("d") }, StrInput(..) => { - sess.warn("can not write --dep-info without a filename when compiling stdin."); - return; + sess.warn("can not write --dep-info without a filename \ + when compiling stdin."); + return Ok(()); }, }, - _ => return, + _ => return Ok(()), }; // Build a list of files used to compile the output and @@ -499,11 +505,12 @@ fn write_out_deps(sess: Session, input: &Input, outputs: &OutputFilenames, crate }) .collect() }; - let mut file = io::File::create(&deps_filename); + let mut file = if_ok!(io::File::create(&deps_filename)); for path in out_filenames.iter() { - write!(&mut file as &mut Writer, - "{}: {}\n\n", path.display(), files.connect(" ")); + if_ok!(write!(&mut file as &mut Writer, + "{}: {}\n\n", path.display(), files.connect(" "))); } + Ok(()) } pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input, @@ -521,7 +528,7 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input, let outputs = build_output_filenames(input, outdir, output, expanded_crate.attrs, sess); - write_out_deps(sess, input, outputs, &expanded_crate); + write_out_deps(sess, input, outputs, &expanded_crate).unwrap(); if stop_after_phase_2(sess) { return; } @@ -541,32 +548,33 @@ struct IdentifiedAnnotation { } impl pprust::PpAnn for IdentifiedAnnotation { - fn pre(&self, node: pprust::AnnNode) { + fn pre(&self, node: pprust::AnnNode) -> io::IoResult<()> { match node { pprust::NodeExpr(s, _) => pprust::popen(s), - _ => () + _ => Ok(()) } } - fn post(&self, node: pprust::AnnNode) { + fn post(&self, node: pprust::AnnNode) -> io::IoResult<()> { match node { pprust::NodeItem(s, item) => { - pp::space(&mut s.s); - pprust::synth_comment(s, item.id.to_str()); + if_ok!(pp::space(&mut s.s)); + if_ok!(pprust::synth_comment(s, item.id.to_str())); } pprust::NodeBlock(s, blk) => { - pp::space(&mut s.s); - pprust::synth_comment(s, ~"block " + blk.id.to_str()); + if_ok!(pp::space(&mut s.s)); + if_ok!(pprust::synth_comment(s, ~"block " + blk.id.to_str())); } pprust::NodeExpr(s, expr) => { - pp::space(&mut s.s); - pprust::synth_comment(s, expr.id.to_str()); - pprust::pclose(s); + if_ok!(pp::space(&mut s.s)); + if_ok!(pprust::synth_comment(s, expr.id.to_str())); + if_ok!(pprust::pclose(s)); } pprust::NodePat(s, pat) => { - pp::space(&mut s.s); - pprust::synth_comment(s, ~"pat " + pat.id.to_str()); + if_ok!(pp::space(&mut s.s)); + if_ok!(pprust::synth_comment(s, ~"pat " + pat.id.to_str())); } } + Ok(()) } } @@ -575,24 +583,26 @@ struct TypedAnnotation { } impl pprust::PpAnn for TypedAnnotation { - fn pre(&self, node: pprust::AnnNode) { + fn pre(&self, node: pprust::AnnNode) -> io::IoResult<()> { match node { pprust::NodeExpr(s, _) => pprust::popen(s), - _ => () + _ => Ok(()) } } - fn post(&self, node: pprust::AnnNode) { + fn post(&self, node: pprust::AnnNode) -> io::IoResult<()> { let tcx = self.analysis.ty_cx; match node { pprust::NodeExpr(s, expr) => { - pp::space(&mut s.s); - pp::word(&mut s.s, "as"); - pp::space(&mut s.s); - pp::word(&mut s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr))); - pprust::pclose(s); + if_ok!(pp::space(&mut s.s)); + if_ok!(pp::word(&mut s.s, "as")); + if_ok!(pp::space(&mut s.s)); + if_ok!(pp::word(&mut s.s, + ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)))); + if_ok!(pprust::pclose(s)); } _ => () } + Ok(()) } } @@ -638,7 +648,7 @@ pub fn pretty_print_input(sess: Session, &mut rdr, ~stdout as ~io::Writer, annotation, - is_expanded); + is_expanded).unwrap(); } pub fn get_os(triple: &str) -> Option { @@ -1167,10 +1177,11 @@ pub fn early_error(emitter: &diagnostic::Emitter, msg: &str) -> ! { fail!(diagnostic::FatalError); } -pub fn list_metadata(sess: Session, path: &Path, out: &mut io::Writer) { +pub fn list_metadata(sess: Session, path: &Path, + out: &mut io::Writer) -> io::IoResult<()> { metadata::loader::list_file_metadata( token::get_ident_interner(), - session::sess_os_to_meta_os(sess.targ_cfg.os), path, out); + session::sess_os_to_meta_os(sess.targ_cfg.os), path, out) } #[cfg(test)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7ba96516bf91b..c5f7d61c224a5 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -54,6 +54,11 @@ use syntax::diagnostic::Emitter; use syntax::diagnostic; use syntax::parse; +#[cfg(stage0)] +macro_rules! if_ok ( + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) +) + pub mod middle { pub mod trans; pub mod ty; @@ -236,8 +241,8 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { 1u => { let ifile = matches.free[0].as_slice(); if ifile == "-" { - let src = - str::from_utf8_owned(io::stdin().read_to_end()).unwrap(); + let contents = io::stdin().read_to_end().unwrap(); + let src = str::from_utf8_owned(contents).unwrap(); (d::StrInput(src), None) } else { (d::FileInput(Path::new(ifile)), Some(Path::new(ifile))) @@ -267,7 +272,7 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { d::FileInput(ref ifile) => { let mut stdout = io::stdout(); d::list_metadata(sess, &(*ifile), - &mut stdout as &mut io::Writer); + &mut stdout as &mut io::Writer).unwrap(); } d::StrInput(_) => { d::early_error(demitter, "can not list metadata for stdin"); diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index deae31abdcb5e..8ba98e84dfa50 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1111,15 +1111,15 @@ fn get_attributes(md: ebml::Doc) -> ~[ast::Attribute] { } fn list_crate_attributes(intr: @IdentInterner, md: ebml::Doc, hash: &str, - out: &mut io::Writer) { - write!(out, "=Crate Attributes ({})=\n", hash); + out: &mut io::Writer) -> io::IoResult<()> { + if_ok!(write!(out, "=Crate Attributes ({})=\n", hash)); let r = get_attributes(md); for attr in r.iter() { - write!(out, "{}\n", pprust::attribute_to_str(attr, intr)); + if_ok!(write!(out, "{}\n", pprust::attribute_to_str(attr, intr))); } - write!(out, "\n\n"); + write!(out, "\n\n") } pub fn get_crate_attributes(data: &[u8]) -> ~[ast::Attribute] { @@ -1154,21 +1154,22 @@ pub fn get_crate_deps(data: &[u8]) -> ~[CrateDep] { return deps; } -fn list_crate_deps(data: &[u8], out: &mut io::Writer) { - write!(out, "=External Dependencies=\n"); +fn list_crate_deps(data: &[u8], out: &mut io::Writer) -> io::IoResult<()> { + if_ok!(write!(out, "=External Dependencies=\n")); let r = get_crate_deps(data); for dep in r.iter() { let string = token::get_ident(dep.name.name); - write!(out, - "{} {}-{}-{}\n", - dep.cnum, - string.get(), - dep.hash, - dep.vers); + if_ok!(write!(out, + "{} {}-{}-{}\n", + dep.cnum, + string.get(), + dep.hash, + dep.vers)); } - write!(out, "\n"); + if_ok!(write!(out, "\n")); + Ok(()) } pub fn get_crate_hash(data: &[u8]) -> ~str { @@ -1186,11 +1187,11 @@ pub fn get_crate_vers(data: &[u8]) -> ~str { } pub fn list_crate_metadata(intr: @IdentInterner, bytes: &[u8], - out: &mut io::Writer) { + out: &mut io::Writer) -> io::IoResult<()> { let hash = get_crate_hash(bytes); let md = reader::Doc(bytes); - list_crate_attributes(intr, md, hash, out); - list_crate_deps(bytes, out); + if_ok!(list_crate_attributes(intr, md, hash, out)); + list_crate_deps(bytes, out) } // Translates a def_id from an external crate to a def_id for the current diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6a1c3dd4b62e0..d56d211b713ee 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -10,6 +10,7 @@ // Metadata encoding +#[allow(unused_must_use)]; // everything is just a MemWriter, can't fail use metadata::common::*; use metadata::cstore; @@ -350,7 +351,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: variant.node.id as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } ebml_w.start_tag(tag_items_data_item); @@ -668,10 +669,10 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic // Encode the base self type. match explicit_self { - SelfStatic => ebml_w.writer.write(&[ 's' as u8 ]), - SelfValue => ebml_w.writer.write(&[ 'v' as u8 ]), - SelfBox => ebml_w.writer.write(&[ '@' as u8 ]), - SelfUniq => ebml_w.writer.write(&[ '~' as u8 ]), + SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); } + SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); } + SelfBox => { ebml_w.writer.write(&[ '@' as u8 ]); } + SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); } SelfRegion(_, m) => { // FIXME(#4846) encode custom lifetime ebml_w.writer.write(&['&' as u8]); @@ -684,8 +685,8 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic fn encode_mutability(ebml_w: &writer::Encoder, m: ast::Mutability) { match m { - MutImmutable => ebml_w.writer.write(&[ 'i' as u8 ]), - MutMutable => ebml_w.writer.write(&[ 'm' as u8 ]), + MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); } + MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); } } } } @@ -726,12 +727,12 @@ fn encode_info_for_struct(ecx: &EncodeContext, }; let id = field.node.id; - index.push(entry {val: id as i64, pos: ebml_w.writer.tell()}); + index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()}); { let mut global_index = global_index.borrow_mut(); global_index.get().push(entry { val: id as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } ebml_w.start_tag(tag_items_data_item); @@ -758,7 +759,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: ctor_id as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } @@ -921,7 +922,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: item.id as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } let add_to_index: || = || add_to_index(item, ebml_w, index); @@ -1157,7 +1158,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: m.def_id.node as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } encode_info_for_method(ecx, @@ -1219,7 +1220,7 @@ fn encode_info_for_item(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: method_def_id.node as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } @@ -1294,7 +1295,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: nitem.id as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } @@ -1418,7 +1419,7 @@ fn encode_info_for_items(ecx: &EncodeContext, let mut index = index.borrow_mut(); index.get().push(entry { val: CRATE_NODE_ID as i64, - pos: ebml_w.writer.tell(), + pos: ebml_w.writer.tell().unwrap(), }); } encode_info_for_mod(ecx, @@ -1478,7 +1479,7 @@ fn encode_index( let mut bucket_locs = ~[]; ebml_w.start_tag(tag_index_buckets); for bucket in buckets.iter() { - bucket_locs.push(ebml_w.writer.tell()); + bucket_locs.push(ebml_w.writer.tell().unwrap()); ebml_w.start_tag(tag_index_buckets_bucket); for elt in (**bucket).iter() { ebml_w.start_tag(tag_index_buckets_bucket_elt); @@ -1895,58 +1896,58 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) encode_hash(&mut ebml_w, ecx.link_meta.crate_hash); - let mut i = ebml_w.writer.tell(); + let mut i = ebml_w.writer.tell().unwrap(); let crate_attrs = synthesize_crate_attrs(&ecx, crate); encode_attributes(&mut ebml_w, crate_attrs); - ecx.stats.attr_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.attr_bytes.set(ebml_w.writer.tell().unwrap() - i); - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore); - ecx.stats.dep_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.dep_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode the language items. - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_lang_items(&ecx, &mut ebml_w); - ecx.stats.lang_item_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.lang_item_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode the native libraries used - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_native_libraries(&ecx, &mut ebml_w); - ecx.stats.native_lib_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.native_lib_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode the macro registrar function - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_macro_registrar_fn(&ecx, &mut ebml_w); - ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode macro definitions - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_macro_defs(&ecx, crate, &mut ebml_w); - ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode the def IDs of impls, for coherence checking. - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_impls(&ecx, crate, &mut ebml_w); - ecx.stats.impl_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.impl_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode miscellaneous info. - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); encode_misc_info(&ecx, crate, &mut ebml_w); - ecx.stats.misc_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.misc_bytes.set(ebml_w.writer.tell().unwrap() - i); // Encode and index the items. ebml_w.start_tag(tag_items); - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate); - ecx.stats.item_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.item_bytes.set(ebml_w.writer.tell().unwrap() - i); - i = ebml_w.writer.tell(); + i = ebml_w.writer.tell().unwrap(); let items_buckets = create_index(items_index); encode_index(&mut ebml_w, items_buckets, write_i64); - ecx.stats.index_bytes.set(ebml_w.writer.tell() - i); + ecx.stats.index_bytes.set(ebml_w.writer.tell().unwrap() - i); ebml_w.end_tag(); - ecx.stats.total_bytes.set(ebml_w.writer.tell()); + ecx.stats.total_bytes.set(ebml_w.writer.tell().unwrap()); if tcx.sess.meta_stats() { for e in ebml_w.writer.get_ref().iter() { diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index fd8c620dc4e96..7e04a36ee2e08 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -11,7 +11,6 @@ use std::cell::RefCell; use std::option; use std::os; -use std::io; use std::io::fs; use std::hashmap::HashSet; @@ -93,7 +92,7 @@ impl FileSearch { pub fn search(&self, pick: pick) { self.for_each_lib_search_path(|lib_search_path| { debug!("searching {}", lib_search_path.display()); - match io::result(|| fs::readdir(lib_search_path)) { + match fs::readdir(lib_search_path) { Ok(files) => { let mut rslt = FileDoesntMatch; let is_rlib = |p: & &Path| { @@ -163,8 +162,8 @@ pub fn get_or_default_sysroot() -> Path { // Follow symlinks. If the resolved path is relative, make it absolute. fn canonicalize(path: Option) -> Option { path.and_then(|mut path| - match io::io_error::cond.trap(|_| ()).inside(|| fs::readlink(&path)) { - Some(canon) => { + match fs::readlink(&path) { + Ok(canon) => { if canon.is_absolute() { Some(canon) } else { @@ -172,7 +171,7 @@ pub fn get_or_default_sysroot() -> Path { Some(path.join(canon)) } }, - None => Some(path), + Err(..) => Some(path), }) } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 8e557560b95f1..abcd650ced131 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -381,13 +381,13 @@ pub fn read_meta_section_name(os: Os) -> &'static str { pub fn list_file_metadata(intr: @IdentInterner, os: Os, path: &Path, - out: &mut io::Writer) { + out: &mut io::Writer) -> io::IoResult<()> { match get_metadata_section(os, path) { option::Some(bytes) => decoder::list_crate_metadata(intr, bytes.as_slice(), out), option::None => { - write!(out, "could not find metadata in {}.\n", path.display()) + write!(out, "could not find metadata in {}.\n", path.display()) } } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index d17a45165432c..913c5dac46039 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -10,6 +10,8 @@ // Type encoding +#[allow(unused_must_use)]; // as with encoding, everything is a no-fail MemWriter + use std::cell::RefCell; use std::hashmap::HashMap; use std::io; @@ -92,9 +94,9 @@ pub fn enc_ty(w: &mut MemWriter, cx: @ctxt, t: ty::t) { None => {} } } - let pos = w.tell(); + let pos = w.tell().unwrap(); enc_sty(w, cx, &ty::get(t).sty); - let end = w.tell(); + let end = w.tell().unwrap(); let len = end - pos; fn estimate_sz(u: u64) -> u64 { let mut n = u; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index a957b8c7ef5f2..78221d2adb341 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -88,7 +88,7 @@ struct LoopScope<'a> { } impl pprust::PpAnn for DataFlowContext { - fn pre(&self, node: pprust::AnnNode) { + fn pre(&self, node: pprust::AnnNode) -> io::IoResult<()> { let (ps, id) = match node { pprust::NodeExpr(ps, expr) => (ps, expr.id), pprust::NodeBlock(ps, blk) => (ps, blk.id), @@ -117,9 +117,10 @@ impl pprust::PpAnn for DataFlowContext { let comment_str = format!("id {}: {}{}{}", id, entry_str, gens_str, kills_str); - pprust::synth_comment(ps, comment_str); - pp::space(&mut ps.s); + if_ok!(pprust::synth_comment(ps, comment_str)); + if_ok!(pp::space(&mut ps.s)); } + Ok(()) } } @@ -347,18 +348,20 @@ impl DataFlowContext { debug!("Dataflow result:"); debug!("{}", { let this = @(*self).clone(); - this.pretty_print_to(~io::stderr() as ~io::Writer, blk); + this.pretty_print_to(~io::stderr() as ~io::Writer, blk).unwrap(); "" }); } - fn pretty_print_to(@self, wr: ~io::Writer, blk: &ast::Block) { + fn pretty_print_to(@self, wr: ~io::Writer, + blk: &ast::Block) -> io::IoResult<()> { let mut ps = pprust::rust_printer_annotated(wr, self.tcx.sess.intr(), self as @pprust::PpAnn); - pprust::cbox(&mut ps, pprust::indent_unit); - pprust::ibox(&mut ps, 0u); - pprust::print_block(&mut ps, blk); - pp::eof(&mut ps.s); + if_ok!(pprust::cbox(&mut ps, pprust::indent_unit)); + if_ok!(pprust::ibox(&mut ps, 0u)); + if_ok!(pprust::print_block(&mut ps, blk)); + if_ok!(pp::eof(&mut ps.s)); + Ok(()) } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index fb5e548e12f6e..26e4a11ae49a2 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -736,14 +736,15 @@ impl Liveness { pub fn write_vars(&self, wr: &mut io::Writer, ln: LiveNode, - test: |uint| -> LiveNode) { + test: |uint| -> LiveNode) -> io::IoResult<()> { let node_base_idx = self.idx(ln, Variable(0)); for var_idx in range(0u, self.ir.num_vars.get()) { let idx = node_base_idx + var_idx; if test(idx).is_valid() { - write!(wr, " {}", Variable(var_idx).to_str()); + if_ok!(write!(wr, " {}", Variable(var_idx).to_str())); } } + Ok(()) } pub fn find_loop_scope(&self, @@ -781,6 +782,7 @@ impl Liveness { *loop_scope.get().last().unwrap() } + #[allow(unused_must_use)] pub fn ln_str(&self, ln: LiveNode) -> ~str { let mut wr = io::MemWriter::new(); { diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 1aaa446fc6cf3..82850dffa2b14 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -20,7 +20,7 @@ use std::fmt; pub struct Escape<'a>(&'a str); impl<'a> fmt::Show for Escape<'a> { - fn fmt(s: &Escape<'a>, fmt: &mut fmt::Formatter) { + fn fmt(s: &Escape<'a>, fmt: &mut fmt::Formatter) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 let Escape(s) = *s; @@ -29,7 +29,7 @@ impl<'a> fmt::Show for Escape<'a> { for (i, ch) in s.bytes().enumerate() { match ch as char { '<' | '>' | '&' | '\'' | '"' => { - fmt.buf.write(pile_o_bits.slice(last, i).as_bytes()); + if_ok!(fmt.buf.write(pile_o_bits.slice(last, i).as_bytes())); let s = match ch as char { '>' => ">", '<' => "<", @@ -38,7 +38,7 @@ impl<'a> fmt::Show for Escape<'a> { '"' => """, _ => unreachable!() }; - fmt.buf.write(s.as_bytes()); + if_ok!(fmt.buf.write(s.as_bytes())); last = i + 1; } _ => {} @@ -46,7 +46,8 @@ impl<'a> fmt::Show for Escape<'a> { } if last < s.len() { - fmt.buf.write(pile_o_bits.slice_from(last).as_bytes()); + if_ok!(fmt.buf.write(pile_o_bits.slice_from(last).as_bytes())); } + Ok(()) } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6b09072ff080e..92d15fbcd672d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -48,85 +48,104 @@ impl PuritySpace { } impl fmt::Show for clean::Generics { - fn fmt(g: &clean::Generics, f: &mut fmt::Formatter) { - if g.lifetimes.len() == 0 && g.type_params.len() == 0 { return } - f.buf.write("<".as_bytes()); + fn fmt(g: &clean::Generics, f: &mut fmt::Formatter) -> fmt::Result { + if g.lifetimes.len() == 0 && g.type_params.len() == 0 { return Ok(()) } + if_ok!(f.buf.write("<".as_bytes())); for (i, life) in g.lifetimes.iter().enumerate() { - if i > 0 { f.buf.write(", ".as_bytes()); } - write!(f.buf, "{}", *life); + if i > 0 { + if_ok!(f.buf.write(", ".as_bytes())); + } + if_ok!(write!(f.buf, "{}", *life)); } if g.type_params.len() > 0 { - if g.lifetimes.len() > 0 { f.buf.write(", ".as_bytes()); } + if g.lifetimes.len() > 0 { + if_ok!(f.buf.write(", ".as_bytes())); + } for (i, tp) in g.type_params.iter().enumerate() { - if i > 0 { f.buf.write(", ".as_bytes()) } - f.buf.write(tp.name.as_bytes()); + if i > 0 { + if_ok!(f.buf.write(", ".as_bytes())) + } + if_ok!(f.buf.write(tp.name.as_bytes())); if tp.bounds.len() > 0 { - f.buf.write(": ".as_bytes()); + if_ok!(f.buf.write(": ".as_bytes())); for (i, bound) in tp.bounds.iter().enumerate() { - if i > 0 { f.buf.write(" + ".as_bytes()); } - write!(f.buf, "{}", *bound); + if i > 0 { + if_ok!(f.buf.write(" + ".as_bytes())); + } + if_ok!(write!(f.buf, "{}", *bound)); } } } } - f.buf.write(">".as_bytes()); + if_ok!(f.buf.write(">".as_bytes())); + Ok(()) } } impl fmt::Show for clean::Lifetime { - fn fmt(l: &clean::Lifetime, f: &mut fmt::Formatter) { - f.buf.write("'".as_bytes()); - f.buf.write(l.get_ref().as_bytes()); + fn fmt(l: &clean::Lifetime, f: &mut fmt::Formatter) -> fmt::Result { + if_ok!(f.buf.write("'".as_bytes())); + if_ok!(f.buf.write(l.get_ref().as_bytes())); + Ok(()) } } impl fmt::Show for clean::TyParamBound { - fn fmt(bound: &clean::TyParamBound, f: &mut fmt::Formatter) { + fn fmt(bound: &clean::TyParamBound, f: &mut fmt::Formatter) -> fmt::Result { match *bound { clean::RegionBound => { f.buf.write("'static".as_bytes()) } clean::TraitBound(ref ty) => { - write!(f.buf, "{}", *ty); + write!(f.buf, "{}", *ty) } } } } impl fmt::Show for clean::Path { - fn fmt(path: &clean::Path, f: &mut fmt::Formatter) { - if path.global { f.buf.write("::".as_bytes()) } + fn fmt(path: &clean::Path, f: &mut fmt::Formatter) -> fmt::Result { + if path.global { + if_ok!(f.buf.write("::".as_bytes())) + } for (i, seg) in path.segments.iter().enumerate() { - if i > 0 { f.buf.write("::".as_bytes()) } - f.buf.write(seg.name.as_bytes()); + if i > 0 { + if_ok!(f.buf.write("::".as_bytes())) + } + if_ok!(f.buf.write(seg.name.as_bytes())); if seg.lifetimes.len() > 0 || seg.types.len() > 0 { - f.buf.write("<".as_bytes()); + if_ok!(f.buf.write("<".as_bytes())); let mut comma = false; for lifetime in seg.lifetimes.iter() { - if comma { f.buf.write(", ".as_bytes()); } + if comma { + if_ok!(f.buf.write(", ".as_bytes())); + } comma = true; - write!(f.buf, "{}", *lifetime); + if_ok!(write!(f.buf, "{}", *lifetime)); } for ty in seg.types.iter() { - if comma { f.buf.write(", ".as_bytes()); } + if comma { + if_ok!(f.buf.write(", ".as_bytes())); + } comma = true; - write!(f.buf, "{}", *ty); + if_ok!(write!(f.buf, "{}", *ty)); } - f.buf.write(">".as_bytes()); + if_ok!(f.buf.write(">".as_bytes())); } } + Ok(()) } } /// Used when rendering a `ResolvedPath` structure. This invokes the `path` /// rendering function with the necessary arguments for linking to a local path. fn resolved_path(w: &mut io::Writer, id: ast::NodeId, p: &clean::Path, - print_all: bool) { + print_all: bool) -> fmt::Result { path(w, p, print_all, |_cache, loc| { Some("../".repeat(loc.len())) }, |cache| { @@ -134,13 +153,14 @@ fn resolved_path(w: &mut io::Writer, id: ast::NodeId, p: &clean::Path, None => None, Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty)) } - }); + }) } /// Used when rendering an `ExternalPath` structure. Like `resolved_path` this /// will invoke `path` with proper linking-style arguments. fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool, - fqn: &[~str], kind: clean::TypeKind, crate: ast::CrateNum) { + fqn: &[~str], kind: clean::TypeKind, + crate: ast::CrateNum) -> fmt::Result { path(w, p, print_all, |cache, loc| { match *cache.extern_locations.get(&crate) { @@ -161,7 +181,9 @@ fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool, fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool, root: |&render::Cache, &[~str]| -> Option<~str>, - info: |&render::Cache| -> Option<(~[~str], &'static str)>) { + info: |&render::Cache| -> Option<(~[~str], &'static str)>) + -> fmt::Result +{ // The generics will get written to both the title and link let mut generics = ~""; let last = path.segments.last().unwrap(); @@ -200,20 +222,20 @@ fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool, let mut root = root; for seg in path.segments.slice_to(amt).iter() { if "super" == seg.name || "self" == seg.name { - write!(w, "{}::", seg.name); + if_ok!(write!(w, "{}::", seg.name)); } else { root.push_str(seg.name); root.push_str("/"); - write!(w, "{}::", - root, - seg.name); + if_ok!(write!(w, "{}::", + root, + seg.name)); } } } None => { for seg in path.segments.slice_to(amt).iter() { - write!(w, "{}::", seg.name); + if_ok!(write!(w, "{}::", seg.name)); } } } @@ -241,51 +263,57 @@ fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool, } } - write!(w, "{}", - shortty, url, fqp.connect("::"), last.name); + if_ok!(write!(w, "{}", + shortty, url, fqp.connect("::"), last.name)); } _ => { - write!(w, "{}", last.name); + if_ok!(write!(w, "{}", last.name)); } } - write!(w, "{}", generics); + if_ok!(write!(w, "{}", generics)); + Ok(()) }) }) } /// Helper to render type parameters -fn typarams(w: &mut io::Writer, typarams: &Option<~[clean::TyParamBound]>) { +fn typarams(w: &mut io::Writer, + typarams: &Option<~[clean::TyParamBound]>) -> fmt::Result { match *typarams { Some(ref params) => { - write!(w, "<"); + if_ok!(write!(w, "<")); for (i, param) in params.iter().enumerate() { - if i > 0 { write!(w, ", "); } - write!(w, "{}", *param); + if i > 0 { + if_ok!(write!(w, ", ")); + } + if_ok!(write!(w, "{}", *param)); } - write!(w, ">"); + if_ok!(write!(w, ">")); + Ok(()) } - None => {} + None => Ok(()) } } impl fmt::Show for clean::Type { - fn fmt(g: &clean::Type, f: &mut fmt::Formatter) { + fn fmt(g: &clean::Type, f: &mut fmt::Formatter) -> fmt::Result { match *g { clean::TyParamBinder(id) | clean::Generic(id) => { local_data::get(cache_key, |cache| { let m = cache.unwrap().get(); - f.buf.write(m.typarams.get(&id).as_bytes()); + f.buf.write(m.typarams.get(&id).as_bytes()) }) } clean::ResolvedPath{id, typarams: ref tp, path: ref path} => { - resolved_path(f.buf, id, path, false); - typarams(f.buf, tp); + if_ok!(resolved_path(f.buf, id, path, false)); + typarams(f.buf, tp) } clean::ExternalPath{path: ref path, typarams: ref tp, fqn: ref fqn, kind, crate} => { - external_path(f.buf, path, false, fqn.as_slice(), kind, crate); - typarams(f.buf, tp); + if_ok!(external_path(f.buf, path, false, fqn.as_slice(), kind, + crate)) + typarams(f.buf, tp) } clean::Self(..) => f.buf.write("Self".as_bytes()), clean::Primitive(prim) => { @@ -306,7 +334,7 @@ impl fmt::Show for clean::Type { ast::TyBool => "bool", ast::TyChar => "char", }; - f.buf.write(s.as_bytes()); + f.buf.write(s.as_bytes()) } clean::Closure(ref decl) => { let region = match decl.region { @@ -322,7 +350,7 @@ impl fmt::Show for clean::Type { ast::ManagedSigil => format!("@{}fn({})", region, decl.decl.inputs), }, arrow = match decl.decl.output { clean::Unit => "no", _ => "yes" }, - ret = decl.decl.output); + ret = decl.decl.output) // FIXME: where are bounds and lifetimes printed?! } clean::BareFunction(ref decl) => { @@ -333,19 +361,21 @@ impl fmt::Show for clean::Type { ref s => " " + *s + " ", }, decl.generics, - decl.decl); + decl.decl) } clean::Tuple(ref typs) => { - f.buf.write("(".as_bytes()); + if_ok!(f.buf.write("(".as_bytes())); for (i, typ) in typs.iter().enumerate() { - if i > 0 { f.buf.write(", ".as_bytes()) } - write!(f.buf, "{}", *typ); + if i > 0 { + if_ok!(f.buf.write(", ".as_bytes())) + } + if_ok!(write!(f.buf, "{}", *typ)); } - f.buf.write(")".as_bytes()); + f.buf.write(")".as_bytes()) } clean::Vector(ref t) => write!(f.buf, "[{}]", **t), clean::FixedVector(ref t, ref s) => { - write!(f.buf, "[{}, ..{}]", **t, *s); + write!(f.buf, "[{}, ..{}]", **t, *s) } clean::String => f.buf.write("str".as_bytes()), clean::Bool => f.buf.write("bool".as_bytes()), @@ -368,23 +398,23 @@ impl fmt::Show for clean::Type { clean::Mutable => "mut ", clean::Immutable => "", }, - **ty); + **ty) } } } } impl fmt::Show for clean::FnDecl { - fn fmt(d: &clean::FnDecl, f: &mut fmt::Formatter) { + fn fmt(d: &clean::FnDecl, f: &mut fmt::Formatter) -> fmt::Result { write!(f.buf, "({args}){arrow, select, yes{ -> {ret}} other{}}", args = d.inputs, arrow = match d.output { clean::Unit => "no", _ => "yes" }, - ret = d.output); + ret = d.output) } } impl fmt::Show for ~[clean::Argument] { - fn fmt(inputs: &~[clean::Argument], f: &mut fmt::Formatter) { + fn fmt(inputs: &~[clean::Argument], f: &mut fmt::Formatter) -> fmt::Result { let mut args = ~""; for (i, input) in inputs.iter().enumerate() { if i > 0 { args.push_str(", "); } @@ -393,12 +423,12 @@ impl fmt::Show for ~[clean::Argument] { } args.push_str(format!("{}", input.type_)); } - f.buf.write(args.as_bytes()); + f.buf.write(args.as_bytes()) } } impl<'a> fmt::Show for Method<'a> { - fn fmt(m: &Method<'a>, f: &mut fmt::Formatter) { + fn fmt(m: &Method<'a>, f: &mut fmt::Formatter) -> fmt::Result { let Method(selfty, d) = *m; let mut args = ~""; match *selfty { @@ -429,74 +459,79 @@ impl<'a> fmt::Show for Method<'a> { write!(f.buf, "({args}){arrow, select, yes{ -> {ret}} other{}}", args = args, arrow = match d.output { clean::Unit => "no", _ => "yes" }, - ret = d.output); + ret = d.output) } } impl fmt::Show for VisSpace { - fn fmt(v: &VisSpace, f: &mut fmt::Formatter) { + fn fmt(v: &VisSpace, f: &mut fmt::Formatter) -> fmt::Result { match v.get() { - Some(ast::Public) => { write!(f.buf, "pub "); } - Some(ast::Private) => { write!(f.buf, "priv "); } - Some(ast::Inherited) | None => {} + Some(ast::Public) => write!(f.buf, "pub "), + Some(ast::Private) => write!(f.buf, "priv "), + Some(ast::Inherited) | None => Ok(()) } } } impl fmt::Show for PuritySpace { - fn fmt(p: &PuritySpace, f: &mut fmt::Formatter) { + fn fmt(p: &PuritySpace, f: &mut fmt::Formatter) -> fmt::Result { match p.get() { ast::UnsafeFn => write!(f.buf, "unsafe "), ast::ExternFn => write!(f.buf, "extern "), - ast::ImpureFn => {} + ast::ImpureFn => Ok(()) } } } impl fmt::Show for clean::ViewPath { - fn fmt(v: &clean::ViewPath, f: &mut fmt::Formatter) { + fn fmt(v: &clean::ViewPath, f: &mut fmt::Formatter) -> fmt::Result { match *v { clean::SimpleImport(ref name, ref src) => { if *name == src.path.segments.last().unwrap().name { - write!(f.buf, "use {};", *src); + write!(f.buf, "use {};", *src) } else { - write!(f.buf, "use {} = {};", *name, *src); + write!(f.buf, "use {} = {};", *name, *src) } } clean::GlobImport(ref src) => { - write!(f.buf, "use {}::*;", *src); + write!(f.buf, "use {}::*;", *src) } clean::ImportList(ref src, ref names) => { - write!(f.buf, "use {}::\\{", *src); + if_ok!(write!(f.buf, "use {}::\\{", *src)); for (i, n) in names.iter().enumerate() { - if i > 0 { write!(f.buf, ", "); } - write!(f.buf, "{}", *n); + if i > 0 { + if_ok!(write!(f.buf, ", ")); + } + if_ok!(write!(f.buf, "{}", *n)); } - write!(f.buf, "\\};"); + write!(f.buf, "\\};") } } } } impl fmt::Show for clean::ImportSource { - fn fmt(v: &clean::ImportSource, f: &mut fmt::Formatter) { + fn fmt(v: &clean::ImportSource, f: &mut fmt::Formatter) -> fmt::Result { match v.did { // FIXME: shouldn't be restricted to just local imports Some(did) if ast_util::is_local(did) => { - resolved_path(f.buf, did.node, &v.path, true); + resolved_path(f.buf, did.node, &v.path, true) } _ => { for (i, seg) in v.path.segments.iter().enumerate() { - if i > 0 { write!(f.buf, "::") } - write!(f.buf, "{}", seg.name); + if i > 0 { + if_ok!(write!(f.buf, "::")) + } + if_ok!(write!(f.buf, "{}", seg.name)); } + Ok(()) } } } } impl fmt::Show for clean::ViewListIdent { - fn fmt(v: &clean::ViewListIdent, f: &mut fmt::Formatter) { + fn fmt(v: &clean::ViewListIdent, f: &mut fmt::Formatter) -> fmt::Result { match v.source { // FIXME: shouldn't be limited to just local imports Some(did) if ast_util::is_local(did) => { @@ -508,7 +543,7 @@ impl fmt::Show for clean::ViewListIdent { types: ~[], }] }; - resolved_path(f.buf, did.node, &path, false); + resolved_path(f.buf, did.node, &path, false) } _ => write!(f.buf, "{}", v.name), } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 4565facea0211..db7c882ab4203 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -26,6 +26,7 @@ pub struct Page<'a> { pub fn render( dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T) + -> fmt::Result { write!(dst, " @@ -121,7 +122,7 @@ pub fn render( favicon = nonestr(layout.favicon), sidebar = *sidebar, crate = layout.crate, - ); + ) } fn nonestr<'a>(s: &'a str) -> &'a str { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 254d65ae2f604..c2203a352c53f 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -109,7 +109,7 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> { } } -pub fn render(w: &mut io::Writer, s: &str) { +pub fn render(w: &mut io::Writer, s: &str) -> fmt::Result { extern fn block(ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) { unsafe { let my_opaque: &my_opaque = cast::transmute(opaque); @@ -159,11 +159,12 @@ pub fn render(w: &mut io::Writer, s: &str) { sd_markdown_render(ob, s.as_ptr(), s.len() as libc::size_t, markdown); sd_markdown_free(markdown); - vec::raw::buf_as_slice((*ob).data, (*ob).size as uint, |buf| { - w.write(buf); + let ret = vec::raw::buf_as_slice((*ob).data, (*ob).size as uint, |buf| { + w.write(buf) }); bufrelease(ob); + ret } } @@ -210,10 +211,10 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { } impl<'a> fmt::Show for Markdown<'a> { - fn fmt(md: &Markdown<'a>, fmt: &mut fmt::Formatter) { + fn fmt(md: &Markdown<'a>, fmt: &mut fmt::Formatter) -> fmt::Result { let Markdown(md) = *md; // This is actually common enough to special-case - if md.len() == 0 { return; } - render(fmt.buf, md.as_slice()); + if md.len() == 0 { return Ok(()) } + render(fmt.buf, md.as_slice()) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0b2c568c723ae..65696528a6fa1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -195,7 +195,7 @@ local_data_key!(pub cache_key: Arc) local_data_key!(pub current_location_key: ~[~str]) /// Generates the documentation for `crate` into the directory `dst` -pub fn run(mut crate: clean::Crate, dst: Path) { +pub fn run(mut crate: clean::Crate, dst: Path) -> io::IoResult<()> { let mut cx = Context { dst: dst, current: ~[], @@ -208,7 +208,7 @@ pub fn run(mut crate: clean::Crate, dst: Path) { }, include_sources: true, }; - mkdir(&cx.dst); + if_ok!(mkdir(&cx.dst)); match crate.module.as_ref().map(|m| m.doc_list().unwrap_or(&[])) { Some(attrs) => { @@ -248,47 +248,55 @@ pub fn run(mut crate: clean::Crate, dst: Path) { // Add all the static files let mut dst = cx.dst.join(crate.name.as_slice()); - mkdir(&dst); - write(dst.join("jquery.js"), include_str!("static/jquery-2.0.3.min.js")); - write(dst.join("main.js"), include_str!("static/main.js")); - write(dst.join("main.css"), include_str!("static/main.css")); - write(dst.join("normalize.css"), include_str!("static/normalize.css")); + if_ok!(mkdir(&dst)); + if_ok!(write(dst.join("jquery.js"), + include_str!("static/jquery-2.0.3.min.js"))); + if_ok!(write(dst.join("main.js"), include_str!("static/main.js"))); + if_ok!(write(dst.join("main.css"), include_str!("static/main.css"))); + if_ok!(write(dst.join("normalize.css"), + include_str!("static/normalize.css"))); // Publish the search index { dst.push("search-index.js"); let mut w = BufferedWriter::new(File::create(&dst).unwrap()); let w = &mut w as &mut Writer; - write!(w, "var searchIndex = ["); + if_ok!(write!(w, "var searchIndex = [")); for (i, item) in cache.search_index.iter().enumerate() { - if i > 0 { write!(w, ","); } - write!(w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}", - item.ty, item.name, item.path, - item.desc.to_json().to_str()) + if i > 0 { + if_ok!(write!(w, ",")); + } + if_ok!(write!(w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}", + item.ty, item.name, item.path, + item.desc.to_json().to_str())); match item.parent { - Some(id) => { write!(w, ",parent:'{}'", id); } + Some(id) => { + if_ok!(write!(w, ",parent:'{}'", id)); + } None => {} } - write!(w, "\\}"); + if_ok!(write!(w, "\\}")); } - write!(w, "];"); - write!(w, "var allPaths = \\{"); + if_ok!(write!(w, "];")); + if_ok!(write!(w, "var allPaths = \\{")); for (i, (&id, &(ref fqp, short))) in cache.paths.iter().enumerate() { - if i > 0 { write!(w, ","); } - write!(w, "'{}':\\{type:'{}',name:'{}'\\}", - id, short, *fqp.last().unwrap()); + if i > 0 { + if_ok!(write!(w, ",")); + } + if_ok!(write!(w, "'{}':\\{type:'{}',name:'{}'\\}", + id, short, *fqp.last().unwrap())); } - write!(w, "\\};"); - w.flush(); + if_ok!(write!(w, "\\};")); + if_ok!(w.flush()); } // Render all source files (this may turn into a giant no-op) { info!("emitting source files"); let dst = cx.dst.join("src"); - mkdir(&dst); + if_ok!(mkdir(&dst)); let dst = dst.join(crate.name.as_slice()); - mkdir(&dst); + if_ok!(mkdir(&dst)); let mut folder = SourceCollector { dst: dst, seen: HashSet::new(), @@ -302,27 +310,23 @@ pub fn run(mut crate: clean::Crate, dst: Path) { } // And finally render the whole crate's documentation - cx.crate(crate, cache); + cx.crate(crate, cache) } /// Writes the entire contents of a string to a destination, not attempting to /// catch any errors. -fn write(dst: Path, contents: &str) { - File::create(&dst).write(contents.as_bytes()); +fn write(dst: Path, contents: &str) -> io::IoResult<()> { + File::create(&dst).write(contents.as_bytes()) } /// Makes a directory on the filesystem, failing the task if an error occurs and /// skipping if the directory already exists. -fn mkdir(path: &Path) { - io::io_error::cond.trap(|err| { - error!("Couldn't create directory `{}`: {}", - path.display(), err.desc); - fail!() - }).inside(|| { - if !path.is_dir() { - fs::mkdir(path, io::UserRWX); - } - }) +fn mkdir(path: &Path) -> io::IoResult<()> { + if !path.exists() { + fs::mkdir(path, io::UserRWX) + } else { + Ok(()) + } } /// Takes a path to a source file and cleans the path to it. This canonicalizes @@ -387,15 +391,17 @@ impl<'a> DocFolder for SourceCollector<'a> { // something like that), so just don't include sources for the // entire crate. The other option is maintaining this mapping on a // per-file basis, but that's probably not worth it... - self.cx.include_sources = self.emit_source(item.source.filename); + self.cx.include_sources = match self.emit_source(item.source.filename) { + Ok(()) => true, + Err(e) => { + println!("warning: source code was requested to be rendered, \ + but processing `{}` had an error: {}", + item.source.filename, e); + println!(" skipping rendering of source code"); + false + } + }; self.seen.insert(item.source.filename.clone()); - - if !self.cx.include_sources { - println!("warning: source code was requested to be rendered, \ - but `{}` is a missing source file.", - item.source.filename); - println!(" skipping rendering of source code"); - } } self.fold_item_recur(item) @@ -404,30 +410,18 @@ impl<'a> DocFolder for SourceCollector<'a> { impl<'a> SourceCollector<'a> { /// Renders the given filename into its corresponding HTML source file. - fn emit_source(&mut self, filename: &str) -> bool { + fn emit_source(&mut self, filename: &str) -> io::IoResult<()> { let p = Path::new(filename); - // Read the contents of the file - let mut contents = ~[]; - { - let mut buf = [0, ..1024]; - // If we couldn't open this file, then just returns because it - // probably means that it's some standard library macro thing and we - // can't have the source to it anyway. - let mut r = match io::result(|| File::open(&p)) { - Ok(r) => r, - // eew macro hacks - Err(..) => return filename == "" - }; - - // read everything - loop { - match r.read(buf) { - Some(n) => contents.push_all(buf.slice_to(n)), - None => break - } - } - } + // If we couldn't open this file, then just returns because it + // probably means that it's some standard library macro thing and we + // can't have the source to it anyway. + let contents = match File::open(&p).read_to_end() { + Ok(r) => r, + // eew macro hacks + Err(..) if filename == "" => return Ok(()), + Err(e) => return Err(e) + }; let contents = str::from_utf8_owned(contents).unwrap(); // Create the intermediate directories @@ -435,12 +429,12 @@ impl<'a> SourceCollector<'a> { let mut root_path = ~"../../"; clean_srcpath(p.dirname(), |component| { cur.push(component); - mkdir(&cur); + mkdir(&cur).unwrap(); root_path.push_str("../"); }); cur.push(p.filename().expect("source has no filename") + bytes!(".html")); - let mut w = BufferedWriter::new(File::create(&cur).unwrap()); + let mut w = BufferedWriter::new(if_ok!(File::create(&cur))); let title = cur.filename_display().with_str(|s| format!("{} -- source", s)); let page = layout::Page { @@ -448,10 +442,10 @@ impl<'a> SourceCollector<'a> { ty: "source", root_path: root_path, }; - layout::render(&mut w as &mut Writer, &self.cx.layout, - &page, &(""), &Source(contents.as_slice())); - w.flush(); - return true; + if_ok!(layout::render(&mut w as &mut Writer, &self.cx.layout, + &page, &(""), &Source(contents.as_slice()))); + if_ok!(w.flush()); + return Ok(()); } } @@ -665,7 +659,7 @@ impl Context { info!("Recursing into {}", self.dst.display()); - mkdir(&self.dst); + mkdir(&self.dst).unwrap(); let ret = f(self); info!("Recursed; leaving {}", self.dst.display()); @@ -683,10 +677,10 @@ impl Context { /// /// This currently isn't parallelized, but it'd be pretty easy to add /// parallelization to this function. - fn crate(self, mut crate: clean::Crate, cache: Cache) { + fn crate(self, mut crate: clean::Crate, cache: Cache) -> io::IoResult<()> { let mut item = match crate.module.take() { Some(i) => i, - None => return + None => return Ok(()) }; item.name = Some(crate.name); @@ -696,12 +690,13 @@ impl Context { let mut work = ~[(self, item)]; loop { match work.pop() { - Some((mut cx, item)) => cx.item(item, |cx, item| { + Some((mut cx, item)) => if_ok!(cx.item(item, |cx, item| { work.push((cx.clone(), item)); - }), + })), None => break, } } + Ok(()) } /// Non-parellelized version of rendering an item. This will take the input @@ -709,9 +704,10 @@ impl Context { /// all sub-items which need to be rendered. /// /// The rendering driver uses this closure to queue up more work. - fn item(&mut self, item: clean::Item, f: |&mut Context, clean::Item|) { + fn item(&mut self, item: clean::Item, + f: |&mut Context, clean::Item|) -> io::IoResult<()> { fn render(w: io::File, cx: &mut Context, it: &clean::Item, - pushname: bool) { + pushname: bool) -> io::IoResult<()> { info!("Rendering an item to {}", w.path().display()); // A little unfortunate that this is done like this, but it sure // does make formatting *a lot* nicer. @@ -733,10 +729,10 @@ impl Context { // of the pain by using a buffered writer instead of invoking the // write sycall all the time. let mut writer = BufferedWriter::new(w); - layout::render(&mut writer as &mut Writer, &cx.layout, &page, - &Sidebar{ cx: cx, item: it }, - &Item{ cx: cx, item: it }); - writer.flush(); + if_ok!(layout::render(&mut writer as &mut Writer, &cx.layout, &page, + &Sidebar{ cx: cx, item: it }, + &Item{ cx: cx, item: it })); + writer.flush() } match item.inner { @@ -748,7 +744,8 @@ impl Context { self.recurse(name, |this| { let item = item.take_unwrap(); let dst = this.dst.join("index.html"); - render(File::create(&dst).unwrap(), this, &item, false); + let dst = if_ok!(File::create(&dst)); + if_ok!(render(dst, this, &item, false)); let m = match item.inner { clean::ModuleItem(m) => m, @@ -758,6 +755,7 @@ impl Context { for item in m.items.move_iter() { f(this,item); } + Ok(()) }) } @@ -765,10 +763,11 @@ impl Context { // pages dedicated to them. _ if item.name.is_some() => { let dst = self.dst.join(item_path(&item)); - render(File::create(&dst).unwrap(), self, &item, true); + let dst = if_ok!(File::create(&dst)); + render(dst, self, &item, true) } - _ => {} + _ => Ok(()) } } } @@ -802,16 +801,16 @@ impl<'a> Item<'a> { } impl<'a> fmt::Show for Item<'a> { - fn fmt(it: &Item<'a>, fmt: &mut fmt::Formatter) { + fn fmt(it: &Item<'a>, fmt: &mut fmt::Formatter) -> fmt::Result { match attr::find_stability(it.item.attrs.iter()) { Some(ref stability) => { - write!(fmt.buf, + if_ok!(write!(fmt.buf, "{lvl}", lvl = stability.level.to_str(), reason = match stability.text { Some(ref s) => (*s).clone(), None => InternedString::new(""), - }); + })); } None => {} } @@ -826,23 +825,24 @@ impl<'a> fmt::Show for Item<'a> { } else { format!("{}-{}", it.item.source.loline, it.item.source.hiline) }; - write!(fmt.buf, - "[src]", - root = it.cx.root_path, - crate = it.cx.layout.crate, - path = path.connect("/"), - href = href); + if_ok!(write!(fmt.buf, + "\ + [src]", + root = it.cx.root_path, + crate = it.cx.layout.crate, + path = path.connect("/"), + href = href)); } // Write the breadcrumb trail header for the top - write!(fmt.buf, "

"); + if_ok!(write!(fmt.buf, "

")); match it.item.inner { - clean::ModuleItem(..) => write!(fmt.buf, "Module "), - clean::FunctionItem(..) => write!(fmt.buf, "Function "), - clean::TraitItem(..) => write!(fmt.buf, "Trait "), - clean::StructItem(..) => write!(fmt.buf, "Struct "), - clean::EnumItem(..) => write!(fmt.buf, "Enum "), + clean::ModuleItem(..) => if_ok!(write!(fmt.buf, "Module ")), + clean::FunctionItem(..) => if_ok!(write!(fmt.buf, "Function ")), + clean::TraitItem(..) => if_ok!(write!(fmt.buf, "Trait ")), + clean::StructItem(..) => if_ok!(write!(fmt.buf, "Struct ")), + clean::EnumItem(..) => if_ok!(write!(fmt.buf, "Enum ")), _ => {} } let cur = it.cx.current.as_slice(); @@ -852,11 +852,11 @@ impl<'a> fmt::Show for Item<'a> { for _ in range(0, cur.len() - i - 1) { trail.push_str("../"); } - write!(fmt.buf, "{}::", - trail, component.as_slice()); + if_ok!(write!(fmt.buf, "{}::", + trail, component.as_slice())); } - write!(fmt.buf, "{}

", - shortty(it.item), it.item.name.get_ref().as_slice()); + if_ok!(write!(fmt.buf, "{}", + shortty(it.item), it.item.name.get_ref().as_slice())); match it.item.inner { clean::ModuleItem(ref m) => item_module(fmt.buf, it.cx, @@ -867,7 +867,7 @@ impl<'a> fmt::Show for Item<'a> { clean::StructItem(ref s) => item_struct(fmt.buf, it.item, s), clean::EnumItem(ref e) => item_enum(fmt.buf, it.item, e), clean::TypedefItem(ref t) => item_typedef(fmt.buf, it.item, t), - _ => {} + _ => Ok(()) } } } @@ -903,18 +903,19 @@ fn shorter<'a>(s: Option<&'a str>) -> &'a str { } } -fn document(w: &mut Writer, item: &clean::Item) { +fn document(w: &mut Writer, item: &clean::Item) -> fmt::Result { match item.doc_value() { Some(s) => { - write!(w, "
{}
", Markdown(s)); + if_ok!(write!(w, "
{}
", Markdown(s))); } None => {} } + Ok(()) } fn item_module(w: &mut Writer, cx: &Context, - item: &clean::Item, items: &[clean::Item]) { - document(w, item); + item: &clean::Item, items: &[clean::Item]) -> fmt::Result { + if_ok!(document(w, item)); debug!("{:?}", items); let mut indices = vec::from_fn(items.len(), |i| i); @@ -965,10 +966,10 @@ fn item_module(w: &mut Writer, cx: &Context, let myty = shortty(myitem); if myty != curty { if curty != "" { - write!(w, ""); + if_ok!(write!(w, "")); } curty = myty; - write!(w, "

{}

\n", match myitem.inner { + if_ok!(write!(w, "

{}

\n
", match myitem.inner { clean::ModuleItem(..) => "Modules", clean::StructItem(..) => "Structs", clean::EnumItem(..) => "Enums", @@ -984,24 +985,26 @@ fn item_module(w: &mut Writer, cx: &Context, clean::VariantItem(..) => "Variants", clean::ForeignFunctionItem(..) => "Foreign Functions", clean::ForeignStaticItem(..) => "Foreign Statics", - }); + })); } match myitem.inner { clean::StaticItem(ref s) | clean::ForeignStaticItem(ref s) => { struct Initializer<'a>(&'a str); impl<'a> fmt::Show for Initializer<'a> { - fn fmt(s: &Initializer<'a>, f: &mut fmt::Formatter) { + fn fmt(s: &Initializer<'a>, + f: &mut fmt::Formatter) -> fmt::Result { let Initializer(s) = *s; - if s.len() == 0 { return; } - write!(f.buf, " = "); + if s.len() == 0 { return Ok(()); } + if_ok!(write!(f.buf, " = ")); let tag = if s.contains("\n") { "pre" } else { "code" }; - write!(f.buf, "<{tag}>{}", - s.as_slice(), tag=tag); + if_ok!(write!(f.buf, "<{tag}>{}", + s.as_slice(), tag=tag)); + Ok(()) } } - write!(w, " + if_ok!(write!(w, " @@ -1011,27 +1014,27 @@ fn item_module(w: &mut Writer, cx: &Context, *myitem.name.get_ref(), s.type_, Initializer(s.expr), - Markdown(blank(myitem.doc_value()))); + Markdown(blank(myitem.doc_value())))); } clean::ViewItemItem(ref item) => { match item.inner { clean::ExternMod(ref name, ref src, _) => { - write!(w, ""); + if_ok!(write!(w, ";")); } clean::Import(ref imports) => { for import in imports.iter() { - write!(w, "", - VisSpace(myitem.visibility), - *import); + if_ok!(write!(w, "", + VisSpace(myitem.visibility), + *import)); } } } @@ -1040,7 +1043,7 @@ fn item_module(w: &mut Writer, cx: &Context, _ => { if myitem.name.is_none() { continue } - write!(w, " + if_ok!(write!(w, " @@ -1051,24 +1054,26 @@ fn item_module(w: &mut Writer, cx: &Context, Markdown(shorter(myitem.doc_value())), class = shortty(myitem), href = item_path(myitem), - title = full_path(cx, myitem)); + title = full_path(cx, myitem))); } } } - write!(w, "
{}static {}: {}{} {} 
extern mod {}", - name.as_slice()); + if_ok!(write!(w, "
extern mod {}", + name.as_slice())); match *src { - Some(ref src) => write!(w, " = \"{}\"", - src.as_slice()), + Some(ref src) => if_ok!(write!(w, " = \"{}\"", + src.as_slice())), None => {} } - write!(w, ";
{}{}
{}{}
{}
"); + write!(w, "") } -fn item_function(w: &mut Writer, it: &clean::Item, f: &clean::Function) { - write!(w, "
{vis}{purity}fn {name}{generics}{decl}
", +fn item_function(w: &mut Writer, it: &clean::Item, + f: &clean::Function) -> fmt::Result { + if_ok!(write!(w, "
{vis}{purity}fn {name}{generics}{decl}
", vis = VisSpace(it.visibility), purity = PuritySpace(f.purity), name = it.name.get_ref().as_slice(), generics = f.generics, - decl = f.decl); - document(w, it); + decl = f.decl)); + document(w, it) } -fn item_trait(w: &mut Writer, it: &clean::Item, t: &clean::Trait) { +fn item_trait(w: &mut Writer, it: &clean::Item, + t: &clean::Trait) -> fmt::Result { let mut parents = ~""; if t.parents.len() > 0 { parents.push_str(": "); @@ -1079,99 +1084,102 @@ fn item_trait(w: &mut Writer, it: &clean::Item, t: &clean::Trait) { } // Output the trait definition - write!(w, "
{}trait {}{}{} ",
-           VisSpace(it.visibility),
-           it.name.get_ref().as_slice(),
-           t.generics,
-           parents);
+    if_ok!(write!(w, "
{}trait {}{}{} ",
+                  VisSpace(it.visibility),
+                  it.name.get_ref().as_slice(),
+                  t.generics,
+                  parents));
     let required = t.methods.iter().filter(|m| m.is_req()).to_owned_vec();
     let provided = t.methods.iter().filter(|m| !m.is_req()).to_owned_vec();
 
     if t.methods.len() == 0 {
-        write!(w, "\\{ \\}");
+        if_ok!(write!(w, "\\{ \\}"));
     } else {
-        write!(w, "\\{\n");
+        if_ok!(write!(w, "\\{\n"));
         for m in required.iter() {
-            write!(w, "    ");
-            render_method(w, m.item(), true);
-            write!(w, ";\n");
+            if_ok!(write!(w, "    "));
+            if_ok!(render_method(w, m.item(), true));
+            if_ok!(write!(w, ";\n"));
         }
         if required.len() > 0 && provided.len() > 0 {
-            w.write("\n".as_bytes());
+            if_ok!(w.write("\n".as_bytes()));
         }
         for m in provided.iter() {
-            write!(w, "    ");
-            render_method(w, m.item(), true);
-            write!(w, " \\{ ... \\}\n");
+            if_ok!(write!(w, "    "));
+            if_ok!(render_method(w, m.item(), true));
+            if_ok!(write!(w, " \\{ ... \\}\n"));
         }
-        write!(w, "\\}");
+        if_ok!(write!(w, "\\}"));
     }
-    write!(w, "
"); + if_ok!(write!(w, "
")); // Trait documentation - document(w, it); - - fn meth(w: &mut Writer, m: &clean::TraitMethod) { - write!(w, "

", - shortty(m.item()), - *m.item().name.get_ref()); - render_method(w, m.item(), false); - write!(w, "

"); - document(w, m.item()); + if_ok!(document(w, it)); + + fn meth(w: &mut Writer, m: &clean::TraitMethod) -> fmt::Result { + if_ok!(write!(w, "

", + shortty(m.item()), + *m.item().name.get_ref())); + if_ok!(render_method(w, m.item(), false)); + if_ok!(write!(w, "

")); + if_ok!(document(w, m.item())); + Ok(()) } // Output the documentation for each function individually if required.len() > 0 { - write!(w, " + if_ok!(write!(w, "

Required Methods

- "); + ")); for m in required.iter() { - meth(w, *m); + if_ok!(meth(w, *m)); } - write!(w, "
"); + if_ok!(write!(w, "")); } if provided.len() > 0 { - write!(w, " + if_ok!(write!(w, "

Provided Methods

- "); + ")); for m in provided.iter() { - meth(w, *m); + if_ok!(meth(w, *m)); } - write!(w, "
"); + if_ok!(write!(w, "")); } local_data::get(cache_key, |cache| { let cache = cache.unwrap().get(); match cache.implementors.find(&it.id) { Some(implementors) => { - write!(w, " + if_ok!(write!(w, "

Implementors

    - "); + ")); for i in implementors.iter() { match *i { PathType(ref ty) => { - write!(w, "
  • {}
  • ", *ty); + if_ok!(write!(w, "
  • {}
  • ", *ty)); } OtherType(ref generics, ref trait_, ref for_) => { - write!(w, "
  • impl{} {} for {}
  • ", - *generics, *trait_, *for_); + if_ok!(write!(w, "
  • impl{} {} for {}
  • ", + *generics, *trait_, *for_)); } } } - write!(w, "
"); + if_ok!(write!(w, "")); } None => {} } + Ok(()) }) } -fn render_method(w: &mut Writer, meth: &clean::Item, withlink: bool) { +fn render_method(w: &mut Writer, meth: &clean::Item, + withlink: bool) -> fmt::Result { fn fun(w: &mut Writer, it: &clean::Item, purity: ast::Purity, g: &clean::Generics, selfty: &clean::SelfTy, d: &clean::FnDecl, - withlink: bool) { + withlink: bool) -> fmt::Result { write!(w, "{}fn {withlink, select, true{{name}} @@ -1185,118 +1193,125 @@ fn render_method(w: &mut Writer, meth: &clean::Item, withlink: bool) { name = it.name.get_ref().as_slice(), generics = *g, decl = Method(selfty, d), - withlink = if withlink {"true"} else {"false"}); + withlink = if withlink {"true"} else {"false"}) } match meth.inner { clean::TyMethodItem(ref m) => { - fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl, withlink); + fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl, withlink) } clean::MethodItem(ref m) => { - fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl, withlink); + fun(w, meth, m.purity, &m.generics, &m.self_, &m.decl, withlink) } _ => unreachable!() } } -fn item_struct(w: &mut Writer, it: &clean::Item, s: &clean::Struct) { - write!(w, "
");
-    render_struct(w, it, Some(&s.generics), s.struct_type, s.fields,
-                  s.fields_stripped, "", true);
-    write!(w, "
"); +fn item_struct(w: &mut Writer, it: &clean::Item, + s: &clean::Struct) -> fmt::Result { + if_ok!(write!(w, "
"));
+    if_ok!(render_struct(w, it, Some(&s.generics), s.struct_type, s.fields,
+                         s.fields_stripped, "", true));
+    if_ok!(write!(w, "
")); - document(w, it); + if_ok!(document(w, it)); match s.struct_type { doctree::Plain if s.fields.len() > 0 => { - write!(w, "

Fields

\n"); + if_ok!(write!(w, "

Fields

\n
")); for field in s.fields.iter() { - write!(w, ""); + if_ok!(write!(w, "")); } - write!(w, "
\ - {name}", - name = field.name.get_ref().as_slice()); - document(w, field); - write!(w, "
\ + {name}", + name = field.name.get_ref().as_slice())); + if_ok!(document(w, field)); + if_ok!(write!(w, "
"); + if_ok!(write!(w, "")); } _ => {} } - render_methods(w, it); + render_methods(w, it) } -fn item_enum(w: &mut Writer, it: &clean::Item, e: &clean::Enum) { - write!(w, "
{}enum {}{}",
-           VisSpace(it.visibility),
-           it.name.get_ref().as_slice(),
-           e.generics);
+fn item_enum(w: &mut Writer, it: &clean::Item, e: &clean::Enum) -> fmt::Result {
+    if_ok!(write!(w, "
{}enum {}{}",
+                  VisSpace(it.visibility),
+                  it.name.get_ref().as_slice(),
+                  e.generics));
     if e.variants.len() == 0 && !e.variants_stripped {
-        write!(w, " \\{\\}");
+        if_ok!(write!(w, " \\{\\}"));
     } else {
-        write!(w, " \\{\n");
+        if_ok!(write!(w, " \\{\n"));
         for v in e.variants.iter() {
-            write!(w, "    ");
+            if_ok!(write!(w, "    "));
             let name = v.name.get_ref().as_slice();
             match v.inner {
                 clean::VariantItem(ref var) => {
                     match var.kind {
-                        clean::CLikeVariant => write!(w, "{}", name),
+                        clean::CLikeVariant => if_ok!(write!(w, "{}", name)),
                         clean::TupleVariant(ref tys) => {
-                            write!(w, "{}(", name);
+                            if_ok!(write!(w, "{}(", name));
                             for (i, ty) in tys.iter().enumerate() {
-                                if i > 0 { write!(w, ", ") }
-                                write!(w, "{}", *ty);
+                                if i > 0 {
+                                    if_ok!(write!(w, ", "))
+                                }
+                                if_ok!(write!(w, "{}", *ty));
                             }
-                            write!(w, ")");
+                            if_ok!(write!(w, ")"));
                         }
                         clean::StructVariant(ref s) => {
-                            render_struct(w, v, None, s.struct_type, s.fields,
-                                          s.fields_stripped, "    ", false);
+                            if_ok!(render_struct(w, v, None, s.struct_type,
+                                                 s.fields, s.fields_stripped,
+                                                 "    ", false));
                         }
                     }
                 }
                 _ => unreachable!()
             }
-            write!(w, ",\n");
+            if_ok!(write!(w, ",\n"));
         }
 
         if e.variants_stripped {
-            write!(w, "    // some variants omitted\n");
+            if_ok!(write!(w, "    // some variants omitted\n"));
         }
-        write!(w, "\\}");
+        if_ok!(write!(w, "\\}"));
     }
-    write!(w, "
"); + if_ok!(write!(w, "
")); - document(w, it); + if_ok!(document(w, it)); if e.variants.len() > 0 { - write!(w, "

Variants

\n"); + if_ok!(write!(w, "

Variants

\n
")); for variant in e.variants.iter() { - write!(w, "
{name}", - name = variant.name.get_ref().as_slice()); - document(w, variant); + if_ok!(write!(w, "
{name}", + name = variant.name.get_ref().as_slice())); + if_ok!(document(w, variant)); match variant.inner { clean::VariantItem(ref var) => { match var.kind { clean::StructVariant(ref s) => { - write!(w, "

Fields

\n"); + if_ok!(write!(w, "

Fields

\n +
")); for field in s.fields.iter() { - write!(w, ""); + if_ok!(write!(w, "")); } - write!(w, "
\ - {f}", - v = variant.name.get_ref().as_slice(), - f = field.name.get_ref().as_slice()); - document(w, field); - write!(w, "
\ + {f}", + v = variant.name.get_ref().as_slice(), + f = field.name.get_ref().as_slice())); + if_ok!(document(w, field)); + if_ok!(write!(w, "
"); + if_ok!(write!(w, "
")); } _ => () } } _ => () } - write!(w, ""); + if_ok!(write!(w, "")); } - write!(w, ""); + if_ok!(write!(w, "")); } - render_methods(w, it); + if_ok!(render_methods(w, it)); + Ok(()) } fn render_struct(w: &mut Writer, it: &clean::Item, @@ -1305,54 +1320,59 @@ fn render_struct(w: &mut Writer, it: &clean::Item, fields: &[clean::Item], fields_stripped: bool, tab: &str, - structhead: bool) { - write!(w, "{}{}{}", - VisSpace(it.visibility), - if structhead {"struct "} else {""}, - it.name.get_ref().as_slice()); + structhead: bool) -> fmt::Result { + if_ok!(write!(w, "{}{}{}", + VisSpace(it.visibility), + if structhead {"struct "} else {""}, + it.name.get_ref().as_slice())); match g { - Some(g) => write!(w, "{}", *g), + Some(g) => if_ok!(write!(w, "{}", *g)), None => {} } match ty { doctree::Plain => { - write!(w, " \\{\n{}", tab); + if_ok!(write!(w, " \\{\n{}", tab)); for field in fields.iter() { match field.inner { clean::StructFieldItem(ref ty) => { - write!(w, " {}{}: {},\n{}", - VisSpace(field.visibility), - field.name.get_ref().as_slice(), - ty.type_, - tab); + if_ok!(write!(w, " {}{}: {},\n{}", + VisSpace(field.visibility), + field.name.get_ref().as_slice(), + ty.type_, + tab)); } _ => unreachable!() } } if fields_stripped { - write!(w, " // some fields omitted\n{}", tab); + if_ok!(write!(w, " // some fields omitted\n{}", tab)); } - write!(w, "\\}"); + if_ok!(write!(w, "\\}")); } doctree::Tuple | doctree::Newtype => { - write!(w, "("); + if_ok!(write!(w, "(")); for (i, field) in fields.iter().enumerate() { - if i > 0 { write!(w, ", ") } + if i > 0 { + if_ok!(write!(w, ", ")); + } match field.inner { clean::StructFieldItem(ref field) => { - write!(w, "{}", field.type_); + if_ok!(write!(w, "{}", field.type_)); } _ => unreachable!() } } - write!(w, ");"); + if_ok!(write!(w, ");")); + } + doctree::Unit => { + if_ok!(write!(w, ";")); } - doctree::Unit => { write!(w, ";"); } } + Ok(()) } -fn render_methods(w: &mut Writer, it: &clean::Item) { +fn render_methods(w: &mut Writer, it: &clean::Item) -> fmt::Result { local_data::get(cache_key, |cache| { let c = cache.unwrap().get(); match c.impls.find(&it.id) { @@ -1367,29 +1387,31 @@ fn render_methods(w: &mut Writer, it: &clean::Item) { let traits = traits.to_owned_vec(); if non_trait.len() > 0 { - write!(w, "

Methods

"); + if_ok!(write!(w, "

Methods

")); for &(ref i, ref dox) in non_trait.move_iter() { - render_impl(w, i, dox); + if_ok!(render_impl(w, i, dox)); } } if traits.len() > 0 { - write!(w, "

Trait \ - Implementations

"); + if_ok!(write!(w, "

Trait \ + Implementations

")); for &(ref i, ref dox) in traits.move_iter() { - render_impl(w, i, dox); + if_ok!(render_impl(w, i, dox)); } } } None => {} } + Ok(()) }) } -fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { - write!(w, "

impl{} ", i.generics); +fn render_impl(w: &mut Writer, i: &clean::Impl, + dox: &Option<~str>) -> fmt::Result { + if_ok!(write!(w, "

impl{} ", i.generics)); let trait_id = match i.trait_ { Some(ref ty) => { - write!(w, "{} for ", *ty); + if_ok!(write!(w, "{} for ", *ty)); match *ty { clean::ResolvedPath { id, .. } => Some(id), _ => None, @@ -1397,32 +1419,32 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { } None => None }; - write!(w, "{}

", i.for_); + if_ok!(write!(w, "{}

", i.for_)); match *dox { Some(ref dox) => { - write!(w, "
{}
", - Markdown(dox.as_slice())); + if_ok!(write!(w, "
{}
", + Markdown(dox.as_slice()))); } None => {} } - fn docmeth(w: &mut Writer, item: &clean::Item) -> bool { - write!(w, "

", - *item.name.get_ref()); - render_method(w, item, false); - write!(w, "

\n"); + fn docmeth(w: &mut Writer, item: &clean::Item) -> io::IoResult { + if_ok!(write!(w, "

", + *item.name.get_ref())); + if_ok!(render_method(w, item, false)); + if_ok!(write!(w, "

\n")); match item.doc_value() { Some(s) => { - write!(w, "
{}
", Markdown(s)); - true + if_ok!(write!(w, "
{}
", Markdown(s))); + Ok(true) } - None => false + None => Ok(false) } } - write!(w, "
"); + if_ok!(write!(w, "
")); for meth in i.methods.iter() { - if docmeth(w, meth) { + if if_ok!(docmeth(w, meth)) { continue } @@ -1431,7 +1453,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { None => continue, Some(id) => id, }; - local_data::get(cache_key, |cache| { + if_ok!(local_data::get(cache_key, |cache| { let cache = cache.unwrap().get(); match cache.traits.find(&trait_id) { Some(t) => { @@ -1440,9 +1462,9 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { Some(method) => { match method.item().doc_value() { Some(s) => { - write!(w, - "
{}
", - Markdown(s)); + if_ok!(write!(w, + "
{}
", + Markdown(s))); } None => {} } @@ -1452,7 +1474,8 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { } None => {} } - }) + Ok(()) + })) } // If we've implemented a trait, then also emit documentation for all @@ -1460,7 +1483,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { match trait_id { None => {} Some(id) => { - local_data::get(cache_key, |cache| { + if_ok!(local_data::get(cache_key, |cache| { let cache = cache.unwrap().get(); match cache.traits.find(&id) { Some(t) => { @@ -1471,50 +1494,56 @@ fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) { None => {} } - docmeth(w, method.item()); + if_ok!(docmeth(w, method.item())); } } None => {} } - }) + Ok(()) + })) } } - write!(w, "
"); + if_ok!(write!(w, "
")); + Ok(()) } -fn item_typedef(w: &mut Writer, it: &clean::Item, t: &clean::Typedef) { - write!(w, "
type {}{} = {};
", - it.name.get_ref().as_slice(), - t.generics, - t.type_); +fn item_typedef(w: &mut Writer, it: &clean::Item, + t: &clean::Typedef) -> fmt::Result { + if_ok!(write!(w, "
type {}{} = {};
", + it.name.get_ref().as_slice(), + t.generics, + t.type_)); - document(w, it); + document(w, it) } impl<'a> fmt::Show for Sidebar<'a> { - fn fmt(s: &Sidebar<'a>, fmt: &mut fmt::Formatter) { + fn fmt(s: &Sidebar<'a>, fmt: &mut fmt::Formatter) -> fmt::Result { let cx = s.cx; let it = s.item; - write!(fmt.buf, "

"); + if_ok!(write!(fmt.buf, "

")); let len = cx.current.len() - if it.is_mod() {1} else {0}; for (i, name) in cx.current.iter().take(len).enumerate() { - if i > 0 { write!(fmt.buf, "&\\#8203;::") } - write!(fmt.buf, "{}", - cx.root_path.slice_to((cx.current.len() - i - 1) * 3), *name); + if i > 0 { + if_ok!(write!(fmt.buf, "&\\#8203;::")); + } + if_ok!(write!(fmt.buf, "{}", + cx.root_path.slice_to((cx.current.len() - i - 1) * 3), + *name)); } - write!(fmt.buf, "

"); + if_ok!(write!(fmt.buf, "

")); fn block(w: &mut Writer, short: &str, longty: &str, - cur: &clean::Item, cx: &Context) { + cur: &clean::Item, cx: &Context) -> fmt::Result { let items = match cx.sidebar.find_equiv(&short) { Some(items) => items.as_slice(), - None => return + None => return Ok(()) }; - write!(w, "

{}

", short, longty); + if_ok!(write!(w, "

{}

", short, longty)); for item in items.iter() { let class = if cur.name.get_ref() == item && short == shortty(cur) { "current" } else { "" }; - write!(w, " fmt::Show for Sidebar<'a> { tysel = short, class = class, curty = shortty(cur), - name = item.as_slice()); + name = item.as_slice())); } - write!(w, "
"); + if_ok!(write!(w, "
")); + Ok(()) } - block(fmt.buf, "mod", "Modules", it, cx); - block(fmt.buf, "struct", "Structs", it, cx); - block(fmt.buf, "enum", "Enums", it, cx); - block(fmt.buf, "trait", "Traits", it, cx); - block(fmt.buf, "fn", "Functions", it, cx); + if_ok!(block(fmt.buf, "mod", "Modules", it, cx)); + if_ok!(block(fmt.buf, "struct", "Structs", it, cx)); + if_ok!(block(fmt.buf, "enum", "Enums", it, cx)); + if_ok!(block(fmt.buf, "trait", "Traits", it, cx)); + if_ok!(block(fmt.buf, "fn", "Functions", it, cx)); + Ok(()) } } @@ -1557,7 +1588,7 @@ fn build_sidebar(m: &clean::Module) -> HashMap<~str, ~[~str]> { } impl<'a> fmt::Show for Source<'a> { - fn fmt(s: &Source<'a>, fmt: &mut fmt::Formatter) { + fn fmt(s: &Source<'a>, fmt: &mut fmt::Formatter) -> fmt::Result { let Source(s) = *s; let lines = s.lines().len(); let mut cols = 0; @@ -1566,13 +1597,14 @@ impl<'a> fmt::Show for Source<'a> { cols += 1; tmp /= 10; } - write!(fmt.buf, "
");
+        if_ok!(write!(fmt.buf, "
"));
         for i in range(1, lines + 1) {
-            write!(fmt.buf, "{0:1$u}\n", i, cols);
+            if_ok!(write!(fmt.buf, "{0:1$u}\n", i, cols));
         }
-        write!(fmt.buf, "
"); - write!(fmt.buf, "
");
-        write!(fmt.buf, "{}", Escape(s.as_slice()));
-        write!(fmt.buf, "
"); + if_ok!(write!(fmt.buf, "
")); + if_ok!(write!(fmt.buf, "
"));
+        if_ok!(write!(fmt.buf, "{}", Escape(s.as_slice())));
+        if_ok!(write!(fmt.buf, "
")); + Ok(()) } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f7a484e3d3e00..fe989279e7147 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -162,10 +162,16 @@ pub fn main_args(args: &[~str]) -> int { let output = matches.opt_str("o").map(|s| Path::new(s)); match matches.opt_str("w") { Some(~"html") | None => { - html::render::run(crate, output.unwrap_or(Path::new("doc"))) + match html::render::run(crate, output.unwrap_or(Path::new("doc"))) { + Ok(()) => {} + Err(e) => fail!("failed to generate documentation: {}", e), + } } Some(~"json") => { - json_output(crate, res, output.unwrap_or(Path::new("doc.json"))) + match json_output(crate, res, output.unwrap_or(Path::new("doc.json"))) { + Ok(()) => {} + Err(e) => fail!("failed to write json: {}", e), + } } Some(s) => { println!("unknown output format: {}", s); @@ -276,8 +282,8 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output { /// run over the deserialized output. fn json_input(input: &str) -> Result { let mut input = match File::open(&Path::new(input)) { - Some(f) => f, - None => return Err(format!("couldn't open {} for reading", input)), + Ok(f) => f, + Err(e) => return Err(format!("couldn't open {}: {}", input, e)), }; match json::from_reader(&mut input) { Err(s) => Err(s.to_str()), @@ -312,7 +318,8 @@ fn json_input(input: &str) -> Result { /// Outputs the crate/plugin json as a giant json blob at the specified /// destination. -fn json_output(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) { +fn json_output(crate: clean::Crate, res: ~[plugins::PluginJson], + dst: Path) -> io::IoResult<()> { // { // "schema": version, // "crate": { parsed crate ... }, @@ -340,6 +347,7 @@ fn json_output(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) { json.insert(~"crate", crate_json); json.insert(~"plugins", json::Object(plugins_json)); - let mut file = File::create(&dst).unwrap(); - json::Object(json).to_writer(&mut file); + let mut file = if_ok!(File::create(&dst)); + if_ok!(json::Object(json).to_writer(&mut file)); + Ok(()) } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 12874d1b502a2..9e3b217f69f68 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -127,8 +127,8 @@ fn runtest(test: &str, cratename: &str, libs: HashSet) { let exe = outdir.path().join("rust_out"); let out = run::process_output(exe.as_str().unwrap(), []); match out { - None => fail!("couldn't run the test"), - Some(out) => { + Err(e) => fail!("couldn't run the test: {}", e), + Ok(out) => { if !out.status.success() { fail!("test executable failed:\n{}", str::from_utf8(out.error)); diff --git a/src/librustuv/file.rs b/src/librustuv/file.rs index 31afa7b5c7c80..2cef2664c2fc4 100644 --- a/src/librustuv/file.rs +++ b/src/librustuv/file.rs @@ -140,9 +140,9 @@ impl FsRequest { let mut paths = ~[]; let path = CString::new(path.with_ref(|p| p), false); let parent = Path::new(path); - c_str::from_c_multistring(req.get_ptr() as *libc::c_char, - Some(req.get_result() as uint), - |rel| { + let _ = c_str::from_c_multistring(req.get_ptr() as *libc::c_char, + Some(req.get_result() as uint), + |rel| { let p = rel.as_bytes(); paths.push(parent.join(p.slice_to(rel.len()))); }); @@ -378,7 +378,8 @@ impl Drop for FileWatcher { rtio::CloseAsynchronously => { unsafe { let req = uvll::malloc_req(uvll::UV_FS); - uvll::uv_fs_close(self.loop_.handle, req, self.fd, close_cb); + assert_eq!(uvll::uv_fs_close(self.loop_.handle, req, + self.fd, close_cb), 0); } extern fn close_cb(req: *uvll::uv_fs_t) { diff --git a/src/librustuv/homing.rs b/src/librustuv/homing.rs index 8d3e71312cd95..a2f3457a9430c 100644 --- a/src/librustuv/homing.rs +++ b/src/librustuv/homing.rs @@ -176,7 +176,7 @@ mod test { }); let task = pool.task(TaskOpts::new(), proc() { - port.recv(); + drop(port.recv()); }); pool.spawn_sched().send(sched::TaskFromFriend(task)); @@ -197,7 +197,7 @@ mod test { let listener = UdpWatcher::bind(local_loop(), addr2); chan.send((listener.unwrap(), addr1)); let mut listener = UdpWatcher::bind(local_loop(), addr1).unwrap(); - listener.sendto([1, 2, 3, 4], addr2); + listener.sendto([1, 2, 3, 4], addr2).unwrap(); }); let task = pool.task(TaskOpts::new(), proc() { diff --git a/src/librustuv/idle.rs b/src/librustuv/idle.rs index 3d6e81d0d6fd5..dafd3dbe1bc96 100644 --- a/src/librustuv/idle.rs +++ b/src/librustuv/idle.rs @@ -52,7 +52,7 @@ impl IdleWatcher { let data = uvll::get_data_for_uv_handle(handle); let f: ~proc() = cast::transmute(data); (*f)(); - uvll::uv_idle_stop(handle); + assert_eq!(uvll::uv_idle_stop(handle), 0); uvll::uv_close(handle, close_cb); } } @@ -122,7 +122,7 @@ mod test { } } }; - task.wake().map(|t| t.reawaken(true)); + let _ = task.wake().map(|t| t.reawaken(true)); } } diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index 0b889e17a445e..f945c0972ca39 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -40,6 +40,7 @@ via `close` and `delete` methods. #[crate_type = "dylib"]; #[feature(macro_rules)]; +#[deny(unused_result, unused_must_use)]; #[cfg(test)] extern mod green; @@ -207,7 +208,7 @@ fn wait_until_woken_after(slot: *mut Option, f: ||) { fn wakeup(slot: &mut Option) { assert!(slot.is_some()); - slot.take_unwrap().wake().map(|t| t.reawaken(true)); + let _ = slot.take_unwrap().wake().map(|t| t.reawaken(true)); } pub struct Request { @@ -276,7 +277,7 @@ impl Loop { pub fn wrap(handle: *uvll::uv_loop_t) -> Loop { Loop { handle: handle } } pub fn run(&mut self) { - unsafe { uvll::uv_run(self.handle, uvll::RUN_DEFAULT) }; + assert_eq!(unsafe { uvll::uv_run(self.handle, uvll::RUN_DEFAULT) }, 0); } pub fn close(&mut self) { diff --git a/src/librustuv/macros.rs b/src/librustuv/macros.rs index 6c8c16784a12b..75b68e3a52885 100644 --- a/src/librustuv/macros.rs +++ b/src/librustuv/macros.rs @@ -33,14 +33,15 @@ pub fn dumb_println(args: &fmt::Arguments) { struct Stderr; impl io::Writer for Stderr { - fn write(&mut self, data: &[u8]) { - unsafe { + fn write(&mut self, data: &[u8]) -> io::IoResult<()> { + let _ = unsafe { libc::write(libc::STDERR_FILENO, data.as_ptr() as *libc::c_void, - data.len() as libc::size_t); - } + data.len() as libc::size_t) + }; + Ok(()) // just ignore the errors } } let mut w = Stderr; - fmt::writeln(&mut w as &mut io::Writer, args); + let _ = fmt::writeln(&mut w as &mut io::Writer, args); } diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 8919ecfa97ef4..5461fc6272d35 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -953,11 +953,11 @@ mod test { spawn(proc() { let port2 = port.recv(); let mut stream = TcpWatcher::connect(local_loop(), addr).unwrap(); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); port2.recv(); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); - stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); port2.recv(); }); @@ -1008,7 +1008,7 @@ mod test { while stream.is_err() { stream = TcpWatcher::connect(local_loop(), addr); } - stream.unwrap().write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.unwrap().write([0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); } #[should_fail] #[test] @@ -1028,7 +1028,7 @@ mod test { let w = TcpListener::bind(local_loop(), addr).unwrap(); let mut w = w.listen().unwrap(); chan.send(()); - w.accept(); + drop(w.accept().unwrap()); }); port.recv(); let _w = TcpWatcher::connect(local_loop(), addr).unwrap(); diff --git a/src/librustuv/pipe.rs b/src/librustuv/pipe.rs index cfe86d739abcf..a021a13e2d98d 100644 --- a/src/librustuv/pipe.rs +++ b/src/librustuv/pipe.rs @@ -306,7 +306,7 @@ mod tests { let p = PipeListener::bind(local_loop(), &path2.to_c_str()).unwrap(); let mut p = p.listen().unwrap(); chan.send(()); - p.accept(); + drop(p.accept().unwrap()); }); port.recv(); let _c = PipeWatcher::connect(local_loop(), &path.to_c_str()).unwrap(); diff --git a/src/librustuv/queue.rs b/src/librustuv/queue.rs index 32f8d8532a209..0e1c4225caa93 100644 --- a/src/librustuv/queue.rs +++ b/src/librustuv/queue.rs @@ -67,7 +67,7 @@ extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) { loop { match state.consumer.pop() { mpsc::Data(Task(task)) => { - task.wake().map(|t| t.reawaken(true)); + let _ = task.wake().map(|t| t.reawaken(true)); } mpsc::Data(Increment) => unsafe { if state.refcnt == 0 { diff --git a/src/librustuv/signal.rs b/src/librustuv/signal.rs index 8cb0c1f0a52d7..2fcc61be79bdf 100644 --- a/src/librustuv/signal.rs +++ b/src/librustuv/signal.rs @@ -86,7 +86,7 @@ mod test { chan); spawn(proc() { - port.try_recv(); + let _ = port.recv_opt(); }); // when we drop the SignalWatcher we're going to destroy the channel, diff --git a/src/librustuv/timer.rs b/src/librustuv/timer.rs index aeda1a45175ea..792414238fdaa 100644 --- a/src/librustuv/timer.rs +++ b/src/librustuv/timer.rs @@ -138,11 +138,11 @@ extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) { match timer.action.take_unwrap() { WakeTask(task) => { - task.wake().map(|t| t.reawaken(true)); + let _ = task.wake().map(|t| t.reawaken(true)); } - SendOnce(chan) => { chan.try_send(()); } + SendOnce(chan) => { let _ = chan.try_send(()); } SendMany(chan, id) => { - chan.try_send(()); + let _ = chan.try_send(()); // Note that the above operation could have performed some form of // scheduling. This means that the timer may have decided to insert @@ -246,7 +246,7 @@ mod test { let timer_port = timer.period(1000); spawn(proc() { - timer_port.recv_opt(); + let _ = timer_port.recv_opt(); }); // when we drop the TimerWatcher we're going to destroy the channel, @@ -260,10 +260,10 @@ mod test { let timer_port = timer.period(1000); spawn(proc() { - timer_port.recv_opt(); + let _ = timer_port.recv_opt(); }); - timer.oneshot(1); + drop(timer.oneshot(1)); } #[test] fn reset_doesnt_switch_tasks2() { @@ -272,7 +272,7 @@ mod test { let timer_port = timer.period(1000); spawn(proc() { - timer_port.recv_opt(); + let _ = timer_port.recv_opt(); }); timer.sleep(1); @@ -299,7 +299,7 @@ mod test { #[test] fn receiver_goes_away_oneshot() { let mut timer1 = TimerWatcher::new(local_loop()); - timer1.oneshot(1); + drop(timer1.oneshot(1)); let mut timer2 = TimerWatcher::new(local_loop()); // while sleeping, the prevous timer should fire and not have its // callback do something terrible. @@ -309,7 +309,7 @@ mod test { #[test] fn receiver_goes_away_period() { let mut timer1 = TimerWatcher::new(local_loop()); - timer1.period(1); + drop(timer1.period(1)); let mut timer2 = TimerWatcher::new(local_loop()); // while sleeping, the prevous timer should fire and not have its // callback do something terrible. diff --git a/src/librustuv/uvio.rs b/src/librustuv/uvio.rs index e0bff059b0c91..8a8ef4a41ec4e 100644 --- a/src/librustuv/uvio.rs +++ b/src/librustuv/uvio.rs @@ -71,7 +71,7 @@ impl Drop for UvEventLoop { // after the loop has been closed because during the closing of the loop // the handle is required to be used apparently. let handle = self.uvio.handle_pool.get_ref().handle(); - self.uvio.handle_pool.take(); + drop(self.uvio.handle_pool.take()); self.uvio.loop_.close(); unsafe { uvll::free_handle(handle) } } diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index 7b1a6055542d0..bccebeaa79f6b 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -1252,7 +1252,7 @@ mod test { spawn(proc() { let _p = port; }); - task::try(proc() { + let _ = task::try(proc() { chan.send(1); }); } diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index a17a030f4f792..06737e22007e4 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -163,9 +163,10 @@ method of the signature: ```rust # use std; +# mod fmt { pub type Result = (); } # struct T; # trait SomeName { -fn fmt(value: &T, f: &mut std::fmt::Formatter); +fn fmt(value: &T, f: &mut std::fmt::Formatter) -> fmt::Result; # } ``` @@ -174,7 +175,14 @@ emit output into the `f.buf` stream. It is up to each format trait implementation to correctly adhere to the requested formatting parameters. The values of these parameters will be listed in the fields of the `Formatter` struct. In order to help with this, the `Formatter` struct also provides some -helper methods. An example of implementing the formatting traits would look +helper methods. + +Additionally, the return value of this function is `fmt::Result` which is a +typedef to `Result<(), IoError>` (also known as `IoError<()>`). Formatting +implementations should ensure that they return errors from `write!` correctly +(propagating errors upward). + +An example of implementing the formatting traits would look like: ```rust @@ -187,7 +195,7 @@ struct Vector2D { } impl fmt::Show for Vector2D { - fn fmt(obj: &Vector2D, f: &mut fmt::Formatter) { + fn fmt(obj: &Vector2D, f: &mut fmt::Formatter) -> fmt::Result { // The `f.buf` value is of the type `&mut io::Writer`, which is what th // write! macro is expecting. Note that this formatting ignores the // various flags provided to format strings. @@ -198,7 +206,7 @@ impl fmt::Show for Vector2D { // Different traits allow different forms of output of a type. The meaning of // this format is to print the magnitude of a vector. impl fmt::Binary for Vector2D { - fn fmt(obj: &Vector2D, f: &mut fmt::Formatter) { + fn fmt(obj: &Vector2D, f: &mut fmt::Formatter) -> fmt::Result { let magnitude = (obj.x * obj.x + obj.y * obj.y) as f64; let magnitude = magnitude.sqrt(); @@ -207,7 +215,7 @@ impl fmt::Binary for Vector2D { // for details, and the function `pad` can be used to pad strings. let decimals = f.precision.unwrap_or(3); let string = f64::to_str_exact(magnitude, decimals); - f.pad_integral(string.as_bytes(), "", true); + f.pad_integral(string.as_bytes(), "", true) } } @@ -242,6 +250,7 @@ strings and instead directly write the output. Under the hood, this function is actually invoking the `write` function defined in this module. Example usage is: ```rust +# #[allow(unused_must_use)]; use std::io; let mut w = io::MemWriter::new(); @@ -468,16 +477,20 @@ will look like `"\\{"`. */ -#[cfg(not(stage0))] -use prelude::*; - use cast; use char::Char; +use container::Container; use io::MemWriter; use io; -use str; +use iter::{Iterator, range}; +use num::Signed; +use option::{Option,Some,None}; use repr; +use result::{Ok, Err}; +use str::StrSlice; +use str; use util; +use vec::ImmutableVector; use vec; // NOTE this is just because the `prelude::*` import above includes @@ -485,22 +498,11 @@ use vec; #[cfg(stage0)] pub use Default = fmt::Show; // export required for `format!()` etc. -#[cfg(stage0)] -use container::Container; -#[cfg(stage0)] -use iter::{Iterator, range}; -#[cfg(stage0)] -use option::{Option,Some,None}; -#[cfg(stage0)] -use vec::ImmutableVector; -#[cfg(stage0)] -use str::StrSlice; -#[cfg(stage0)] -use num::Signed; - pub mod parse; pub mod rt; +pub type Result = io::IoResult<()>; + /// A struct to represent both where to emit formatting strings to and how they /// should be formatted. A mutable version of this is passed to all formatting /// traits. @@ -527,7 +529,7 @@ pub struct Formatter<'a> { /// compile time it is ensured that the function and the value have the correct /// types, and then this struct is used to canonicalize arguments to one type. pub struct Argument<'a> { - priv formatter: extern "Rust" fn(&util::Void, &mut Formatter), + priv formatter: extern "Rust" fn(&util::Void, &mut Formatter) -> Result, priv value: &'a util::Void, } @@ -561,50 +563,50 @@ pub struct Arguments<'a> { /// to this trait. There is not an explicit way of selecting this trait to be /// used for formatting, it is only if no other format is specified. #[allow(missing_doc)] -pub trait Show { fn fmt(&Self, &mut Formatter); } +pub trait Show { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `b` character #[allow(missing_doc)] -pub trait Bool { fn fmt(&Self, &mut Formatter); } +pub trait Bool { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `c` character #[allow(missing_doc)] -pub trait Char { fn fmt(&Self, &mut Formatter); } +pub trait Char { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `i` and `d` characters #[allow(missing_doc)] -pub trait Signed { fn fmt(&Self, &mut Formatter); } +pub trait Signed { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `u` character #[allow(missing_doc)] -pub trait Unsigned { fn fmt(&Self, &mut Formatter); } +pub trait Unsigned { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `o` character #[allow(missing_doc)] -pub trait Octal { fn fmt(&Self, &mut Formatter); } +pub trait Octal { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `b` character #[allow(missing_doc)] -pub trait Binary { fn fmt(&Self, &mut Formatter); } +pub trait Binary { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `x` character #[allow(missing_doc)] -pub trait LowerHex { fn fmt(&Self, &mut Formatter); } +pub trait LowerHex { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `X` character #[allow(missing_doc)] -pub trait UpperHex { fn fmt(&Self, &mut Formatter); } +pub trait UpperHex { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `s` character #[allow(missing_doc)] -pub trait String { fn fmt(&Self, &mut Formatter); } +pub trait String { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `?` character #[allow(missing_doc)] -pub trait Poly { fn fmt(&Self, &mut Formatter); } +pub trait Poly { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `p` character #[allow(missing_doc)] -pub trait Pointer { fn fmt(&Self, &mut Formatter); } +pub trait Pointer { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `f` character #[allow(missing_doc)] -pub trait Float { fn fmt(&Self, &mut Formatter); } +pub trait Float { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `e` character #[allow(missing_doc)] -pub trait LowerExp { fn fmt(&Self, &mut Formatter); } +pub trait LowerExp { fn fmt(&Self, &mut Formatter) -> Result; } /// Format trait for the `E` character #[allow(missing_doc)] -pub trait UpperExp { fn fmt(&Self, &mut Formatter); } +pub trait UpperExp { fn fmt(&Self, &mut Formatter) -> Result; } // FIXME #11938 - UFCS would make us able call the above methods // directly Show::show(x, fmt). @@ -617,7 +619,7 @@ macro_rules! uniform_fn_call_workaround { ($( $name: ident, $trait_: ident; )*) => { $( #[doc(hidden)] - pub fn $name(x: &T, fmt: &mut Formatter) { + pub fn $name(x: &T, fmt: &mut Formatter) -> Result { $trait_::fmt(x, fmt) } )* @@ -653,21 +655,22 @@ uniform_fn_call_workaround! { /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::fmt; /// use std::io; /// /// let w = &mut io::stdout() as &mut io::Writer; -/// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world"); +/// format_args!(|args| { fmt::write(w, args); }, "Hello, {}!", "world"); /// ``` -pub fn write(output: &mut io::Writer, args: &Arguments) { +pub fn write(output: &mut io::Writer, args: &Arguments) -> Result { unsafe { write_unsafe(output, args.fmt, args.args) } } /// The `writeln` function takes the same arguments as `write`, except that it /// will also write a newline (`\n`) character at the end of the format string. -pub fn writeln(output: &mut io::Writer, args: &Arguments) { - unsafe { write_unsafe(output, args.fmt, args.args) } - output.write(['\n' as u8]); +pub fn writeln(output: &mut io::Writer, args: &Arguments) -> Result { + let first = unsafe { write_unsafe(output, args.fmt, args.args) }; + first.and_then(|()| output.write(['\n' as u8])) } /// The `write_unsafe` function takes an output stream, a precompiled format @@ -692,7 +695,7 @@ pub fn writeln(output: &mut io::Writer, args: &Arguments) { /// format string. pub unsafe fn write_unsafe(output: &mut io::Writer, fmt: &[rt::Piece], - args: &[Argument]) { + args: &[Argument]) -> Result { let mut formatter = Formatter { flags: 0, width: None, @@ -704,8 +707,9 @@ pub unsafe fn write_unsafe(output: &mut io::Writer, curarg: args.iter(), }; for piece in fmt.iter() { - formatter.run(piece, None); + if_ok!(formatter.run(piece, None)); } + Ok(()) } /// The format function takes a precompiled format string and a list of @@ -752,7 +756,7 @@ pub fn format(args: &Arguments) -> ~str { /// format string. pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str { let mut output = MemWriter::new(); - write_unsafe(&mut output as &mut io::Writer, fmt, args); + write_unsafe(&mut output as &mut io::Writer, fmt, args).unwrap(); return str::from_utf8_owned(output.unwrap()).unwrap(); } @@ -762,10 +766,10 @@ impl<'a> Formatter<'a> { // at runtime. This consumes all of the compile-time statics generated by // the format! syntax extension. - fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) { + fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) -> Result { match *piece { - rt::String(s) => { self.buf.write(s.as_bytes()); } - rt::CurrentArgument(()) => { self.buf.write(cur.unwrap().as_bytes()); } + rt::String(s) => self.buf.write(s.as_bytes()), + rt::CurrentArgument(()) => self.buf.write(cur.unwrap().as_bytes()), rt::Argument(ref arg) => { // Fill in the format parameters into the formatter self.fill = arg.format.fill; @@ -782,8 +786,8 @@ impl<'a> Formatter<'a> { // Then actually do some printing match arg.method { - None => { (value.formatter)(value.value, self); } - Some(ref method) => { self.execute(*method, value); } + None => (value.formatter)(value.value, self), + Some(ref method) => self.execute(*method, value) } } } @@ -804,7 +808,7 @@ impl<'a> Formatter<'a> { } } - fn execute(&mut self, method: &rt::Method, arg: Argument) { + fn execute(&mut self, method: &rt::Method, arg: Argument) -> Result { match *method { // Pluralization is selection upon a numeric value specified as the // parameter. @@ -847,7 +851,7 @@ impl<'a> Formatter<'a> { } } - self.runplural(value, *default); + self.runplural(value, *default) } // Select is just a matching against the string specified. @@ -860,24 +864,26 @@ impl<'a> Formatter<'a> { for s in selectors.iter() { if s.selector == value { for piece in s.result.iter() { - self.run(piece, Some(value)); + if_ok!(self.run(piece, Some(value))); } - return; + return Ok(()); } } for piece in default.iter() { - self.run(piece, Some(value)); + if_ok!(self.run(piece, Some(value))); } + Ok(()) } } } - fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) { + fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) -> Result { ::uint::to_str_bytes(value, 10, |buf| { let valuestr = str::from_utf8(buf).unwrap(); for piece in pieces.iter() { - self.run(piece, Some(valuestr)); + if_ok!(self.run(piece, Some(valuestr))); } + Ok(()) }) } @@ -899,7 +905,7 @@ impl<'a> Formatter<'a> { /// This function will correctly account for the flags provided as well as /// the minimum width. It will not take precision into account. pub fn pad_integral(&mut self, s: &[u8], alternate_prefix: &str, - positive: bool) { + positive: bool) -> Result { use fmt::parse::{FlagAlternate, FlagSignPlus, FlagSignAwareZeroPad}; let mut actual_len = s.len(); @@ -916,32 +922,32 @@ impl<'a> Formatter<'a> { let sign = |this: &mut Formatter| { if !signprinted { if this.flags & 1 << (FlagSignPlus as uint) != 0 && positive { - this.buf.write(['+' as u8]); + if_ok!(this.buf.write(['+' as u8])); } else if !positive { - this.buf.write(['-' as u8]); + if_ok!(this.buf.write(['-' as u8])); } if this.flags & 1 << (FlagAlternate as uint) != 0 { - this.buf.write(alternate_prefix.as_bytes()); + if_ok!(this.buf.write(alternate_prefix.as_bytes())); } signprinted = true; } + Ok(()) }; let emit = |this: &mut Formatter| { - sign(this); - this.buf.write(s); + sign(this).and_then(|()| this.buf.write(s)) }; match self.width { - None => { emit(self) } - Some(min) if actual_len >= min => { emit(self) } + None => emit(self), + Some(min) if actual_len >= min => emit(self), Some(min) => { if self.flags & 1 << (FlagSignAwareZeroPad as uint) != 0 { self.fill = '0'; - sign(self); + if_ok!(sign(self)); } self.with_padding(min - actual_len, parse::AlignRight, |me| { - emit(me); + emit(me) }) } } @@ -958,11 +964,10 @@ impl<'a> Formatter<'a> { /// is longer than this length /// /// Notably this function ignored the `flag` parameters - pub fn pad(&mut self, s: &str) { + pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front if self.width.is_none() && self.precision.is_none() { - self.buf.write(s.as_bytes()); - return + return self.buf.write(s.as_bytes()); } // The `precision` field can be interpreted as a `max-width` for the // string being formatted @@ -974,8 +979,7 @@ impl<'a> Formatter<'a> { let char_len = s.char_len(); if char_len >= max { let nchars = ::cmp::min(max, char_len); - self.buf.write(s.slice_chars(0, nchars).as_bytes()); - return + return self.buf.write(s.slice_chars(0, nchars).as_bytes()); } } None => {} @@ -985,7 +989,7 @@ impl<'a> Formatter<'a> { match self.width { // If we're under the maximum length, and there's no minimum length // requirements, then we can just emit the string - None => { self.buf.write(s.as_bytes()) } + None => self.buf.write(s.as_bytes()), // If we're under the maximum width, check if we're over the minimum // width, if so it's as easy as just emitting the string. @@ -997,7 +1001,7 @@ impl<'a> Formatter<'a> { // up the minimum width with the specified string + some alignment. Some(width) => { self.with_padding(width - s.len(), parse::AlignLeft, |me| { - me.buf.write(s.as_bytes()); + me.buf.write(s.as_bytes()) }) } } @@ -1006,29 +1010,30 @@ impl<'a> Formatter<'a> { fn with_padding(&mut self, padding: uint, default: parse::Alignment, - f: |&mut Formatter|) { + f: |&mut Formatter| -> Result) -> Result { let align = match self.align { parse::AlignUnknown => default, parse::AlignLeft | parse::AlignRight => self.align }; if align == parse::AlignLeft { - f(self); + if_ok!(f(self)); } let mut fill = [0u8, ..4]; let len = self.fill.encode_utf8(fill); for _ in range(0, padding) { - self.buf.write(fill.slice_to(len)); + if_ok!(self.buf.write(fill.slice_to(len))); } if align == parse::AlignRight { - f(self); + if_ok!(f(self)); } + Ok(()) } } /// This is a function which calls are emitted to by the compiler itself to /// create the Argument structures that are passed into the `format` function. #[doc(hidden)] #[inline] -pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter), +pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter) -> Result, t: &'a T) -> Argument<'a> { unsafe { Argument { @@ -1055,41 +1060,41 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> { // Implementations of the core formatting traits impl Bool for bool { - fn fmt(b: &bool, f: &mut Formatter) { - String::fmt(&(if *b {"true"} else {"false"}), f); + fn fmt(b: &bool, f: &mut Formatter) -> Result { + String::fmt(&(if *b {"true"} else {"false"}), f) } } impl<'a, T: str::Str> String for T { - fn fmt(s: &T, f: &mut Formatter) { - f.pad(s.as_slice()); + fn fmt(s: &T, f: &mut Formatter) -> Result { + f.pad(s.as_slice()) } } impl Char for char { - fn fmt(c: &char, f: &mut Formatter) { + fn fmt(c: &char, f: &mut Formatter) -> Result { let mut utf8 = [0u8, ..4]; let amt = c.encode_utf8(utf8); let s: &str = unsafe { cast::transmute(utf8.slice_to(amt)) }; - String::fmt(&s, f); + String::fmt(&s, f) } } macro_rules! int_base(($ty:ident, $into:ident, $base:expr, $name:ident, $prefix:expr) => { impl $name for $ty { - fn fmt(c: &$ty, f: &mut Formatter) { + fn fmt(c: &$ty, f: &mut Formatter) -> Result { ::$into::to_str_bytes(*c as $into, $base, |buf| { - f.pad_integral(buf, $prefix, true); + f.pad_integral(buf, $prefix, true) }) } } }) macro_rules! upper_hex(($ty:ident, $into:ident) => { impl UpperHex for $ty { - fn fmt(c: &$ty, f: &mut Formatter) { + fn fmt(c: &$ty, f: &mut Formatter) -> Result { ::$into::to_str_bytes(*c as $into, 16, |buf| { - upperhex(buf, f); + upperhex(buf, f) }) } } @@ -1097,7 +1102,7 @@ macro_rules! upper_hex(($ty:ident, $into:ident) => { // Not sure why, but this causes an "unresolved enum variant, struct or const" // when inlined into the above macro... #[doc(hidden)] -pub fn upperhex(buf: &[u8], f: &mut Formatter) { +pub fn upperhex(buf: &[u8], f: &mut Formatter) -> Result { let mut local = [0u8, ..16]; for i in ::iter::range(0, buf.len()) { local[i] = match buf[i] as char { @@ -1105,16 +1110,16 @@ pub fn upperhex(buf: &[u8], f: &mut Formatter) { c => c as u8, } } - f.pad_integral(local.slice_to(buf.len()), "0x", true); + f.pad_integral(local.slice_to(buf.len()), "0x", true) } macro_rules! integer(($signed:ident, $unsigned:ident) => { // Signed is special because it actuall emits the negative sign, // nothing else should do that, however. impl Signed for $signed { - fn fmt(c: &$signed, f: &mut Formatter) { + fn fmt(c: &$signed, f: &mut Formatter) -> Result { ::$unsigned::to_str_bytes(c.abs() as $unsigned, 10, |buf| { - f.pad_integral(buf, "", *c >= 0); + f.pad_integral(buf, "", *c >= 0) }) } } @@ -1138,35 +1143,35 @@ integer!(i64, u64) macro_rules! floating(($ty:ident) => { impl Float for $ty { - fn fmt(f: &$ty, fmt: &mut Formatter) { + fn fmt(f: &$ty, fmt: &mut Formatter) -> Result { // FIXME: this shouldn't perform an allocation let s = match fmt.precision { Some(i) => ::$ty::to_str_exact(f.abs(), i), None => ::$ty::to_str_digits(f.abs(), 6) }; - fmt.pad_integral(s.as_bytes(), "", *f >= 0.0); + fmt.pad_integral(s.as_bytes(), "", *f >= 0.0) } } impl LowerExp for $ty { - fn fmt(f: &$ty, fmt: &mut Formatter) { + fn fmt(f: &$ty, fmt: &mut Formatter) -> Result { // FIXME: this shouldn't perform an allocation let s = match fmt.precision { Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, false), None => ::$ty::to_str_exp_digits(f.abs(), 6, false) }; - fmt.pad_integral(s.as_bytes(), "", *f >= 0.0); + fmt.pad_integral(s.as_bytes(), "", *f >= 0.0) } } impl UpperExp for $ty { - fn fmt(f: &$ty, fmt: &mut Formatter) { + fn fmt(f: &$ty, fmt: &mut Formatter) -> Result { // FIXME: this shouldn't perform an allocation let s = match fmt.precision { Some(i) => ::$ty::to_str_exp_exact(f.abs(), i, true), None => ::$ty::to_str_exp_digits(f.abs(), 6, true) }; - fmt.pad_integral(s.as_bytes(), "", *f >= 0.0); + fmt.pad_integral(s.as_bytes(), "", *f >= 0.0) } } }) @@ -1174,39 +1179,41 @@ floating!(f32) floating!(f64) impl Poly for T { - fn fmt(t: &T, f: &mut Formatter) { + fn fmt(t: &T, f: &mut Formatter) -> Result { match (f.width, f.precision) { (None, None) => { - repr::write_repr(f.buf, t); + repr::write_repr(f.buf, t) } // If we have a specified width for formatting, then we have to make // this allocation of a new string _ => { let s = repr::repr_to_str(t); - f.pad(s); + f.pad(s) } } } } impl Pointer for *T { - fn fmt(t: &*T, f: &mut Formatter) { + fn fmt(t: &*T, f: &mut Formatter) -> Result { f.flags |= 1 << (parse::FlagAlternate as uint); ::uint::to_str_bytes(*t as uint, 16, |buf| { - f.pad_integral(buf, "0x", true); + f.pad_integral(buf, "0x", true) }) } } impl Pointer for *mut T { - fn fmt(t: &*mut T, f: &mut Formatter) { Pointer::fmt(&(*t as *T), f) } + fn fmt(t: &*mut T, f: &mut Formatter) -> Result { + Pointer::fmt(&(*t as *T), f) + } } // Implementation of Show for various core types macro_rules! delegate(($ty:ty to $other:ident) => { impl<'a> Show for $ty { - fn fmt(me: &$ty, f: &mut Formatter) { + fn fmt(me: &$ty, f: &mut Formatter) -> Result { $other::fmt(me, f) } } @@ -1229,10 +1236,10 @@ delegate!(f32 to Float) delegate!(f64 to Float) impl Show for *T { - fn fmt(me: &*T, f: &mut Formatter) { Pointer::fmt(me, f) } + fn fmt(me: &*T, f: &mut Formatter) -> Result { Pointer::fmt(me, f) } } impl Show for *mut T { - fn fmt(me: &*mut T, f: &mut Formatter) { Pointer::fmt(me, f) } + fn fmt(me: &*mut T, f: &mut Formatter) -> Result { Pointer::fmt(me, f) } } // If you expected tests to be here, look instead at the run-pass/ifmt.rs test, diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index 1444f9b4129d8..4163d1e0c96e8 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -27,13 +27,14 @@ #[allow(missing_doc)]; use container::Container; +use io::{Writer, IoResult}; use iter::Iterator; +use num::ToStrRadix; use option::{Some, None}; -use io::Writer; +use result::Ok; use str::OwnedStr; use to_bytes::IterBytes; use vec::ImmutableVector; -use num::ToStrRadix; // Alias `SipState` to `State`. pub use State = hash::SipState; @@ -164,7 +165,7 @@ macro_rules! compress ( impl Writer for SipState { // Methods for io::writer #[inline] - fn write(&mut self, msg: &[u8]) { + fn write(&mut self, msg: &[u8]) -> IoResult<()> { let length = msg.len(); self.length += length; @@ -180,7 +181,7 @@ impl Writer for SipState { t += 1; } self.ntail += length; - return; + return Ok(()) } let mut t = 0; @@ -222,17 +223,14 @@ impl Writer for SipState { t += 1 } self.ntail = left; - } - - fn flush(&mut self) { - // No-op + Ok(()) } } impl Streaming for SipState { #[inline] fn input(&mut self, buf: &[u8]) { - self.write(buf); + self.write(buf).unwrap(); } #[inline] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 64e42c5480f28..256f9d325f3ed 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -11,10 +11,11 @@ //! Buffering wrappers for I/O traits use container::Container; -use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE}; +use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; use iter::ExactSize; use num; -use option::{Option, Some, None}; +use option::{Some, None}; +use result::{Ok, Err}; use vec::{OwnedVector, ImmutableVector, MutableVector}; use vec; @@ -30,14 +31,13 @@ use vec; /// ```rust /// use std::io::{BufferedReader, File}; /// -/// # let _g = ::std::io::ignore_io_error(); /// let file = File::open(&Path::new("message.txt")); /// let mut reader = BufferedReader::new(file); /// /// let mut buf = [0, ..100]; /// match reader.read(buf) { -/// Some(nread) => println!("Read {} bytes", nread), -/// None => println!("At the end of the file!") +/// Ok(nread) => println!("Read {} bytes", nread), +/// Err(e) => println!("error reading: {}", e) /// } /// ``` pub struct BufferedReader { @@ -86,17 +86,12 @@ impl BufferedReader { } impl Buffer for BufferedReader { - fn fill<'a>(&'a mut self) -> &'a [u8] { + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { if self.pos == self.cap { - match self.inner.read(self.buf) { - Some(cap) => { - self.pos = 0; - self.cap = cap; - } - None => { self.eof = true; } - } + self.cap = if_ok!(self.inner.read(self.buf)); + self.pos = 0; } - return self.buf.slice(self.pos, self.cap); + Ok(self.buf.slice(self.pos, self.cap)) } fn consume(&mut self, amt: uint) { @@ -106,18 +101,15 @@ impl Buffer for BufferedReader { } impl Reader for BufferedReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let nread = { - let available = self.fill(); + let available = if_ok!(self.fill()); let nread = num::min(available.len(), buf.len()); vec::bytes::copy_memory(buf, available.slice_to(nread)); nread }; self.pos += nread; - if nread == 0 && buf.len() != 0 && self.eof { - return None; - } - Some(nread) + Ok(nread) } } @@ -128,9 +120,9 @@ impl Reader for BufferedReader { /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::io::{BufferedWriter, File}; /// -/// # let _g = ::std::io::ignore_io_error(); /// let file = File::open(&Path::new("message.txt")); /// let mut writer = BufferedWriter::new(file); /// @@ -161,10 +153,13 @@ impl BufferedWriter { BufferedWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } - fn flush_buf(&mut self) { + fn flush_buf(&mut self) -> IoResult<()> { if self.pos != 0 { - self.inner.write(self.buf.slice_to(self.pos)); + let ret = self.inner.write(self.buf.slice_to(self.pos)); self.pos = 0; + ret + } else { + Ok(()) } } @@ -178,29 +173,30 @@ impl BufferedWriter { /// /// The buffer is flushed before returning the writer. pub fn unwrap(mut self) -> W { - self.flush_buf(); + // FIXME: is failing the right thing to do if flushing fails? + self.flush_buf().unwrap(); self.inner } } impl Writer for BufferedWriter { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { if self.pos + buf.len() > self.buf.len() { - self.flush_buf(); + if_ok!(self.flush_buf()); } if buf.len() > self.buf.len() { - self.inner.write(buf); + self.inner.write(buf) } else { let dst = self.buf.mut_slice_from(self.pos); vec::bytes::copy_memory(dst, buf); self.pos += buf.len(); + Ok(()) } } - fn flush(&mut self) { - self.flush_buf(); - self.inner.flush(); + fn flush(&mut self) -> IoResult<()> { + self.flush_buf().and_then(|()| self.inner.flush()) } } @@ -234,18 +230,19 @@ impl LineBufferedWriter { } impl Writer for LineBufferedWriter { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { match buf.iter().rposition(|&b| b == '\n' as u8) { Some(i) => { - self.inner.write(buf.slice_to(i + 1)); - self.inner.flush(); - self.inner.write(buf.slice_from(i + 1)); + if_ok!(self.inner.write(buf.slice_to(i + 1))); + if_ok!(self.inner.flush()); + if_ok!(self.inner.write(buf.slice_from(i + 1))); + Ok(()) } None => self.inner.write(buf), } } - fn flush(&mut self) { self.inner.flush() } + fn flush(&mut self) -> IoResult<()> { self.inner.flush() } } struct InternalBufferedWriter(BufferedWriter); @@ -258,7 +255,9 @@ impl InternalBufferedWriter { } impl Reader for InternalBufferedWriter { - fn read(&mut self, buf: &mut [u8]) -> Option { self.get_mut_ref().inner.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { + self.get_mut_ref().inner.read(buf) + } } /// Wraps a Stream and buffers input and output to and from it @@ -268,9 +267,9 @@ impl Reader for InternalBufferedWriter { /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::io::{BufferedStream, File}; /// -/// # let _g = ::std::io::ignore_io_error(); /// let file = File::open(&Path::new("message.txt")); /// let mut stream = BufferedStream::new(file); /// @@ -279,8 +278,8 @@ impl Reader for InternalBufferedWriter { /// /// let mut buf = [0, ..100]; /// match stream.read(buf) { -/// Some(nread) => println!("Read {} bytes", nread), -/// None => println!("At the end of the stream!") +/// Ok(nread) => println!("Read {} bytes", nread), +/// Err(e) => println!("error reading: {}", e) /// } /// ``` pub struct BufferedStream { @@ -326,17 +325,23 @@ impl BufferedStream { } impl Buffer for BufferedStream { - fn fill<'a>(&'a mut self) -> &'a [u8] { self.inner.fill() } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill() } fn consume(&mut self, amt: uint) { self.inner.consume(amt) } } impl Reader for BufferedStream { - fn read(&mut self, buf: &mut [u8]) -> Option { self.inner.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { + self.inner.read(buf) + } } impl Writer for BufferedStream { - fn write(&mut self, buf: &[u8]) { self.inner.inner.get_mut_ref().write(buf) } - fn flush(&mut self) { self.inner.inner.get_mut_ref().flush() } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.inner.inner.get_mut_ref().write(buf) + } + fn flush(&mut self) -> IoResult<()> { + self.inner.inner.get_mut_ref().flush() + } } #[cfg(test)] @@ -354,13 +359,13 @@ mod test { pub struct NullStream; impl Reader for NullStream { - fn read(&mut self, _: &mut [u8]) -> Option { - None + fn read(&mut self, _: &mut [u8]) -> io::IoResult { + Err(io::standard_error(io::EndOfFile)) } } impl Writer for NullStream { - fn write(&mut self, _: &[u8]) { } + fn write(&mut self, _: &[u8]) -> io::IoResult<()> { Ok(()) } } /// A dummy reader intended at testing short-reads propagation. @@ -369,8 +374,11 @@ mod test { } impl Reader for ShortReader { - fn read(&mut self, _: &mut [u8]) -> Option { - self.lengths.shift() + fn read(&mut self, _: &mut [u8]) -> io::IoResult { + match self.lengths.shift() { + Some(i) => Ok(i), + None => Err(io::standard_error(io::EndOfFile)) + } } } @@ -381,24 +389,24 @@ mod test { let mut buf = [0, 0, 0]; let nread = reader.read(buf); - assert_eq!(Some(2), nread); + assert_eq!(Ok(2), nread); assert_eq!([0, 1, 0], buf); let mut buf = [0]; let nread = reader.read(buf); - assert_eq!(Some(1), nread); + assert_eq!(Ok(1), nread); assert_eq!([2], buf); let mut buf = [0, 0, 0]; let nread = reader.read(buf); - assert_eq!(Some(1), nread); + assert_eq!(Ok(1), nread); assert_eq!([3, 0, 0], buf); let nread = reader.read(buf); - assert_eq!(Some(1), nread); + assert_eq!(Ok(1), nread); assert_eq!([4, 0, 0], buf); - assert_eq!(None, reader.read(buf)); + assert!(reader.read(buf).is_err()); } #[test] @@ -406,35 +414,35 @@ mod test { let inner = MemWriter::new(); let mut writer = BufferedWriter::with_capacity(2, inner); - writer.write([0, 1]); + writer.write([0, 1]).unwrap(); assert_eq!([], writer.get_ref().get_ref()); - writer.write([2]); + writer.write([2]).unwrap(); assert_eq!([0, 1], writer.get_ref().get_ref()); - writer.write([3]); + writer.write([3]).unwrap(); assert_eq!([0, 1], writer.get_ref().get_ref()); - writer.flush(); + writer.flush().unwrap(); assert_eq!([0, 1, 2, 3], writer.get_ref().get_ref()); - writer.write([4]); - writer.write([5]); + writer.write([4]).unwrap(); + writer.write([5]).unwrap(); assert_eq!([0, 1, 2, 3], writer.get_ref().get_ref()); - writer.write([6]); + writer.write([6]).unwrap(); assert_eq!([0, 1, 2, 3, 4, 5], writer.get_ref().get_ref()); - writer.write([7, 8]); + writer.write([7, 8]).unwrap(); assert_eq!([0, 1, 2, 3, 4, 5, 6], writer.get_ref().get_ref()); - writer.write([9, 10, 11]); + writer.write([9, 10, 11]).unwrap(); assert_eq!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], writer.get_ref().get_ref()); - writer.flush(); + writer.flush().unwrap(); assert_eq!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], writer.get_ref().get_ref()); } @@ -442,7 +450,7 @@ mod test { #[test] fn test_buffered_writer_inner_flushes() { let mut w = BufferedWriter::with_capacity(3, MemWriter::new()); - w.write([0, 1]); + w.write([0, 1]).unwrap(); assert_eq!([], w.get_ref().get_ref()); let w = w.unwrap(); assert_eq!([0, 1], w.get_ref()); @@ -455,47 +463,49 @@ mod test { struct S; impl io::Writer for S { - fn write(&mut self, _: &[u8]) {} + fn write(&mut self, _: &[u8]) -> io::IoResult<()> { Ok(()) } } impl io::Reader for S { - fn read(&mut self, _: &mut [u8]) -> Option { None } + fn read(&mut self, _: &mut [u8]) -> io::IoResult { + Err(io::standard_error(io::EndOfFile)) + } } let mut stream = BufferedStream::new(S); let mut buf = []; - stream.read(buf); - stream.write(buf); - stream.flush(); + assert!(stream.read(buf).is_err()); + stream.write(buf).unwrap(); + stream.flush().unwrap(); } #[test] fn test_read_until() { let inner = MemReader::new(~[0, 1, 2, 1, 0]); let mut reader = BufferedReader::with_capacity(2, inner); - assert_eq!(reader.read_until(0), Some(~[0])); - assert_eq!(reader.read_until(2), Some(~[1, 2])); - assert_eq!(reader.read_until(1), Some(~[1])); - assert_eq!(reader.read_until(8), Some(~[0])); - assert_eq!(reader.read_until(9), None); + assert_eq!(reader.read_until(0), Ok(~[0])); + assert_eq!(reader.read_until(2), Ok(~[1, 2])); + assert_eq!(reader.read_until(1), Ok(~[1])); + assert_eq!(reader.read_until(8), Ok(~[0])); + assert!(reader.read_until(9).is_err()); } #[test] fn test_line_buffer() { let mut writer = LineBufferedWriter::new(MemWriter::new()); - writer.write([0]); + writer.write([0]).unwrap(); assert_eq!(writer.get_ref().get_ref(), []); - writer.write([1]); + writer.write([1]).unwrap(); assert_eq!(writer.get_ref().get_ref(), []); - writer.flush(); + writer.flush().unwrap(); assert_eq!(writer.get_ref().get_ref(), [0, 1]); - writer.write([0, '\n' as u8, 1, '\n' as u8, 2]); + writer.write([0, '\n' as u8, 1, '\n' as u8, 2]).unwrap(); assert_eq!(writer.get_ref().get_ref(), [0, 1, 0, '\n' as u8, 1, '\n' as u8]); - writer.flush(); + writer.flush().unwrap(); assert_eq!(writer.get_ref().get_ref(), [0, 1, 0, '\n' as u8, 1, '\n' as u8, 2]); - writer.write([3, '\n' as u8]); + writer.write([3, '\n' as u8]).unwrap(); assert_eq!(writer.get_ref().get_ref(), [0, 1, 0, '\n' as u8, 1, '\n' as u8, 2, 3, '\n' as u8]); } @@ -504,10 +514,10 @@ mod test { fn test_read_line() { let in_buf = MemReader::new(bytes!("a\nb\nc").to_owned()); let mut reader = BufferedReader::with_capacity(2, in_buf); - assert_eq!(reader.read_line(), Some(~"a\n")); - assert_eq!(reader.read_line(), Some(~"b\n")); - assert_eq!(reader.read_line(), Some(~"c")); - assert_eq!(reader.read_line(), None); + assert_eq!(reader.read_line(), Ok(~"a\n")); + assert_eq!(reader.read_line(), Ok(~"b\n")); + assert_eq!(reader.read_line(), Ok(~"c")); + assert!(reader.read_line().is_err()); } #[test] @@ -526,20 +536,20 @@ mod test { let inner = ShortReader{lengths: ~[0, 1, 2, 0, 1, 0]}; let mut reader = BufferedReader::new(inner); let mut buf = [0, 0]; - assert_eq!(reader.read(buf), Some(0)); - assert_eq!(reader.read(buf), Some(1)); - assert_eq!(reader.read(buf), Some(2)); - assert_eq!(reader.read(buf), Some(0)); - assert_eq!(reader.read(buf), Some(1)); - assert_eq!(reader.read(buf), Some(0)); - assert_eq!(reader.read(buf), None); + assert_eq!(reader.read(buf), Ok(0)); + assert_eq!(reader.read(buf), Ok(1)); + assert_eq!(reader.read(buf), Ok(2)); + assert_eq!(reader.read(buf), Ok(0)); + assert_eq!(reader.read(buf), Ok(1)); + assert_eq!(reader.read(buf), Ok(0)); + assert!(reader.read(buf).is_err()); } #[test] fn read_char_buffered() { let buf = [195u8, 159u8]; let mut reader = BufferedReader::with_capacity(1, BufReader::new(buf)); - assert_eq!(reader.read_char(), Some('ß')); + assert_eq!(reader.read_char(), Ok('ß')); } #[bench] diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 1eaa752d2a31a..6ed588ac69fd4 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -14,7 +14,7 @@ use comm::{Port, Chan}; use cmp; use io; use option::{None, Option, Some}; -use super::{Reader, Writer}; +use super::{Reader, Writer, IoResult}; use vec::{bytes, CloneableVector, MutableVector, ImmutableVector}; /// Allows reading from a port. @@ -49,7 +49,7 @@ impl PortReader { } impl Reader for PortReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let mut num_read = 0; loop { match self.buf { @@ -71,10 +71,9 @@ impl Reader for PortReader { self.closed = self.buf.is_none(); } if self.closed && num_read == 0 { - io::io_error::cond.raise(io::standard_error(io::EndOfFile)); - None + Err(io::standard_error(io::EndOfFile)) } else { - Some(num_read) + Ok(num_read) } } } @@ -98,13 +97,15 @@ impl ChanWriter { } impl Writer for ChanWriter { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { if !self.chan.try_send(buf.to_owned()) { - io::io_error::cond.raise(io::IoError { + Err(io::IoError { kind: io::BrokenPipe, desc: "Pipe closed", detail: None - }); + }) + } else { + Ok(()) } } } @@ -132,36 +133,28 @@ mod test { let mut buf = ~[0u8, ..3]; - assert_eq!(Some(0), reader.read([])); + assert_eq!(Ok(0), reader.read([])); - assert_eq!(Some(3), reader.read(buf)); + assert_eq!(Ok(3), reader.read(buf)); assert_eq!(~[1,2,3], buf); - assert_eq!(Some(3), reader.read(buf)); + assert_eq!(Ok(3), reader.read(buf)); assert_eq!(~[4,5,6], buf); - assert_eq!(Some(2), reader.read(buf)); + assert_eq!(Ok(2), reader.read(buf)); assert_eq!(~[7,8,6], buf); - let mut err = None; - let result = io::io_error::cond.trap(|io::standard_error(k, _, _)| { - err = Some(k) - }).inside(|| { - reader.read(buf) - }); - assert_eq!(Some(io::EndOfFile), err); - assert_eq!(None, result); + match reader.read(buf) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::EndOfFile), + } assert_eq!(~[7,8,6], buf); // Ensure it continues to fail in the same way. - err = None; - let result = io::io_error::cond.trap(|io::standard_error(k, _, _)| { - err = Some(k) - }).inside(|| { - reader.read(buf) - }); - assert_eq!(Some(io::EndOfFile), err); - assert_eq!(None, result); + match reader.read(buf) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::EndOfFile), + } assert_eq!(~[7,8,6], buf); } @@ -169,18 +162,15 @@ mod test { fn test_chan_writer() { let (port, chan) = Chan::new(); let mut writer = ChanWriter::new(chan); - writer.write_be_u32(42); + writer.write_be_u32(42).unwrap(); let wanted = ~[0u8, 0u8, 0u8, 42u8]; let got = task::try(proc() { port.recv() }).unwrap(); assert_eq!(wanted, got); - let mut err = None; - io::io_error::cond.trap(|io::IoError { kind, .. } | { - err = Some(kind) - }).inside(|| { - writer.write_u8(1) - }); - assert_eq!(Some(io::BrokenPipe), err); + match writer.write_u8(1) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::BrokenPipe), + } } } diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 548dc3efe92f0..49d51cbb26fc8 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -46,7 +46,7 @@ impl<'r, R: Reader> Bytes<'r, R> { impl<'r, R: Reader> Iterator for Bytes<'r, R> { #[inline] fn next(&mut self) -> Option { - self.reader.read_byte() + self.reader.read_byte().ok() } } @@ -125,23 +125,22 @@ pub fn u64_from_be_bytes(data: &[u8], #[cfg(test)] mod test { - use unstable::finally::Finally; use prelude::*; + use io; use io::{MemReader, MemWriter}; - use io::{io_error, placeholder_error}; struct InitialZeroByteReader { count: int, } impl Reader for InitialZeroByteReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { if self.count == 0 { self.count = 1; - Some(0) + Ok(0) } else { buf[0] = 10; - Some(1) + Ok(1) } } } @@ -149,17 +148,16 @@ mod test { struct EofReader; impl Reader for EofReader { - fn read(&mut self, _: &mut [u8]) -> Option { - None + fn read(&mut self, _: &mut [u8]) -> io::IoResult { + Err(io::standard_error(io::EndOfFile)) } } struct ErroringReader; impl Reader for ErroringReader { - fn read(&mut self, _: &mut [u8]) -> Option { - io_error::cond.raise(placeholder_error()); - None + fn read(&mut self, _: &mut [u8]) -> io::IoResult { + Err(io::standard_error(io::InvalidInput)) } } @@ -168,16 +166,16 @@ mod test { } impl Reader for PartialReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { if self.count == 0 { self.count = 1; buf[0] = 10; buf[1] = 11; - Some(2) + Ok(2) } else { buf[0] = 12; buf[1] = 13; - Some(2) + Ok(2) } } } @@ -187,14 +185,13 @@ mod test { } impl Reader for ErroringLaterReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { if self.count == 0 { self.count = 1; buf[0] = 10; - Some(1) + Ok(1) } else { - io_error::cond.raise(placeholder_error()); - None + Err(io::standard_error(io::InvalidInput)) } } } @@ -204,19 +201,19 @@ mod test { } impl Reader for ThreeChunkReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { if self.count == 0 { self.count = 1; buf[0] = 10; buf[1] = 11; - Some(2) + Ok(2) } else if self.count == 1 { self.count = 2; buf[0] = 12; buf[1] = 13; - Some(2) + Ok(2) } else { - None + Err(io::standard_error(io::EndOfFile)) } } } @@ -225,7 +222,7 @@ mod test { fn read_byte() { let mut reader = MemReader::new(~[10]); let byte = reader.read_byte(); - assert!(byte == Some(10)); + assert!(byte == Ok(10)); } #[test] @@ -234,24 +231,21 @@ mod test { count: 0, }; let byte = reader.read_byte(); - assert!(byte == Some(10)); + assert!(byte == Ok(10)); } #[test] fn read_byte_eof() { let mut reader = EofReader; let byte = reader.read_byte(); - assert!(byte == None); + assert!(byte.is_err()); } #[test] fn read_byte_error() { let mut reader = ErroringReader; - io_error::cond.trap(|_| { - }).inside(|| { - let byte = reader.read_byte(); - assert!(byte == None); - }); + let byte = reader.read_byte(); + assert!(byte.is_err()); } #[test] @@ -267,23 +261,21 @@ mod test { fn bytes_eof() { let mut reader = EofReader; let byte = reader.bytes().next(); - assert!(byte == None); + assert!(byte.is_none()); } #[test] fn bytes_error() { let mut reader = ErroringReader; let mut it = reader.bytes(); - io_error::cond.trap(|_| ()).inside(|| { - let byte = it.next(); - assert!(byte == None); - }) + let byte = it.next(); + assert!(byte.is_none()); } #[test] fn read_bytes() { let mut reader = MemReader::new(~[10, 11, 12, 13]); - let bytes = reader.read_bytes(4); + let bytes = reader.read_bytes(4).unwrap(); assert!(bytes == ~[10, 11, 12, 13]); } @@ -292,24 +284,21 @@ mod test { let mut reader = PartialReader { count: 0, }; - let bytes = reader.read_bytes(4); + let bytes = reader.read_bytes(4).unwrap(); assert!(bytes == ~[10, 11, 12, 13]); } #[test] fn read_bytes_eof() { let mut reader = MemReader::new(~[10, 11]); - io_error::cond.trap(|_| { - }).inside(|| { - assert!(reader.read_bytes(4) == ~[10, 11]); - }) + assert!(reader.read_bytes(4).is_err()); } #[test] fn push_bytes() { let mut reader = MemReader::new(~[10, 11, 12, 13]); let mut buf = ~[8, 9]; - reader.push_bytes(&mut buf, 4); + reader.push_bytes(&mut buf, 4).unwrap(); assert!(buf == ~[8, 9, 10, 11, 12, 13]); } @@ -319,7 +308,7 @@ mod test { count: 0, }; let mut buf = ~[8, 9]; - reader.push_bytes(&mut buf, 4); + reader.push_bytes(&mut buf, 4).unwrap(); assert!(buf == ~[8, 9, 10, 11, 12, 13]); } @@ -327,11 +316,8 @@ mod test { fn push_bytes_eof() { let mut reader = MemReader::new(~[10, 11]); let mut buf = ~[8, 9]; - io_error::cond.trap(|_| { - }).inside(|| { - reader.push_bytes(&mut buf, 4); - assert!(buf == ~[8, 9, 10, 11]); - }) + assert!(reader.push_bytes(&mut buf, 4).is_err()); + assert!(buf == ~[8, 9, 10, 11]); } #[test] @@ -340,38 +326,16 @@ mod test { count: 0, }; let mut buf = ~[8, 9]; - io_error::cond.trap(|_| { } ).inside(|| { - reader.push_bytes(&mut buf, 4); - }); + assert!(reader.push_bytes(&mut buf, 4).is_err()); assert!(buf == ~[8, 9, 10]); } - #[test] - #[should_fail] - #[ignore] // borrow issues with RefCell - fn push_bytes_fail_reset_len() { - // push_bytes unsafely sets the vector length. This is testing that - // upon failure the length is reset correctly. - let _reader = ErroringLaterReader { - count: 0, - }; - // FIXME (#7049): Figure out some other way to do this. - //let buf = RefCell::new(~[8, 9]); - (|| { - //reader.push_bytes(buf.borrow_mut().get(), 4); - }).finally(|| { - // NB: Using rtassert here to trigger abort on failure since this is a should_fail test - // FIXME: #7049 This fails because buf is still borrowed - //rtassert!(buf.borrow().get() == ~[8, 9, 10]); - }) - } - #[test] fn read_to_end() { let mut reader = ThreeChunkReader { count: 0, }; - let buf = reader.read_to_end(); + let buf = reader.read_to_end().unwrap(); assert!(buf == ~[10, 11, 12, 13]); } @@ -381,7 +345,7 @@ mod test { let mut reader = ThreeChunkReader { count: 0, }; - let buf = reader.read_to_end(); + let buf = reader.read_to_end().unwrap(); assert!(buf == ~[10, 11]); } @@ -391,12 +355,12 @@ mod test { let mut writer = MemWriter::new(); for i in uints.iter() { - writer.write_le_u64(*i); + writer.write_le_u64(*i).unwrap(); } let mut reader = MemReader::new(writer.unwrap()); for i in uints.iter() { - assert!(reader.read_le_u64() == *i); + assert!(reader.read_le_u64().unwrap() == *i); } } @@ -407,12 +371,12 @@ mod test { let mut writer = MemWriter::new(); for i in uints.iter() { - writer.write_be_u64(*i); + writer.write_be_u64(*i).unwrap(); } let mut reader = MemReader::new(writer.unwrap()); for i in uints.iter() { - assert!(reader.read_be_u64() == *i); + assert!(reader.read_be_u64().unwrap() == *i); } } @@ -422,14 +386,14 @@ mod test { let mut writer = MemWriter::new(); for i in ints.iter() { - writer.write_be_i32(*i); + writer.write_be_i32(*i).unwrap(); } let mut reader = MemReader::new(writer.unwrap()); for i in ints.iter() { // this tests that the sign extension is working // (comparing the values as i32 would not test this) - assert!(reader.read_be_int_n(4) == *i as i64); + assert!(reader.read_be_int_n(4).unwrap() == *i as i64); } } @@ -439,10 +403,10 @@ mod test { let buf = ~[0x41, 0x02, 0x00, 0x00]; let mut writer = MemWriter::new(); - writer.write(buf); + writer.write(buf).unwrap(); let mut reader = MemReader::new(writer.unwrap()); - let f = reader.read_be_f32(); + let f = reader.read_be_f32().unwrap(); assert!(f == 8.1250); } @@ -451,12 +415,12 @@ mod test { let f:f32 = 8.1250; let mut writer = MemWriter::new(); - writer.write_be_f32(f); - writer.write_le_f32(f); + writer.write_be_f32(f).unwrap(); + writer.write_le_f32(f).unwrap(); let mut reader = MemReader::new(writer.unwrap()); - assert!(reader.read_be_f32() == 8.1250); - assert!(reader.read_le_f32() == 8.1250); + assert!(reader.read_be_f32().unwrap() == 8.1250); + assert!(reader.read_le_f32().unwrap() == 8.1250); } #[test] diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 8904101dd05ed..ef1b1a56ec0e0 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -14,11 +14,11 @@ This module provides a set of functions and traits for working with regular files & directories on a filesystem. At the top-level of the module are a set of freestanding functions, associated -with various filesystem operations. They all operate on a `Path` object. +with various filesystem operations. They all operate on `Path` objects. All operations in this module, including those as part of `File` et al -block the task during execution. Most will raise `std::io::io_error` -conditions in the event of failure. +block the task during execution. In the event of failure, all functions/methods +will return an `IoResult` type with an `Err` value. Also included in this module is an implementation block on the `Path` object defined in `std::path::Path`. The impl adds useful methods about inspecting the @@ -27,21 +27,25 @@ particular bits of it, etc. # Example - use std::io::{File, fs}; +```rust +# #[allow(unused_must_use)]; +use std::io::{File, fs}; - let path = Path::new("foo.txt"); +let path = Path::new("foo.txt"); - // create the file, whether it exists or not - let mut file = File::create(&path); - file.write(bytes!("foobar")); +// create the file, whether it exists or not +let mut file = File::create(&path); +file.write(bytes!("foobar")); +# drop(file); - // open the file in read-only mode - let mut file = File::open(&path); - file.read_to_end(); +// open the file in read-only mode +let mut file = File::open(&path); +file.read_to_end(); - println!("{}", path.stat().size); - fs::symlink(&path, &Path::new("bar.txt")); - fs::unlink(&path); +println!("{}", path.stat().unwrap().size); +# drop(file); +fs::unlink(&path); +``` */ @@ -50,7 +54,7 @@ use clone::Clone; use iter::Iterator; use super::{Reader, Writer, Seek}; use super::{SeekStyle, Read, Write, Open, IoError, Truncate, - FileMode, FileAccess, FileStat, io_error, FilePermission}; + FileMode, FileAccess, FileStat, IoResult, FilePermission}; use rt::rtio::{RtioFileStream, IoFactory, LocalIo}; use io; use option::{Some, None, Option}; @@ -64,11 +68,12 @@ use vec::{OwnedVector, ImmutableVector}; /// Can be constructed via `File::open()`, `File::create()`, and /// `File::open_mode()`. /// -/// # Errors +/// # Error /// -/// This type will raise an io_error condition if operations are attempted against -/// it for which its underlying file descriptor was not configured at creation -/// time, via the `FileAccess` parameter to `File::open_mode()`. +/// This type will return errors as an `IoResult` if operations are +/// attempted against it for which its underlying file descriptor was not +/// configured at creation time, via the `FileAccess` parameter to +/// `File::open_mode()`. pub struct File { priv fd: ~RtioFileStream, priv path: Path, @@ -81,22 +86,19 @@ impl File { /// /// # Example /// - /// use std::io::{File, io_error, Open, ReadWrite}; + /// ```rust,should_fail + /// use std::io::{File, Open, ReadWrite}; /// - /// let p = Path::new("/some/file/path.txt"); + /// let p = Path::new("/some/file/path.txt"); /// - /// io_error::cond.trap(|_| { - /// // hoo-boy... - /// }).inside(|| { - /// let file = match File::open_mode(&p, Open, ReadWrite) { - /// Some(s) => s, - /// None => fail!("whoops! I'm sure this raised, anyways..") - /// }; - /// // do some stuff with that file + /// let file = match File::open_mode(&p, Open, ReadWrite) { + /// Ok(f) => f, + /// Err(e) => fail!("file error: {}", e), + /// }; + /// // do some stuff with that file /// - /// // the file will be closed at the end of this block - /// }) - /// // .. + /// // the file will be closed at the end of this block + /// ``` /// /// `FileMode` and `FileAccess` provide information about the permissions /// context in which a given stream is created. More information about them @@ -106,12 +108,12 @@ impl File { /// /// Note that, with this function, a `File` is returned regardless of the /// access-limitations indicated by `FileAccess` (e.g. calling `write` on a - /// `File` opened as `Read` will raise an `io_error` condition at runtime). + /// `File` opened as `Read` will return an error at runtime). /// - /// # Errors + /// # Error /// - /// This function will raise an `io_error` condition under a number of - /// different circumstances, to include but not limited to: + /// This function will return an error under a number of different + /// circumstances, to include but not limited to: /// /// * Opening a file that does not exist with `Read` access. /// * Attempting to open a file with a `FileAccess` that the user lacks @@ -119,7 +121,7 @@ impl File { /// * Filesystem-level errors (full disk, etc) pub fn open_mode(path: &Path, mode: FileMode, - access: FileAccess) -> Option { + access: FileAccess) -> IoResult { LocalIo::maybe_raise(|io| { io.fs_open(&path.to_c_str(), mode, access).map(|fd| { File { @@ -139,10 +141,12 @@ impl File { /// /// # Example /// - /// use std::io::File; + /// ```rust + /// use std::io::File; /// - /// let contents = File::open(&Path::new("foo.txt")).read_to_end(); - pub fn open(path: &Path) -> Option { + /// let contents = File::open(&Path::new("foo.txt")).read_to_end(); + /// ``` + pub fn open(path: &Path) -> IoResult { File::open_mode(path, Open, Read) } @@ -154,11 +158,16 @@ impl File { /// /// # Example /// - /// use std::io::File; + /// ```rust + /// # #[allow(unused_must_use)]; + /// use std::io::File; /// - /// let mut f = File::create(&Path::new("foo.txt")); - /// f.write(bytes!("This is a sample file")); - pub fn create(path: &Path) -> Option { + /// let mut f = File::create(&Path::new("foo.txt")); + /// f.write(bytes!("This is a sample file")); + /// # drop(f); + /// # ::std::io::fs::unlink(&Path::new("foo.txt")); + /// ``` + pub fn create(path: &Path) -> IoResult { File::open_mode(path, Truncate, Write) } @@ -170,24 +179,16 @@ impl File { /// Synchronizes all modifications to this file to its permanent storage /// device. This will flush any internal buffers necessary to perform this /// operation. - /// - /// # Errors - /// - /// This function will raise on the `io_error` condition on failure. - pub fn fsync(&mut self) { - let _ = self.fd.fsync().map_err(|e| io_error::cond.raise(e)); + pub fn fsync(&mut self) -> IoResult<()> { + self.fd.fsync() } /// This function is similar to `fsync`, except that it may not synchronize /// file metadata to the filesystem. This is intended for use case which /// must synchronize content, but don't need the metadata on disk. The goal /// of this method is to reduce disk operations. - /// - /// # Errors - /// - /// This function will raise on the `io_error` condition on failure. - pub fn datasync(&mut self) { - let _ = self.fd.datasync().map_err(|e| io_error::cond.raise(e)); + pub fn datasync(&mut self) -> IoResult<()> { + self.fd.datasync() } /// Either truncates or extends the underlying file, updating the size of @@ -198,12 +199,8 @@ impl File { /// be shrunk. If it is greater than the current file's size, then the file /// will be extended to `size` and have all of the intermediate data filled /// in with 0s. - /// - /// # Errors - /// - /// On error, this function will raise on the `io_error` condition. - pub fn truncate(&mut self, size: i64) { - let _ = self.fd.truncate(size).map_err(|e| io_error::cond.raise(e)); + pub fn truncate(&mut self, size: i64) -> IoResult<()> { + self.fd.truncate(size) } /// Tests whether this stream has reached EOF. @@ -219,24 +216,25 @@ impl File { /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// let p = Path::new("/some/file/path.txt"); -/// fs::unlink(&p); -/// // if we made it here without failing, then the -/// // unlink operation was successful +/// let p = Path::new("/some/file/path.txt"); +/// fs::unlink(&p); +/// ``` /// /// Note that, just because an unlink call was successful, it is not /// guaranteed that a file is immediately deleted (e.g. depending on /// platform, other open file descriptors may prevent immediate removal) /// -/// # Errors +/// # Error /// -/// This function will raise an `io_error` condition if the path points to a -/// directory, the user lacks permissions to remove the file, or if some -/// other filesystem-level error occurs. -pub fn unlink(path: &Path) { - LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str())); +/// This function will return an error if the path points to a directory, the +/// user lacks permissions to remove the file, or if some other filesystem-level +/// error occurs. +pub fn unlink(path: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_unlink(&path.to_c_str())) } /// Given a path, query the file system to get information about a file, @@ -249,48 +247,25 @@ pub fn unlink(path: &Path) { /// /// # Example /// -/// use std::io; -/// use std::io::fs; +/// ```rust +/// use std::io::fs; /// -/// let p = Path::new("/some/file/path.txt"); -/// match io::result(|| fs::stat(&p)) { -/// Ok(stat) => { /* ... */ } -/// Err(e) => { /* handle error */ } -/// } +/// let p = Path::new("/some/file/path.txt"); +/// match fs::stat(&p) { +/// Ok(stat) => { /* ... */ } +/// Err(e) => { /* handle error */ } +/// } +/// ``` /// -/// # Errors +/// # Error /// -/// This call will raise an `io_error` condition if the user lacks the -/// requisite permissions to perform a `stat` call on the given path or if -/// there is no entry in the filesystem at the provided path. -pub fn stat(path: &Path) -> FileStat { +/// This call will return an error if the user lacks the requisite permissions +/// to perform a `stat` call on the given path or if there is no entry in the +/// filesystem at the provided path. +pub fn stat(path: &Path) -> IoResult { LocalIo::maybe_raise(|io| { io.fs_stat(&path.to_c_str()) - }).unwrap_or_else(dummystat) -} - -fn dummystat() -> FileStat { - FileStat { - path: Path::new(""), - size: 0, - kind: io::TypeFile, - perm: 0, - created: 0, - modified: 0, - accessed: 0, - unstable: io::UnstableFileStat { - device: 0, - inode: 0, - rdev: 0, - nlink: 0, - uid: 0, - gid: 0, - blksize: 0, - blocks: 0, - flags: 0, - gen: 0, - } - } + }) } /// Perform the same operation as the `stat` function, except that this @@ -298,31 +273,33 @@ fn dummystat() -> FileStat { /// information about the symlink file instead of the file that it points /// to. /// -/// # Errors +/// # Error /// /// See `stat` -pub fn lstat(path: &Path) -> FileStat { +pub fn lstat(path: &Path) -> IoResult { LocalIo::maybe_raise(|io| { io.fs_lstat(&path.to_c_str()) - }).unwrap_or_else(dummystat) + }) } /// Rename a file or directory to a new name. /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// fs::rename(&Path::new("foo"), &Path::new("bar")); -/// // Oh boy, nothing was raised! +/// fs::rename(&Path::new("foo"), &Path::new("bar")); +/// ``` /// -/// # Errors +/// # Error /// -/// Will raise an `io_error` condition if the provided `path` doesn't exist, -/// the process lacks permissions to view the contents, or if some other -/// intermittent I/O error occurs. -pub fn rename(from: &Path, to: &Path) { - LocalIo::maybe_raise(|io| io.fs_rename(&from.to_c_str(), &to.to_c_str())); +/// Will return an error if the provided `path` doesn't exist, the process lacks +/// permissions to view the contents, or if some other intermittent I/O error +/// occurs. +pub fn rename(from: &Path, to: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_rename(&from.to_c_str(), &to.to_c_str())) } /// Copies the contents of one file to another. This function will also @@ -333,15 +310,17 @@ pub fn rename(from: &Path, to: &Path) { /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt")); -/// // Oh boy, nothing was raised! +/// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt")); +/// ``` /// -/// # Errors +/// # Error /// -/// Will raise an `io_error` condition is the following situations, but is -/// not limited to just these cases: +/// Will return an error in the following situations, but is not limited to +/// just these cases: /// /// * The `from` path is not a file /// * The `from` file does not exist @@ -351,27 +330,29 @@ pub fn rename(from: &Path, to: &Path) { /// Note that this copy is not atomic in that once the destination is /// ensured to not exist, there is nothing preventing the destination from /// being created and then destroyed by this operation. -pub fn copy(from: &Path, to: &Path) { +pub fn copy(from: &Path, to: &Path) -> IoResult<()> { if !from.is_file() { - return io_error::cond.raise(IoError { + return Err(IoError { kind: io::MismatchedFileTypeForOperation, desc: "the source path is not an existing file", detail: None, - }); + }) } - let mut reader = match File::open(from) { Some(f) => f, None => return }; - let mut writer = match File::create(to) { Some(f) => f, None => return }; + let mut reader = if_ok!(File::open(from)); + let mut writer = if_ok!(File::create(to)); let mut buf = [0, ..io::DEFAULT_BUF_SIZE]; loop { - match reader.read(buf) { - Some(amt) => writer.write(buf.slice_to(amt)), - None => break - } + let amt = match reader.read(buf) { + Ok(n) => n, + Err(ref e) if e.kind == io::EndOfFile => { break } + Err(e) => return Err(e) + }; + if_ok!(writer.write(buf.slice_to(amt))); } - chmod(to, from.stat().perm) + chmod(to, if_ok!(from.stat()).perm) } /// Changes the permission mode bits found on a file or a directory. This @@ -379,61 +360,51 @@ pub fn copy(from: &Path, to: &Path) { /// /// # Example /// -/// use std::io; -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io; +/// use std::io::fs; /// -/// fs::chmod(&Path::new("file.txt"), io::UserFile); -/// fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite); -/// fs::chmod(&Path::new("dir"), io::UserDir); -/// fs::chmod(&Path::new("file.exe"), io::UserExec); +/// fs::chmod(&Path::new("file.txt"), io::UserFile); +/// fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite); +/// fs::chmod(&Path::new("dir"), io::UserDir); +/// fs::chmod(&Path::new("file.exe"), io::UserExec); +/// ``` /// -/// # Errors +/// # Error /// -/// If this function encounters an I/O error, it will raise on the `io_error` -/// condition. Some possible error situations are not having the permission to +/// If this function encounters an I/O error, it will return an `Err` value. +/// Some possible error situations are not having the permission to /// change the attributes of a file or the file not existing. -pub fn chmod(path: &Path, mode: io::FilePermission) { - LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode)); +pub fn chmod(path: &Path, mode: io::FilePermission) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_chmod(&path.to_c_str(), mode)) } /// Change the user and group owners of a file at the specified path. -/// -/// # Errors -/// -/// This function will raise on the `io_error` condition on failure. -pub fn chown(path: &Path, uid: int, gid: int) { - LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid)); +pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_chown(&path.to_c_str(), uid, gid)) } /// Creates a new hard link on the filesystem. The `dst` path will be a /// link pointing to the `src` path. Note that systems often require these /// two paths to both be located on the same filesystem. -/// -/// # Errors -/// -/// This function will raise on the `io_error` condition on failure. -pub fn link(src: &Path, dst: &Path) { - LocalIo::maybe_raise(|io| io.fs_link(&src.to_c_str(), &dst.to_c_str())); +pub fn link(src: &Path, dst: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_link(&src.to_c_str(), &dst.to_c_str())) } /// Creates a new symbolic link on the filesystem. The `dst` path will be a /// symlink pointing to the `src` path. -/// -/// # Errors -/// -/// This function will raise on the `io_error` condition on failure. -pub fn symlink(src: &Path, dst: &Path) { - LocalIo::maybe_raise(|io| io.fs_symlink(&src.to_c_str(), &dst.to_c_str())); +pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_symlink(&src.to_c_str(), &dst.to_c_str())) } /// Reads a symlink, returning the file that the symlink points to. /// -/// # Errors +/// # Error /// -/// This function will raise on the `io_error` condition on failure. Failure -/// conditions include reading a file that does not exist or reading a file -/// which is not a symlink. -pub fn readlink(path: &Path) -> Option { +/// This function will return an error on failure. Failure conditions include +/// reading a file that does not exist or reading a file which is not a symlink. +pub fn readlink(path: &Path) -> IoResult { LocalIo::maybe_raise(|io| io.fs_readlink(&path.to_c_str())) } @@ -441,75 +412,85 @@ pub fn readlink(path: &Path) -> Option { /// /// # Example /// -/// use std::libc::S_IRWXU; -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io; +/// use std::io::fs; /// -/// let p = Path::new("/some/dir"); -/// fs::mkdir(&p, S_IRWXU as int); -/// // If we got here, our directory exists! Hooray! +/// let p = Path::new("/some/dir"); +/// fs::mkdir(&p, io::UserRWX); +/// ``` /// -/// # Errors +/// # Error /// -/// This call will raise an `io_error` condition if the user lacks permissions -/// to make a new directory at the provided path, or if the directory already -/// exists. -pub fn mkdir(path: &Path, mode: FilePermission) { - LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode)); +/// This call will return an error if the user lacks permissions to make a new +/// directory at the provided path, or if the directory already exists. +pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_mkdir(&path.to_c_str(), mode)) } /// Remove an existing, empty directory /// /// # Example /// -/// use std::io::fs; +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::fs; /// -/// let p = Path::new("/some/dir"); -/// fs::rmdir(&p); -/// // good riddance, you mean ol' directory +/// let p = Path::new("/some/dir"); +/// fs::rmdir(&p); +/// ``` /// -/// # Errors +/// # Error /// -/// This call will raise an `io_error` condition if the user lacks permissions -/// to remove the directory at the provided path, or if the directory isn't -/// empty. -pub fn rmdir(path: &Path) { - LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str())); +/// This call will return an error if the user lacks permissions to remove the +/// directory at the provided path, or if the directory isn't empty. +pub fn rmdir(path: &Path) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str())) } /// Retrieve a vector containing all entries within a provided directory /// /// # Example /// -/// use std::io::fs; -/// -/// // one possible implementation of fs::walk_dir only visiting files -/// fn visit_dirs(dir: &Path, cb: |&Path|) { -/// if dir.is_dir() { -/// let contents = fs::readdir(dir).unwrap(); -/// for entry in contents.iter() { -/// if entry.is_dir() { visit_dirs(entry, cb); } -/// else { cb(entry); } +/// ```rust +/// use std::io; +/// use std::io::fs; +/// +/// // one possible implementation of fs::walk_dir only visiting files +/// fn visit_dirs(dir: &Path, cb: |&Path|) -> io::IoResult<()> { +/// if dir.is_dir() { +/// let contents = if_ok!(fs::readdir(dir)); +/// for entry in contents.iter() { +/// if entry.is_dir() { +/// if_ok!(visit_dirs(entry, |p| cb(p))); +/// } else { +/// cb(entry); /// } /// } -/// else { fail!("nope"); } +/// Ok(()) +/// } else { +/// Err(io::standard_error(io::InvalidInput)) /// } +/// } +/// ``` /// -/// # Errors +/// # Error /// -/// Will raise an `io_error` condition if the provided `from` doesn't exist, -/// the process lacks permissions to view the contents or if the `path` points -/// at a non-directory file -pub fn readdir(path: &Path) -> ~[Path] { +/// Will return an error if the provided `from` doesn't exist, the process lacks +/// permissions to view the contents or if the `path` points at a non-directory +/// file +pub fn readdir(path: &Path) -> IoResult<~[Path]> { LocalIo::maybe_raise(|io| { io.fs_readdir(&path.to_c_str(), 0) - }).unwrap_or_else(|| ~[]) + }) } /// Returns an iterator which will recursively walk the directory structure /// rooted at `path`. The path given will not be iterated over, and this will /// perform iteration in a top-down order. -pub fn walk_dir(path: &Path) -> Directories { - Directories { stack: readdir(path) } +pub fn walk_dir(path: &Path) -> IoResult { + Ok(Directories { stack: if_ok!(readdir(path)) }) } /// An iterator which walks over a directory @@ -522,7 +503,10 @@ impl Iterator for Directories { match self.stack.shift() { Some(path) => { if path.is_dir() { - self.stack.push_all_move(readdir(&path)); + match readdir(&path) { + Ok(dirs) => { self.stack.push_all_move(dirs); } + Err(..) => {} + } } Some(path) } @@ -534,19 +518,18 @@ impl Iterator for Directories { /// Recursively create a directory and all of its parent components if they /// are missing. /// -/// # Errors +/// # Error /// -/// This function will raise on the `io_error` condition if an error -/// happens, see `fs::mkdir` for more information about error conditions -/// and performance. -pub fn mkdir_recursive(path: &Path, mode: FilePermission) { +/// This function will return an `Err` value if an error happens, see +/// `fs::mkdir` for more information about error conditions and performance. +pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> { // tjc: if directory exists but with different permissions, // should we return false? if path.is_dir() { - return + return Ok(()) } if path.filename().is_some() { - mkdir_recursive(&path.dir_path(), mode); + if_ok!(mkdir_recursive(&path.dir_path(), mode)); } mkdir(path, mode) } @@ -554,92 +537,64 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) { /// Removes a directory at this path, after removing all its contents. Use /// carefully! /// -/// # Errors +/// # Error /// -/// This function will raise on the `io_error` condition if an error -/// happens. See `file::unlink` and `fs::readdir` for possible error -/// conditions. -pub fn rmdir_recursive(path: &Path) { - let children = readdir(path); +/// This function will return an `Err` value if an error happens. See +/// `file::unlink` and `fs::readdir` for possible error conditions. +pub fn rmdir_recursive(path: &Path) -> IoResult<()> { + let children = if_ok!(readdir(path)); for child in children.iter() { if child.is_dir() { - rmdir_recursive(child); + if_ok!(rmdir_recursive(child)); } else { - unlink(child); + if_ok!(unlink(child)); } } // Directory should now be empty - rmdir(path); + rmdir(path) } /// Changes the timestamps for a file's last modification and access time. /// The file at the path specified will have its last access time set to /// `atime` and its modification time set to `mtime`. The times specified should /// be in milliseconds. -/// -/// # Errors -/// -/// This function will raise on the `io_error` condition if an error -/// happens. // FIXME(#10301) these arguments should not be u64 -pub fn change_file_times(path: &Path, atime: u64, mtime: u64) { - LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime)); +pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> { + LocalIo::maybe_raise(|io| io.fs_utime(&path.to_c_str(), atime, mtime)) } impl Reader for File { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> IoResult { match self.fd.read(buf) { Ok(read) => { self.last_nread = read; match read { - 0 => None, - _ => Some(read as uint) + 0 => Err(io::standard_error(io::EndOfFile)), + _ => Ok(read as uint) } }, - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != io::EndOfFile { - io_error::cond.raise(ioerr); - } - return None; - } + Err(e) => Err(e), } } } impl Writer for File { - fn write(&mut self, buf: &[u8]) { - match self.fd.write(buf) { - Ok(()) => (), - Err(ioerr) => { - io_error::cond.raise(ioerr); - } - } - } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.fd.write(buf) } } impl Seek for File { - fn tell(&self) -> u64 { - let res = self.fd.tell(); - match res { - Ok(cursor) => cursor, - Err(ioerr) => { - io_error::cond.raise(ioerr); - return -1; - } - } + fn tell(&self) -> IoResult { + self.fd.tell() } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { match self.fd.seek(pos, style) { Ok(_) => { // successful seek resets EOF indicator self.last_nread = -1; - () - }, - Err(ioerr) => { - io_error::cond.raise(ioerr); + Ok(()) } + Err(e) => Err(e), } } } @@ -650,17 +605,17 @@ impl path::Path { /// Consult the `file::stat` documentation for more info. /// /// This call preserves identical runtime/error semantics with `file::stat`. - pub fn stat(&self) -> FileStat { stat(self) } + pub fn stat(&self) -> IoResult { stat(self) } /// Boolean value indicator whether the underlying file exists on the local /// filesystem. This will return true if the path points to either a /// directory or a file. /// - /// # Errors + /// # Error /// /// Will not raise a condition pub fn exists(&self) -> bool { - io::result(|| self.stat()).is_ok() + self.stat().is_ok() } /// Whether the underlying implementation (be it a file path, or something @@ -668,11 +623,11 @@ impl path::Path { /// to non-existent locations or directories or other non-regular files /// (named pipes, etc). /// - /// # Errors + /// # Error /// /// Will not raise a condition pub fn is_file(&self) -> bool { - match io::result(|| self.stat()) { + match self.stat() { Ok(s) => s.kind == io::TypeFile, Err(..) => false } @@ -683,11 +638,11 @@ impl path::Path { /// Will return false for paths to non-existent locations or if the item is /// not a directory (eg files, named pipes, links, etc) /// - /// # Errors + /// # Error /// /// Will not raise a condition pub fn is_dir(&self) -> bool { - match io::result(|| self.stat()) { + match self.stat() { Ok(s) => s.kind == io::TypeDirectory, Err(..) => false } @@ -698,8 +653,7 @@ impl path::Path { #[allow(unused_imports)] mod test { use prelude::*; - use io::{SeekSet, SeekCur, SeekEnd, io_error, Read, Open, - ReadWrite}; + use io::{SeekSet, SeekCur, SeekEnd, Read, Open, ReadWrite}; use io; use str; use io::fs::{File, rmdir, mkdir, readdir, rmdir_recursive, @@ -729,7 +683,7 @@ mod test { // Gee, seeing how we're testing the fs module I sure hope that we // at least implement this correctly! let TempDir(ref p) = *self; - io::fs::rmdir_recursive(p); + io::fs::rmdir_recursive(p).unwrap(); } } @@ -737,7 +691,7 @@ mod test { use os; use rand; let ret = os::tmpdir().join(format!("rust-{}", rand::random::())); - io::fs::mkdir(&ret, io::UserRWX); + io::fs::mkdir(&ret, io::UserRWX).unwrap(); TempDir(ret) } @@ -747,7 +701,7 @@ mod test { let filename = &tmpdir.join("file_rt_io_file_test.txt"); { let mut write_stream = File::open_mode(filename, Open, ReadWrite); - write_stream.write(message.as_bytes()); + write_stream.write(message.as_bytes()).unwrap(); } { let mut read_stream = File::open_mode(filename, Open, Read); @@ -758,30 +712,20 @@ mod test { }; assert_eq!(read_str, message.to_owned()); } - unlink(filename); + unlink(filename).unwrap(); }) iotest!(fn invalid_path_raises() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_that_does_not_exist.txt"); - let mut called = false; - io_error::cond.trap(|_| { - called = true; - }).inside(|| { - let result = File::open_mode(filename, Open, Read); - assert!(result.is_none()); - }); - assert!(called); + let result = File::open_mode(filename, Open, Read); + assert!(result.is_err()); }) iotest!(fn file_test_iounlinking_invalid_path_should_raise_condition() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt"); - let mut called = false; - io_error::cond.trap(|_| { - called = true; - }).inside(|| unlink(filename)); - assert!(called); + assert!(unlink(filename).is_err()); }) iotest!(fn file_test_io_non_positional_read() { @@ -791,20 +735,20 @@ mod test { let filename = &tmpdir.join("file_rt_io_file_test_positional.txt"); { let mut rw_stream = File::open_mode(filename, Open, ReadWrite); - rw_stream.write(message.as_bytes()); + rw_stream.write(message.as_bytes()).unwrap(); } { let mut read_stream = File::open_mode(filename, Open, Read); { let read_buf = read_mem.mut_slice(0, 4); - read_stream.read(read_buf); + read_stream.read(read_buf).unwrap(); } { let read_buf = read_mem.mut_slice(4, 8); - read_stream.read(read_buf); + read_stream.read(read_buf).unwrap(); } } - unlink(filename); + unlink(filename).unwrap(); let read_str = str::from_utf8(read_mem).unwrap(); assert_eq!(read_str, message); }) @@ -819,16 +763,16 @@ mod test { let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt"); { let mut rw_stream = File::open_mode(filename, Open, ReadWrite); - rw_stream.write(message.as_bytes()); + rw_stream.write(message.as_bytes()).unwrap(); } { let mut read_stream = File::open_mode(filename, Open, Read); - read_stream.seek(set_cursor as i64, SeekSet); - tell_pos_pre_read = read_stream.tell(); - read_stream.read(read_mem); - tell_pos_post_read = read_stream.tell(); + read_stream.seek(set_cursor as i64, SeekSet).unwrap(); + tell_pos_pre_read = read_stream.tell().unwrap(); + read_stream.read(read_mem).unwrap(); + tell_pos_post_read = read_stream.tell().unwrap(); } - unlink(filename); + unlink(filename).unwrap(); let read_str = str::from_utf8(read_mem).unwrap(); assert_eq!(read_str, message.slice(4, 8)); assert_eq!(tell_pos_pre_read, set_cursor); @@ -845,15 +789,15 @@ mod test { let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt"); { let mut rw_stream = File::open_mode(filename, Open, ReadWrite); - rw_stream.write(initial_msg.as_bytes()); - rw_stream.seek(seek_idx as i64, SeekSet); - rw_stream.write(overwrite_msg.as_bytes()); + rw_stream.write(initial_msg.as_bytes()).unwrap(); + rw_stream.seek(seek_idx as i64, SeekSet).unwrap(); + rw_stream.write(overwrite_msg.as_bytes()).unwrap(); } { let mut read_stream = File::open_mode(filename, Open, Read); - read_stream.read(read_mem); + read_stream.read(read_mem).unwrap(); } - unlink(filename); + unlink(filename).unwrap(); let read_str = str::from_utf8(read_mem).unwrap(); assert!(read_str == final_msg.to_owned()); }) @@ -869,24 +813,24 @@ mod test { let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt"); { let mut rw_stream = File::open_mode(filename, Open, ReadWrite); - rw_stream.write(initial_msg.as_bytes()); + rw_stream.write(initial_msg.as_bytes()).unwrap(); } { let mut read_stream = File::open_mode(filename, Open, Read); - read_stream.seek(-4, SeekEnd); - read_stream.read(read_mem); + read_stream.seek(-4, SeekEnd).unwrap(); + read_stream.read(read_mem).unwrap(); assert_eq!(str::from_utf8(read_mem).unwrap(), chunk_three); - read_stream.seek(-9, SeekCur); - read_stream.read(read_mem); + read_stream.seek(-9, SeekCur).unwrap(); + read_stream.read(read_mem).unwrap(); assert_eq!(str::from_utf8(read_mem).unwrap(), chunk_two); - read_stream.seek(0, SeekSet); - read_stream.read(read_mem); + read_stream.seek(0, SeekSet).unwrap(); + read_stream.read(read_mem).unwrap(); assert_eq!(str::from_utf8(read_mem).unwrap(), chunk_one); } - unlink(filename); + unlink(filename).unwrap(); }) iotest!(fn file_test_stat_is_correct_on_is_file() { @@ -895,36 +839,36 @@ mod test { { let mut fs = File::open_mode(filename, Open, ReadWrite); let msg = "hw"; - fs.write(msg.as_bytes()); + fs.write(msg.as_bytes()).unwrap(); } - let stat_res = stat(filename); + let stat_res = stat(filename).unwrap(); assert_eq!(stat_res.kind, io::TypeFile); - unlink(filename); + unlink(filename).unwrap(); }) iotest!(fn file_test_stat_is_correct_on_is_dir() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_stat_correct_on_is_dir"); - mkdir(filename, io::UserRWX); - let stat_res = filename.stat(); + mkdir(filename, io::UserRWX).unwrap(); + let stat_res = filename.stat().unwrap(); assert!(stat_res.kind == io::TypeDirectory); - rmdir(filename); + rmdir(filename).unwrap(); }) iotest!(fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() { let tmpdir = tmpdir(); let dir = &tmpdir.join("fileinfo_false_on_dir"); - mkdir(dir, io::UserRWX); + mkdir(dir, io::UserRWX).unwrap(); assert!(dir.is_file() == false); - rmdir(dir); + rmdir(dir).unwrap(); }) 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"); - File::create(file).write(bytes!("foo")); + File::create(file).write(bytes!("foo")).unwrap(); assert!(file.exists()); - unlink(file); + unlink(file).unwrap(); assert!(!file.exists()); }) @@ -932,10 +876,10 @@ mod test { let tmpdir = tmpdir(); let dir = &tmpdir.join("before_and_after_dir"); assert!(!dir.exists()); - mkdir(dir, io::UserRWX); + mkdir(dir, io::UserRWX).unwrap(); assert!(dir.exists()); assert!(dir.is_dir()); - rmdir(dir); + rmdir(dir).unwrap(); assert!(!dir.exists()); }) @@ -943,21 +887,21 @@ mod test { use std::str; let tmpdir = tmpdir(); let dir = &tmpdir.join("di_readdir"); - mkdir(dir, io::UserRWX); + mkdir(dir, io::UserRWX).unwrap(); let prefix = "foo"; for n in range(0,3) { let f = dir.join(format!("{}.txt", n)); - let mut w = File::create(&f); + let mut w = File::create(&f).unwrap(); let msg_str = (prefix + n.to_str().to_owned()).to_owned(); let msg = msg_str.as_bytes(); - w.write(msg); + w.write(msg).unwrap(); } - let files = readdir(dir); + let files = readdir(dir).unwrap(); let mut mem = [0u8, .. 4]; for f in files.iter() { { let n = f.filestem_str(); - File::open(f).read(mem); + File::open(f).read(mem).unwrap(); let read_str = str::from_utf8(mem).unwrap(); let expected = match n { None|Some("") => fail!("really shouldn't happen.."), @@ -965,13 +909,13 @@ mod test { }; assert_eq!(expected.as_slice(), read_str); } - unlink(f); + unlink(f).unwrap(); } - rmdir(dir); + rmdir(dir).unwrap(); }) iotest!(fn recursive_mkdir_slash() { - mkdir_recursive(&Path::new("/"), io::UserRWX); + mkdir_recursive(&Path::new("/"), io::UserRWX).unwrap(); }) iotest!(fn unicode_path_is_dir() { @@ -982,12 +926,12 @@ mod test { let mut dirpath = tmpdir.path().clone(); dirpath.push(format!("test-가一ー你好")); - mkdir(&dirpath, io::UserRWX); + mkdir(&dirpath, io::UserRWX).unwrap(); assert!(dirpath.is_dir()); let mut filepath = dirpath; filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs"); - File::create(&filepath); // ignore return; touch only + File::create(&filepath).unwrap(); // ignore return; touch only assert!(!filepath.is_dir()); assert!(filepath.exists()); }) @@ -999,7 +943,7 @@ mod test { let tmpdir = tmpdir(); let unicode = tmpdir.path(); let unicode = unicode.join(format!("test-각丁ー再见")); - mkdir(&unicode, io::UserRWX); + mkdir(&unicode, io::UserRWX).unwrap(); assert!(unicode.exists()); assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists()); }) @@ -1007,7 +951,7 @@ mod test { iotest!(fn copy_file_does_not_exist() { let from = Path::new("test/nonexistent-bogus-path"); let to = Path::new("test/other-bogus-path"); - match io::result(|| copy(&from, &to)) { + match copy(&from, &to) { Ok(..) => fail!(), Err(..) => { assert!(!from.exists()); @@ -1021,20 +965,20 @@ mod test { let input = tmpdir.join("in.txt"); let out = tmpdir.join("out.txt"); - File::create(&input).write(bytes!("hello")); - copy(&input, &out); - let contents = File::open(&out).read_to_end(); + File::create(&input).write(bytes!("hello")).unwrap(); + copy(&input, &out).unwrap(); + let contents = File::open(&out).read_to_end().unwrap(); assert_eq!(contents.as_slice(), bytes!("hello")); - assert_eq!(input.stat().perm, out.stat().perm); + assert_eq!(input.stat().unwrap().perm, out.stat().unwrap().perm); }) iotest!(fn copy_file_dst_dir() { let tmpdir = tmpdir(); let out = tmpdir.join("out"); - File::create(&out); - match io::result(|| copy(&out, tmpdir.path())) { + File::create(&out).unwrap(); + match copy(&out, tmpdir.path()) { Ok(..) => fail!(), Err(..) => {} } }) @@ -1044,11 +988,11 @@ mod test { let input = tmpdir.join("in"); let output = tmpdir.join("out"); - File::create(&input).write("foo".as_bytes()); - File::create(&output).write("bar".as_bytes()); - copy(&input, &output); + File::create(&input).write("foo".as_bytes()).unwrap(); + File::create(&output).write("bar".as_bytes()).unwrap(); + copy(&input, &output).unwrap(); - assert_eq!(File::open(&output).read_to_end(), + assert_eq!(File::open(&output).read_to_end().unwrap(), (bytes!("foo")).to_owned()); }) @@ -1056,7 +1000,7 @@ mod test { let tmpdir = tmpdir(); let out = tmpdir.join("out"); - match io::result(|| copy(tmpdir.path(), &out)) { + match copy(tmpdir.path(), &out) { Ok(..) => fail!(), Err(..) => {} } assert!(!out.exists()); @@ -1067,13 +1011,13 @@ mod test { let input = tmpdir.join("in.txt"); let out = tmpdir.join("out.txt"); - File::create(&input); - chmod(&input, io::UserRead); - copy(&input, &out); - assert!(out.stat().perm & io::UserWrite == 0); + File::create(&input).unwrap(); + chmod(&input, io::UserRead).unwrap(); + copy(&input, &out).unwrap(); + assert!(out.stat().unwrap().perm & io::UserWrite == 0); - chmod(&input, io::UserFile); - chmod(&out, io::UserFile); + chmod(&input, io::UserFile).unwrap(); + chmod(&out, io::UserFile).unwrap(); }) #[cfg(not(windows))] // FIXME(#10264) operation not permitted? @@ -1082,26 +1026,27 @@ mod test { let input = tmpdir.join("in.txt"); let out = tmpdir.join("out.txt"); - File::create(&input).write("foobar".as_bytes()); - symlink(&input, &out); + File::create(&input).write("foobar".as_bytes()).unwrap(); + symlink(&input, &out).unwrap(); if cfg!(not(windows)) { - assert_eq!(lstat(&out).kind, io::TypeSymlink); + assert_eq!(lstat(&out).unwrap().kind, io::TypeSymlink); } - assert_eq!(stat(&out).size, stat(&input).size); - assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned()); + assert_eq!(stat(&out).unwrap().size, stat(&input).unwrap().size); + assert_eq!(File::open(&out).read_to_end().unwrap(), + (bytes!("foobar")).to_owned()); }) #[cfg(not(windows))] // apparently windows doesn't like symlinks iotest!(fn symlink_noexist() { let tmpdir = tmpdir(); // symlinks can point to things that don't exist - symlink(&tmpdir.join("foo"), &tmpdir.join("bar")); + symlink(&tmpdir.join("foo"), &tmpdir.join("bar")).unwrap(); assert!(readlink(&tmpdir.join("bar")).unwrap() == tmpdir.join("foo")); }) iotest!(fn readlink_not_symlink() { let tmpdir = tmpdir(); - match io::result(|| readlink(tmpdir.path())) { + match readlink(tmpdir.path()) { Ok(..) => fail!("wanted a failure"), Err(..) => {} } @@ -1112,22 +1057,23 @@ mod test { let input = tmpdir.join("in.txt"); let out = tmpdir.join("out.txt"); - File::create(&input).write("foobar".as_bytes()); - link(&input, &out); + File::create(&input).write("foobar".as_bytes()).unwrap(); + link(&input, &out).unwrap(); if cfg!(not(windows)) { - assert_eq!(lstat(&out).kind, io::TypeFile); - assert_eq!(stat(&out).unstable.nlink, 2); + assert_eq!(lstat(&out).unwrap().kind, io::TypeFile); + assert_eq!(stat(&out).unwrap().unstable.nlink, 2); } - assert_eq!(stat(&out).size, stat(&input).size); - assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned()); + assert_eq!(stat(&out).unwrap().size, stat(&input).unwrap().size); + assert_eq!(File::open(&out).read_to_end().unwrap(), + (bytes!("foobar")).to_owned()); // can't link to yourself - match io::result(|| link(&input, &input)) { + match link(&input, &input) { Ok(..) => fail!("wanted a failure"), Err(..) => {} } // can't link to something that doesn't exist - match io::result(|| link(&tmpdir.join("foo"), &tmpdir.join("bar"))) { + match link(&tmpdir.join("foo"), &tmpdir.join("bar")) { Ok(..) => fail!("wanted a failure"), Err(..) => {} } @@ -1137,17 +1083,17 @@ mod test { let tmpdir = tmpdir(); let file = tmpdir.join("in.txt"); - File::create(&file); - assert!(stat(&file).perm & io::UserWrite == io::UserWrite); - chmod(&file, io::UserRead); - assert!(stat(&file).perm & io::UserWrite == 0); + File::create(&file).unwrap(); + assert!(stat(&file).unwrap().perm & io::UserWrite == io::UserWrite); + chmod(&file, io::UserRead).unwrap(); + assert!(stat(&file).unwrap().perm & io::UserWrite == 0); - match io::result(|| chmod(&tmpdir.join("foo"), io::UserRWX)) { + match chmod(&tmpdir.join("foo"), io::UserRWX) { Ok(..) => fail!("wanted a failure"), Err(..) => {} } - chmod(&file, io::UserFile); + chmod(&file, io::UserFile).unwrap(); }) iotest!(fn sync_doesnt_kill_anything() { @@ -1155,11 +1101,11 @@ mod test { let path = tmpdir.join("in.txt"); let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap(); - file.fsync(); - file.datasync(); - file.write(bytes!("foo")); - file.fsync(); - file.datasync(); + file.fsync().unwrap(); + file.datasync().unwrap(); + file.write(bytes!("foo")).unwrap(); + file.fsync().unwrap(); + file.datasync().unwrap(); drop(file); }) @@ -1168,28 +1114,28 @@ mod test { let path = tmpdir.join("in.txt"); let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap(); - file.write(bytes!("foo")); - file.fsync(); + file.write(bytes!("foo")).unwrap(); + file.fsync().unwrap(); // Do some simple things with truncation - assert_eq!(stat(&path).size, 3); - file.truncate(10); - assert_eq!(stat(&path).size, 10); - file.write(bytes!("bar")); - file.fsync(); - assert_eq!(stat(&path).size, 10); - assert_eq!(File::open(&path).read_to_end(), + assert_eq!(stat(&path).unwrap().size, 3); + file.truncate(10).unwrap(); + assert_eq!(stat(&path).unwrap().size, 10); + file.write(bytes!("bar")).unwrap(); + file.fsync().unwrap(); + assert_eq!(stat(&path).unwrap().size, 10); + assert_eq!(File::open(&path).read_to_end().unwrap(), (bytes!("foobar", 0, 0, 0, 0)).to_owned()); // 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). - file.truncate(2); - assert_eq!(stat(&path).size, 2); - file.write(bytes!("wut")); - file.fsync(); - assert_eq!(stat(&path).size, 9); - assert_eq!(File::open(&path).read_to_end(), + file.truncate(2).unwrap(); + assert_eq!(stat(&path).unwrap().size, 2); + file.write(bytes!("wut")).unwrap(); + file.fsync().unwrap(); + assert_eq!(stat(&path).unwrap().size, 9); + assert_eq!(File::open(&path).read_to_end().unwrap(), (bytes!("fo", 0, 0, 0, 0, "wut")).to_owned()); drop(file); }) @@ -1197,8 +1143,7 @@ mod test { iotest!(fn open_flavors() { let tmpdir = tmpdir(); - match io::result(|| File::open_mode(&tmpdir.join("a"), io::Open, - io::Read)) { + match File::open_mode(&tmpdir.join("a"), io::Open, io::Read) { Ok(..) => fail!(), Err(..) => {} } File::open_mode(&tmpdir.join("b"), io::Open, io::Write).unwrap(); @@ -1208,46 +1153,46 @@ mod test { File::open_mode(&tmpdir.join("f"), io::Truncate, io::Write).unwrap(); File::open_mode(&tmpdir.join("g"), io::Truncate, io::ReadWrite).unwrap(); - File::create(&tmpdir.join("h")).write("foo".as_bytes()); + File::create(&tmpdir.join("h")).write("foo".as_bytes()).unwrap(); File::open_mode(&tmpdir.join("h"), io::Open, io::Read).unwrap(); { let mut f = File::open_mode(&tmpdir.join("h"), io::Open, io::Read).unwrap(); - match io::result(|| f.write("wut".as_bytes())) { + match f.write("wut".as_bytes()) { Ok(..) => fail!(), Err(..) => {} } } - assert_eq!(stat(&tmpdir.join("h")).size, 3); + assert_eq!(stat(&tmpdir.join("h")).unwrap().size, 3); { let mut f = File::open_mode(&tmpdir.join("h"), io::Append, io::Write).unwrap(); - f.write("bar".as_bytes()); + f.write("bar".as_bytes()).unwrap(); } - assert_eq!(stat(&tmpdir.join("h")).size, 6); + assert_eq!(stat(&tmpdir.join("h")).unwrap().size, 6); { let mut f = File::open_mode(&tmpdir.join("h"), io::Truncate, io::Write).unwrap(); - f.write("bar".as_bytes()); + f.write("bar".as_bytes()).unwrap(); } - assert_eq!(stat(&tmpdir.join("h")).size, 3); + assert_eq!(stat(&tmpdir.join("h")).unwrap().size, 3); }) #[test] fn utime() { let tmpdir = tmpdir(); let path = tmpdir.join("a"); - File::create(&path); + File::create(&path).unwrap(); - change_file_times(&path, 1000, 2000); - assert_eq!(path.stat().accessed, 1000); - assert_eq!(path.stat().modified, 2000); + change_file_times(&path, 1000, 2000).unwrap(); + assert_eq!(path.stat().unwrap().accessed, 1000); + assert_eq!(path.stat().unwrap().modified, 2000); } #[test] fn utime_noexist() { let tmpdir = tmpdir(); - match io::result(|| change_file_times(&tmpdir.join("a"), 100, 200)) { + match change_file_times(&tmpdir.join("a"), 100, 200) { Ok(..) => fail!(), Err(..) => {} } diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index c185951fecac8..395ece17eded6 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -13,9 +13,10 @@ use cmp::max; use cmp::min; use container::Container; -use option::{Option, Some, None}; -use super::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, io_error, - OtherIoError}; +use option::None; +use result::{Err, Ok}; +use io; +use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult}; use vec; use vec::{Vector, ImmutableVector, MutableVector, OwnedCloneableVector}; @@ -24,6 +25,7 @@ use vec::{Vector, ImmutableVector, MutableVector, OwnedCloneableVector}; /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::io::MemWriter; /// /// let mut w = MemWriter::new(); @@ -59,7 +61,7 @@ impl MemWriter { } impl Writer for MemWriter { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { // Make sure the internal buffer is as least as big as where we // currently are let difference = self.pos as i64 - self.buf.len() as i64; @@ -86,14 +88,15 @@ impl Writer for MemWriter { // Bump us forward self.pos += buf.len(); + Ok(()) } } // FIXME(#10432) impl Seek for MemWriter { - fn tell(&self) -> u64 { self.pos as u64 } + fn tell(&self) -> IoResult { Ok(self.pos as u64) } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { // compute offset as signed and clamp to prevent overflow let offset = match style { SeekSet => { 0 } @@ -102,6 +105,7 @@ impl Seek for MemWriter { } as i64; self.pos = max(0, offset+pos) as uint; + Ok(()) } } @@ -110,11 +114,12 @@ impl Seek for MemWriter { /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::io::MemReader; /// /// let mut r = MemReader::new(~[0, 1, 2]); /// -/// assert_eq!(r.read_to_end(), ~[0, 1, 2]); +/// assert_eq!(r.read_to_end().unwrap(), ~[0, 1, 2]); /// ``` pub struct MemReader { priv buf: ~[u8], @@ -148,8 +153,8 @@ impl MemReader { } impl Reader for MemReader { - fn read(&mut self, buf: &mut [u8]) -> Option { - if self.eof() { return None } + fn read(&mut self, buf: &mut [u8]) -> IoResult { + if self.eof() { return Err(io::standard_error(io::EndOfFile)) } let write_len = min(buf.len(), self.buf.len() - self.pos); { @@ -161,28 +166,31 @@ impl Reader for MemReader { self.pos += write_len; assert!(self.pos <= self.buf.len()); - return Some(write_len); + return Ok(write_len); } } impl Seek for MemReader { - fn tell(&self) -> u64 { self.pos as u64 } - fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } + fn tell(&self) -> IoResult { Ok(self.pos as u64) } + fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() } } impl Buffer for MemReader { - fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { + Ok(self.buf.slice_from(self.pos)) + } fn consume(&mut self, amt: uint) { self.pos += amt; } } /// Writes to a fixed-size byte slice /// -/// If a write will not fit in the buffer, it raises the `io_error` -/// condition and does not write any data. +/// If a write will not fit in the buffer, it returns an error and does not +/// write any data. /// /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::io::BufWriter; /// /// let mut buf = [0, ..4]; @@ -207,28 +215,28 @@ impl<'a> BufWriter<'a> { } impl<'a> Writer for BufWriter<'a> { - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { // raises a condition if the entire write does not fit in the buffer let max_size = self.buf.len(); if self.pos >= max_size || (self.pos + buf.len()) > max_size { - io_error::cond.raise(IoError { - kind: OtherIoError, + return Err(IoError { + kind: io::OtherIoError, desc: "Trying to write past end of buffer", detail: None - }); - return; + }) } vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos), buf); self.pos += buf.len(); + Ok(()) } } // FIXME(#10432) impl<'a> Seek for BufWriter<'a> { - fn tell(&self) -> u64 { self.pos as u64 } + fn tell(&self) -> IoResult { Ok(self.pos as u64) } - fn seek(&mut self, pos: i64, style: SeekStyle) { + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { // compute offset as signed and clamp to prevent overflow let offset = match style { SeekSet => { 0 } @@ -237,6 +245,7 @@ impl<'a> Seek for BufWriter<'a> { } as i64; self.pos = max(0, offset+pos) as uint; + Ok(()) } } @@ -246,12 +255,13 @@ impl<'a> Seek for BufWriter<'a> { /// # Example /// /// ```rust +/// # #[allow(unused_must_use)]; /// use std::io::BufReader; /// /// let mut buf = [0, 1, 2, 3]; /// let mut r = BufReader::new(buf); /// -/// assert_eq!(r.read_to_end(), ~[0, 1, 2, 3]); +/// assert_eq!(r.read_to_end().unwrap(), ~[0, 1, 2, 3]); /// ``` pub struct BufReader<'a> { priv buf: &'a [u8], @@ -274,8 +284,8 @@ impl<'a> BufReader<'a> { } impl<'a> Reader for BufReader<'a> { - fn read(&mut self, buf: &mut [u8]) -> Option { - if self.eof() { return None } + fn read(&mut self, buf: &mut [u8]) -> IoResult { + if self.eof() { return Err(io::standard_error(io::EndOfFile)) } let write_len = min(buf.len(), self.buf.len() - self.pos); { @@ -287,18 +297,19 @@ impl<'a> Reader for BufReader<'a> { self.pos += write_len; assert!(self.pos <= self.buf.len()); - return Some(write_len); + return Ok(write_len); } } impl<'a> Seek for BufReader<'a> { - fn tell(&self) -> u64 { self.pos as u64 } - - fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } + fn tell(&self) -> IoResult { Ok(self.pos as u64) } + fn seek(&mut self, _pos: i64, _style: SeekStyle) -> IoResult<()> { fail!() } } impl<'a> Buffer for BufReader<'a> { - fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) } + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { + Ok(self.buf.slice_from(self.pos)) + } fn consume(&mut self, amt: uint) { self.pos += amt; } } @@ -307,33 +318,34 @@ mod test { use prelude::*; use super::*; use io::*; + use io; #[test] fn test_mem_writer() { let mut writer = MemWriter::new(); - assert_eq!(writer.tell(), 0); - writer.write([0]); - assert_eq!(writer.tell(), 1); - writer.write([1, 2, 3]); - writer.write([4, 5, 6, 7]); - assert_eq!(writer.tell(), 8); + assert_eq!(writer.tell(), Ok(0)); + writer.write([0]).unwrap(); + assert_eq!(writer.tell(), Ok(1)); + writer.write([1, 2, 3]).unwrap(); + writer.write([4, 5, 6, 7]).unwrap(); + assert_eq!(writer.tell(), Ok(8)); assert_eq!(writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7]); - writer.seek(0, SeekSet); - assert_eq!(writer.tell(), 0); - writer.write([3, 4]); + writer.seek(0, SeekSet).unwrap(); + assert_eq!(writer.tell(), Ok(0)); + writer.write([3, 4]).unwrap(); assert_eq!(writer.get_ref(), [3, 4, 2, 3, 4, 5, 6, 7]); - writer.seek(1, SeekCur); - writer.write([0, 1]); + writer.seek(1, SeekCur).unwrap(); + writer.write([0, 1]).unwrap(); assert_eq!(writer.get_ref(), [3, 4, 2, 0, 1, 5, 6, 7]); - writer.seek(-1, SeekEnd); - writer.write([1, 2]); + writer.seek(-1, SeekEnd).unwrap(); + writer.write([1, 2]).unwrap(); assert_eq!(writer.get_ref(), [3, 4, 2, 0, 1, 5, 6, 1, 2]); - writer.seek(1, SeekEnd); - writer.write([1]); + writer.seek(1, SeekEnd).unwrap(); + writer.write([1]).unwrap(); assert_eq!(writer.get_ref(), [3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]); } @@ -342,12 +354,12 @@ mod test { let mut buf = [0 as u8, ..8]; { let mut writer = BufWriter::new(buf); - assert_eq!(writer.tell(), 0); - writer.write([0]); - assert_eq!(writer.tell(), 1); - writer.write([1, 2, 3]); - writer.write([4, 5, 6, 7]); - assert_eq!(writer.tell(), 8); + assert_eq!(writer.tell(), Ok(0)); + writer.write([0]).unwrap(); + assert_eq!(writer.tell(), Ok(1)); + writer.write([1, 2, 3]).unwrap(); + writer.write([4, 5, 6, 7]).unwrap(); + assert_eq!(writer.tell(), Ok(8)); } assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7]); } @@ -357,24 +369,24 @@ mod test { let mut buf = [0 as u8, ..8]; { let mut writer = BufWriter::new(buf); - assert_eq!(writer.tell(), 0); - writer.write([1]); - assert_eq!(writer.tell(), 1); + assert_eq!(writer.tell(), Ok(0)); + writer.write([1]).unwrap(); + assert_eq!(writer.tell(), Ok(1)); - writer.seek(2, SeekSet); - assert_eq!(writer.tell(), 2); - writer.write([2]); - assert_eq!(writer.tell(), 3); + writer.seek(2, SeekSet).unwrap(); + assert_eq!(writer.tell(), Ok(2)); + writer.write([2]).unwrap(); + assert_eq!(writer.tell(), Ok(3)); - writer.seek(-2, SeekCur); - assert_eq!(writer.tell(), 1); - writer.write([3]); - assert_eq!(writer.tell(), 2); + writer.seek(-2, SeekCur).unwrap(); + assert_eq!(writer.tell(), Ok(1)); + writer.write([3]).unwrap(); + assert_eq!(writer.tell(), Ok(2)); - writer.seek(-1, SeekEnd); - assert_eq!(writer.tell(), 7); - writer.write([4]); - assert_eq!(writer.tell(), 8); + writer.seek(-1, SeekEnd).unwrap(); + assert_eq!(writer.tell(), Ok(7)); + writer.write([4]).unwrap(); + assert_eq!(writer.tell(), Ok(8)); } assert_eq!(buf, [1, 3, 2, 0, 0, 0, 0, 4]); @@ -384,35 +396,31 @@ mod test { fn test_buf_writer_error() { let mut buf = [0 as u8, ..2]; let mut writer = BufWriter::new(buf); - writer.write([0]); - - let mut called = false; - io_error::cond.trap(|err| { - assert_eq!(err.kind, OtherIoError); - called = true; - }).inside(|| { - writer.write([0, 0]); - }); - assert!(called); + writer.write([0]).unwrap(); + + match writer.write([0, 0]) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::OtherIoError), + } } #[test] fn test_mem_reader() { let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]); let mut buf = []; - assert_eq!(reader.read(buf), Some(0)); - assert_eq!(reader.tell(), 0); + assert_eq!(reader.read(buf), Ok(0)); + assert_eq!(reader.tell(), Ok(0)); let mut buf = [0]; - assert_eq!(reader.read(buf), Some(1)); - assert_eq!(reader.tell(), 1); + assert_eq!(reader.read(buf), Ok(1)); + assert_eq!(reader.tell(), Ok(1)); assert_eq!(buf, [0]); let mut buf = [0, ..4]; - assert_eq!(reader.read(buf), Some(4)); - assert_eq!(reader.tell(), 5); + assert_eq!(reader.read(buf), Ok(4)); + assert_eq!(reader.tell(), Ok(5)); assert_eq!(buf, [1, 2, 3, 4]); - assert_eq!(reader.read(buf), Some(3)); + assert_eq!(reader.read(buf), Ok(3)); assert_eq!(buf.slice(0, 3), [5, 6, 7]); - assert_eq!(reader.read(buf), None); + assert!(reader.read(buf).is_err()); } #[test] @@ -420,64 +428,64 @@ mod test { let in_buf = ~[0, 1, 2, 3, 4, 5, 6, 7]; let mut reader = BufReader::new(in_buf); let mut buf = []; - assert_eq!(reader.read(buf), Some(0)); - assert_eq!(reader.tell(), 0); + assert_eq!(reader.read(buf), Ok(0)); + assert_eq!(reader.tell(), Ok(0)); let mut buf = [0]; - assert_eq!(reader.read(buf), Some(1)); - assert_eq!(reader.tell(), 1); + assert_eq!(reader.read(buf), Ok(1)); + assert_eq!(reader.tell(), Ok(1)); assert_eq!(buf, [0]); let mut buf = [0, ..4]; - assert_eq!(reader.read(buf), Some(4)); - assert_eq!(reader.tell(), 5); + assert_eq!(reader.read(buf), Ok(4)); + assert_eq!(reader.tell(), Ok(5)); assert_eq!(buf, [1, 2, 3, 4]); - assert_eq!(reader.read(buf), Some(3)); + assert_eq!(reader.read(buf), Ok(3)); assert_eq!(buf.slice(0, 3), [5, 6, 7]); - assert_eq!(reader.read(buf), None); + assert!(reader.read(buf).is_err()); } #[test] fn test_read_char() { let b = bytes!("Việt"); let mut r = BufReader::new(b); - assert_eq!(r.read_char(), Some('V')); - assert_eq!(r.read_char(), Some('i')); - assert_eq!(r.read_char(), Some('ệ')); - assert_eq!(r.read_char(), Some('t')); - assert_eq!(r.read_char(), None); + assert_eq!(r.read_char(), Ok('V')); + assert_eq!(r.read_char(), Ok('i')); + assert_eq!(r.read_char(), Ok('ệ')); + assert_eq!(r.read_char(), Ok('t')); + assert!(r.read_char().is_err()); } #[test] fn test_read_bad_char() { let b = bytes!(0x80); let mut r = BufReader::new(b); - assert_eq!(r.read_char(), None); + assert!(r.read_char().is_err()); } #[test] fn test_write_strings() { let mut writer = MemWriter::new(); - writer.write_str("testing"); - writer.write_line("testing"); - writer.write_str("testing"); + writer.write_str("testing").unwrap(); + writer.write_line("testing").unwrap(); + writer.write_str("testing").unwrap(); let mut r = BufReader::new(writer.get_ref()); - assert_eq!(r.read_to_str(), ~"testingtesting\ntesting"); + assert_eq!(r.read_to_str().unwrap(), ~"testingtesting\ntesting"); } #[test] fn test_write_char() { let mut writer = MemWriter::new(); - writer.write_char('a'); - writer.write_char('\n'); - writer.write_char('ệ'); + writer.write_char('a').unwrap(); + writer.write_char('\n').unwrap(); + writer.write_char('ệ').unwrap(); let mut r = BufReader::new(writer.get_ref()); - assert_eq!(r.read_to_str(), ~"a\nệ"); + assert_eq!(r.read_to_str().unwrap(), ~"a\nệ"); } #[test] fn test_read_whole_string_bad() { let buf = [0xff]; let mut r = BufReader::new(buf); - match result(|| r.read_to_str()) { + match r.read_to_str() { Ok(..) => fail!(), Err(..) => {} } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 69f0cf96ffc34..7690c88478fde 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -29,7 +29,6 @@ Some examples of obvious things you might want to do use std::io::BufferedReader; use std::io::stdin; - # let _g = ::std::io::ignore_io_error(); let mut stdin = BufferedReader::new(stdin()); for line in stdin.lines() { print!("{}", line); @@ -41,16 +40,15 @@ Some examples of obvious things you might want to do ```rust use std::io::File; - # let _g = ::std::io::ignore_io_error(); let contents = File::open(&Path::new("message.txt")).read_to_end(); ``` * Write a line to a file ```rust + # #[allow(unused_must_use)]; use std::io::File; - # let _g = ::std::io::ignore_io_error(); let mut file = File::create(&Path::new("message.txt")); file.write(bytes!("hello, file!\n")); # drop(file); @@ -63,7 +61,6 @@ Some examples of obvious things you might want to do use std::io::BufferedReader; use std::io::File; - # let _g = ::std::io::ignore_io_error(); let path = Path::new("message.txt"); let mut file = BufferedReader::new(File::open(&path)); for line in file.lines() { @@ -77,7 +74,6 @@ Some examples of obvious things you might want to do use std::io::BufferedReader; use std::io::File; - # let _g = ::std::io::ignore_io_error(); let path = Path::new("message.txt"); let mut file = BufferedReader::new(File::open(&path)); let lines: ~[~str] = file.lines().collect(); @@ -88,10 +84,10 @@ Some examples of obvious things you might want to do `write_str` and `write_line` methods. ```rust,should_fail + # #[allow(unused_must_use)]; use std::io::net::ip::SocketAddr; use std::io::net::tcp::TcpStream; - # let _g = ::std::io::ignore_io_error(); let addr = from_str::("127.0.0.1:8080").unwrap(); let mut socket = TcpStream::connect(addr).unwrap(); socket.write(bytes!("GET / HTTP/1.0\n\n")); @@ -168,72 +164,51 @@ asynchronous request completes. # Error Handling I/O is an area where nearly every operation can result in unexpected -errors. It should allow errors to be handled efficiently. -It needs to be convenient to use I/O when you don't care -about dealing with specific errors. +errors. Errors should be painfully visible when they happen, and handling them +should be easy to work with. It should be convenient to handle specific I/O +errors, and it should also be convenient to not deal with I/O errors. Rust's I/O employs a combination of techniques to reduce boilerplate while still providing feedback about errors. The basic strategy: -* Errors are fatal by default, resulting in task failure -* Errors raise the `io_error` condition which provides an opportunity to inspect - an IoError object containing details. -* Return values must have a sensible null or zero value which is returned - if a condition is handled successfully. This may be an `Option`, an empty - vector, or other designated error value. -* Common traits are implemented for `Option`, e.g. `impl Reader for Option`, - so that nullable values do not have to be 'unwrapped' before use. +* All I/O operations return `IoResult` which is equivalent to + `Result`. The core `Result` type is defined in the `std::result` + module. +* If the `Result` type goes unused, then the compiler will by default emit a + warning about the unused result. +* Common traits are implemented for `IoResult`, e.g. + `impl Reader for IoResult`, so that error values do not have + 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"))` 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 the task will fail. +encounters an error then the result of the entire expression will +be an error. If you wanted to handle the error though you might write: ```rust +# #[allow(unused_must_use)]; use std::io::File; -use std::io::{IoError, io_error}; -let mut error = None; -io_error::cond.trap(|e: IoError| { - error = Some(e); -}).inside(|| { - File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")); -}); - -if error.is_some() { - println!("failed to write my diary"); +match File::create(&Path::new("diary.txt")).write(bytes!("Met a girl.\n")) { + Ok(()) => { /* succeeded */ } + Err(e) => println!("failed to write to my diary: {}", e), } + # ::std::io::fs::unlink(&Path::new("diary.txt")); ``` -FIXME: Need better condition handling syntax - -In this case the condition handler will have the opportunity to -inspect the IoError raised by either the call to `new` or the call to -`write_line`, but then execution will continue. - -So what actually happens if `new` encounters an error? To understand -that it's important to know that what `new` returns is not a `File` -but an `Option`. If the file does not open, and the condition -is handled, then `new` will simply return `None`. Because there is an -implementation of `Writer` (the trait required ultimately required for -types to implement `write_line`) there is no need to inspect or unwrap -the `Option` and we simply call `write_line` on it. If `new` -returned a `None` then the followup call to `write_line` will also -raise an error. - -## Concerns about this strategy - -This structure will encourage a programming style that is prone -to errors similar to null pointer dereferences. -In particular code written to ignore errors and expect conditions to be unhandled -will start passing around null or zero objects when wrapped in a condition handler. - -* FIXME: How should we use condition handlers that return values? -* FIXME: Should EOF raise default conditions when EOF is not an error? +So what actually happens if `create` encounters an error? +It's important to know that what `new` returns is not a `File` +but an `IoResult`. If the file does not open, then `new` will simply +return `Err(..)`. Because there is an implementation of `Writer` (the trait +required ultimately required for types to implement `write_line`) there is no +need to inspect or unwrap the `IoResult` and we simply call `write_line` +on it. If `new` returned an `Err(..)` then the followup call to `write_line` +will also return an error. # Issues with i/o scheduler affinity, work stealing, task pinning @@ -287,18 +262,19 @@ Out of scope */ #[allow(missing_doc)]; +#[deny(unused_must_use)]; use cast; use char::Char; -use condition::Guard; use container::Container; +use fmt; use int; use iter::Iterator; use option::{Option, Some, None}; use path::Path; use result::{Ok, Err, Result}; -use str; use str::{StrSlice, OwnedStr}; +use str; use to_str::ToStr; use uint; use unstable::finally::Finally; @@ -347,8 +323,8 @@ mod mem; /// Non-blocking access to stdin, stdout, stderr pub mod stdio; -/// Implementations for Option -mod option; +/// Implementations for Result +mod result; /// Extension traits pub mod extensions; @@ -373,17 +349,30 @@ mod comm_adapters; // https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA static DEFAULT_BUF_SIZE: uint = 1024 * 64; +pub type IoResult = Result; + /// The type passed to I/O condition handlers to indicate error /// /// # FIXME /// /// Is something like this sufficient? It's kind of archaic +#[deriving(Eq, Clone)] pub struct IoError { kind: IoErrorKind, desc: &'static str, detail: Option<~str> } +impl fmt::Show for IoError { + fn fmt(err: &IoError, fmt: &mut fmt::Formatter) -> fmt::Result { + if_ok!(fmt.buf.write_str(err.desc)); + match err.detail { + Some(ref s) => write!(fmt.buf, " ({})", *s), + None => Ok(()) + } + } +} + // FIXME: #8242 implementing manually because deriving doesn't work for some reason impl ToStr for IoError { fn to_str(&self) -> ~str { @@ -398,9 +387,8 @@ impl ToStr for IoError { } } -#[deriving(Eq)] +#[deriving(Eq, Clone)] pub enum IoErrorKind { - PreviousIoError, OtherIoError, EndOfFile, FileNotFound, @@ -424,7 +412,6 @@ pub enum IoErrorKind { impl ToStr for IoErrorKind { fn to_str(&self) -> ~str { match *self { - PreviousIoError => ~"PreviousIoError", OtherIoError => ~"OtherIoError", EndOfFile => ~"EndOfFile", FileNotFound => ~"FileNotFound", @@ -446,184 +433,130 @@ impl ToStr for IoErrorKind { } } -// FIXME: Can't put doc comments on macros -// Raised by `I/O` operations on error. -condition! { - pub io_error: IoError -> (); -} - -/// Helper for wrapper calls where you want to -/// ignore any io_errors that might be raised -pub fn ignore_io_error() -> Guard<'static,IoError,()> { - io_error::cond.trap(|_| { - // just swallow the error.. downstream users - // who can make a decision based on a None result - // won't care - }).guard() -} - -/// Helper for catching an I/O error and wrapping it in a Result object. The -/// return result will be the last I/O error that happened or the result of the -/// closure if no error occurred. -pub fn result(cb: || -> T) -> Result { - let mut err = None; - let ret = io_error::cond.trap(|e| { - if err.is_none() { - err = Some(e); - } - }).inside(cb); - match err { - Some(e) => Err(e), - None => Ok(ret), - } -} - pub trait Reader { - // Only two methods which need to get implemented for this trait + // Only method which need to get implemented for this trait /// Read bytes, up to the length of `buf` and place them in `buf`. /// Returns the number of bytes read. The number of bytes read my - /// be less than the number requested, even 0. Returns `None` on EOF. - /// - /// # Failure + /// be less than the number requested, even 0. Returns `Err` on EOF. /// - /// Raises the `io_error` condition on error. If the condition - /// is handled then no guarantee is made about the number of bytes - /// read and the contents of `buf`. If the condition is handled - /// returns `None` (FIXME see below). + /// # Error /// - /// # FIXME - /// - /// * Should raise_default error on eof? - /// * If the condition is handled it should still return the bytes read, - /// in which case there's no need to return Option - but then you *have* - /// to install a handler to detect eof. - /// - /// This doesn't take a `len` argument like the old `read`. - /// Will people often need to slice their vectors to call this - /// and will that be annoying? - /// Is it actually possible for 0 bytes to be read successfully? - fn read(&mut self, buf: &mut [u8]) -> Option; + /// If an error occurs during this I/O operation, then it is returned as + /// `Err(IoError)`. Note that end-of-file is considered an error, and can be + /// inspected for in the error's `kind` field. Also note that reading 0 + /// bytes is not considered an error in all circumstances + fn read(&mut self, buf: &mut [u8]) -> IoResult; // Convenient helper methods based on the above methods - /// Reads a single byte. Returns `None` on EOF. - /// - /// # Failure - /// - /// Raises the same conditions as the `read` method. Returns - /// `None` if the condition is handled. - fn read_byte(&mut self) -> Option { + /// Reads a single byte. Returns `Err` on EOF. + fn read_byte(&mut self) -> IoResult { let mut buf = [0]; - match self.read(buf) { - Some(0) => { - debug!("read 0 bytes. trying again"); - self.read_byte() + loop { + match self.read(buf) { + Ok(0) => { + debug!("read 0 bytes. trying again"); + } + Ok(1) => return Ok(buf[0]), + Ok(_) => unreachable!(), + Err(e) => return Err(e) } - Some(1) => Some(buf[0]), - Some(_) => unreachable!(), - None => None } } /// Reads `len` bytes and appends them to a vector. /// /// May push fewer than the requested number of bytes on error - /// or EOF. Returns true on success, false on EOF or error. - /// - /// # Failure - /// - /// Raises the same conditions as `read`. Additionally raises `io_error` - /// on EOF. If `io_error` is handled then `push_bytes` may push less - /// than the requested number of bytes. - fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) { - unsafe { - let start_len = buf.len(); - let mut total_read = 0; - - buf.reserve_additional(len); - buf.set_len(start_len + len); - - (|| { - while total_read < len { - let len = buf.len(); - let slice = buf.mut_slice(start_len + total_read, len); - match self.read(slice) { - Some(nread) => { - total_read += nread; - } - None => { - io_error::cond.raise(standard_error(EndOfFile)); - break; - } + /// or EOF. If `Ok(())` is returned, then all of the requested bytes were + /// pushed on to the vector, otherwise the amount `len` bytes couldn't be + /// read (an error was encountered), and the error is returned. + fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) -> IoResult<()> { + let start_len = buf.len(); + let mut total_read = 0; + + buf.reserve_additional(len); + unsafe { buf.set_len(start_len + len); } + + (|| { + while total_read < len { + let len = buf.len(); + let slice = buf.mut_slice(start_len + total_read, len); + match self.read(slice) { + Ok(nread) => { + total_read += nread; } + Err(e) => return Err(e) } - }).finally(|| buf.set_len(start_len + total_read)) - } + } + Ok(()) + }).finally(|| unsafe { buf.set_len(start_len + total_read) }) } /// Reads `len` bytes and gives you back a new vector of length `len` /// - /// # Failure + /// # Error /// - /// Raises the same conditions as `read`. Additionally raises `io_error` - /// on EOF. If `io_error` is handled then the returned vector may - /// contain less than the requested number of bytes. - fn read_bytes(&mut self, len: uint) -> ~[u8] { + /// Fails with the same conditions as `read`. Additionally returns error on + /// on EOF. Note that if an error is returned, then some number of bytes may + /// have already been consumed from the underlying reader, and they are lost + /// (not returned as part of the error). If this is unacceptable, then it is + /// recommended to use the `push_bytes` or `read` methods. + fn read_bytes(&mut self, len: uint) -> IoResult<~[u8]> { let mut buf = vec::with_capacity(len); - self.push_bytes(&mut buf, len); - return buf; + match self.push_bytes(&mut buf, len) { + Ok(()) => Ok(buf), + Err(e) => Err(e), + } } /// Reads all remaining bytes from the stream. /// - /// # Failure + /// # Error /// - /// Raises the same conditions as the `read` method except for - /// `EndOfFile` which is swallowed. - fn read_to_end(&mut self) -> ~[u8] { + /// Returns any non-EOF error immediately. Previously read bytes are + /// discarded when an error is returned. + /// + /// When EOF is encountered, all bytes read up to that point are returned. + fn read_to_end(&mut self) -> IoResult<~[u8]> { let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE); - let mut keep_reading = true; - io_error::cond.trap(|e| { - if e.kind == EndOfFile { - keep_reading = false; - } else { - io_error::cond.raise(e) - } - }).inside(|| { - while keep_reading { - self.push_bytes(&mut buf, DEFAULT_BUF_SIZE) + loop { + match self.push_bytes(&mut buf, DEFAULT_BUF_SIZE) { + Ok(()) => {} + Err(ref e) if e.kind == EndOfFile => break, + Err(e) => return Err(e) } - }); - return buf; + } + return Ok(buf); } /// Reads all of the remaining bytes of this stream, interpreting them as a /// UTF-8 encoded stream. The corresponding string is returned. /// - /// # Failure + /// # Error /// - /// This function will raise all the same conditions as the `read` method, - /// along with raising a condition if the input is not valid UTF-8. - fn read_to_str(&mut self) -> ~str { - match str::from_utf8_owned(self.read_to_end()) { - Some(s) => s, - None => { - io_error::cond.raise(standard_error(InvalidInput)); - ~"" + /// This function returns all of the same errors as `read_to_end` with an + /// additional error if the reader's contents are not a valid sequence of + /// UTF-8 bytes. + fn read_to_str(&mut self) -> IoResult<~str> { + self.read_to_end().and_then(|s| { + match str::from_utf8_owned(s) { + Some(s) => Ok(s), + None => Err(standard_error(InvalidInput)), } - } + }) } /// Create an iterator that reads a single byte on /// each iteration, until EOF. /// - /// # Failure + /// # Error /// - /// Raises the same conditions as the `read` method, for - /// each call to its `.next()` method. - /// Ends the iteration if the condition is handled. + /// The iterator protocol causes all specifics about errors encountered to + /// be swallowed. All errors will be signified by returning `None` from the + /// iterator. If this is undesirable, it is recommended to use the + /// `read_byte` method. fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> { extensions::Bytes::new(self) } @@ -633,225 +566,219 @@ pub trait Reader { /// Reads `n` little-endian unsigned integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_le_uint_n(&mut self, nbytes: uint) -> u64 { + fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult { assert!(nbytes > 0 && nbytes <= 8); let mut val = 0u64; let mut pos = 0; let mut i = nbytes; while i > 0 { - val += (self.read_u8() as u64) << pos; + val += (if_ok!(self.read_u8()) as u64) << pos; pos += 8; i -= 1; } - val + Ok(val) } /// Reads `n` little-endian signed integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_le_int_n(&mut self, nbytes: uint) -> i64 { - extend_sign(self.read_le_uint_n(nbytes), nbytes) + fn read_le_int_n(&mut self, nbytes: uint) -> IoResult { + self.read_le_uint_n(nbytes).map(|i| extend_sign(i, nbytes)) } /// Reads `n` big-endian unsigned integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_be_uint_n(&mut self, nbytes: uint) -> u64 { + fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult { assert!(nbytes > 0 && nbytes <= 8); let mut val = 0u64; let mut i = nbytes; while i > 0 { i -= 1; - val += (self.read_u8() as u64) << i * 8; + val += (if_ok!(self.read_u8()) as u64) << i * 8; } - val + Ok(val) } /// Reads `n` big-endian signed integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_be_int_n(&mut self, nbytes: uint) -> i64 { - extend_sign(self.read_be_uint_n(nbytes), nbytes) + fn read_be_int_n(&mut self, nbytes: uint) -> IoResult { + self.read_be_uint_n(nbytes).map(|i| extend_sign(i, nbytes)) } /// Reads a little-endian unsigned integer. /// /// The number of bytes returned is system-dependant. - fn read_le_uint(&mut self) -> uint { - self.read_le_uint_n(uint::BYTES) as uint + fn read_le_uint(&mut self) -> IoResult { + self.read_le_uint_n(uint::BYTES).map(|i| i as uint) } /// Reads a little-endian integer. /// /// The number of bytes returned is system-dependant. - fn read_le_int(&mut self) -> int { - self.read_le_int_n(int::BYTES) as int + fn read_le_int(&mut self) -> IoResult { + self.read_le_int_n(int::BYTES).map(|i| i as int) } /// Reads a big-endian unsigned integer. /// /// The number of bytes returned is system-dependant. - fn read_be_uint(&mut self) -> uint { - self.read_be_uint_n(uint::BYTES) as uint + fn read_be_uint(&mut self) -> IoResult { + self.read_be_uint_n(uint::BYTES).map(|i| i as uint) } /// Reads a big-endian integer. /// /// The number of bytes returned is system-dependant. - fn read_be_int(&mut self) -> int { - self.read_be_int_n(int::BYTES) as int + fn read_be_int(&mut self) -> IoResult { + self.read_be_int_n(int::BYTES).map(|i| i as int) } /// Reads a big-endian `u64`. /// /// `u64`s are 8 bytes long. - fn read_be_u64(&mut self) -> u64 { + fn read_be_u64(&mut self) -> IoResult { self.read_be_uint_n(8) } /// Reads a big-endian `u32`. /// /// `u32`s are 4 bytes long. - fn read_be_u32(&mut self) -> u32 { - self.read_be_uint_n(4) as u32 + fn read_be_u32(&mut self) -> IoResult { + self.read_be_uint_n(4).map(|i| i as u32) } /// Reads a big-endian `u16`. /// /// `u16`s are 2 bytes long. - fn read_be_u16(&mut self) -> u16 { - self.read_be_uint_n(2) as u16 + fn read_be_u16(&mut self) -> IoResult { + self.read_be_uint_n(2).map(|i| i as u16) } /// Reads a big-endian `i64`. /// /// `i64`s are 8 bytes long. - fn read_be_i64(&mut self) -> i64 { + fn read_be_i64(&mut self) -> IoResult { self.read_be_int_n(8) } /// Reads a big-endian `i32`. /// /// `i32`s are 4 bytes long. - fn read_be_i32(&mut self) -> i32 { - self.read_be_int_n(4) as i32 + fn read_be_i32(&mut self) -> IoResult { + self.read_be_int_n(4).map(|i| i as i32) } /// Reads a big-endian `i16`. /// /// `i16`s are 2 bytes long. - fn read_be_i16(&mut self) -> i16 { - self.read_be_int_n(2) as i16 + fn read_be_i16(&mut self) -> IoResult { + self.read_be_int_n(2).map(|i| i as i16) } /// Reads a big-endian `f64`. /// /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - fn read_be_f64(&mut self) -> f64 { - unsafe { - cast::transmute::(self.read_be_u64()) - } + fn read_be_f64(&mut self) -> IoResult { + self.read_be_u64().map(|i| unsafe { + cast::transmute::(i) + }) } /// Reads a big-endian `f32`. /// /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - fn read_be_f32(&mut self) -> f32 { - unsafe { - cast::transmute::(self.read_be_u32()) - } + fn read_be_f32(&mut self) -> IoResult { + self.read_be_u32().map(|i| unsafe { + cast::transmute::(i) + }) } /// Reads a little-endian `u64`. /// /// `u64`s are 8 bytes long. - fn read_le_u64(&mut self) -> u64 { + fn read_le_u64(&mut self) -> IoResult { self.read_le_uint_n(8) } /// Reads a little-endian `u32`. /// /// `u32`s are 4 bytes long. - fn read_le_u32(&mut self) -> u32 { - self.read_le_uint_n(4) as u32 + fn read_le_u32(&mut self) -> IoResult { + self.read_le_uint_n(4).map(|i| i as u32) } /// Reads a little-endian `u16`. /// /// `u16`s are 2 bytes long. - fn read_le_u16(&mut self) -> u16 { - self.read_le_uint_n(2) as u16 + fn read_le_u16(&mut self) -> IoResult { + self.read_le_uint_n(2).map(|i| i as u16) } /// Reads a little-endian `i64`. /// /// `i64`s are 8 bytes long. - fn read_le_i64(&mut self) -> i64 { + fn read_le_i64(&mut self) -> IoResult { self.read_le_int_n(8) } /// Reads a little-endian `i32`. /// /// `i32`s are 4 bytes long. - fn read_le_i32(&mut self) -> i32 { - self.read_le_int_n(4) as i32 + fn read_le_i32(&mut self) -> IoResult { + self.read_le_int_n(4).map(|i| i as i32) } /// Reads a little-endian `i16`. /// /// `i16`s are 2 bytes long. - fn read_le_i16(&mut self) -> i16 { - self.read_le_int_n(2) as i16 + fn read_le_i16(&mut self) -> IoResult { + self.read_le_int_n(2).map(|i| i as i16) } /// Reads a little-endian `f64`. /// /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - fn read_le_f64(&mut self) -> f64 { - unsafe { - cast::transmute::(self.read_le_u64()) - } + fn read_le_f64(&mut self) -> IoResult { + self.read_le_u64().map(|i| unsafe { + cast::transmute::(i) + }) } /// Reads a little-endian `f32`. /// /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - fn read_le_f32(&mut self) -> f32 { - unsafe { - cast::transmute::(self.read_le_u32()) - } + fn read_le_f32(&mut self) -> IoResult { + self.read_le_u32().map(|i| unsafe { + cast::transmute::(i) + }) } /// Read a u8. /// /// `u8`s are 1 byte. - fn read_u8(&mut self) -> u8 { - match self.read_byte() { - Some(b) => b, - None => 0 - } + fn read_u8(&mut self) -> IoResult { + self.read_byte() } /// Read an i8. /// /// `i8`s are 1 byte. - fn read_i8(&mut self) -> i8 { - match self.read_byte() { - Some(b) => b as i8, - None => 0 - } + fn read_i8(&mut self) -> IoResult { + self.read_byte().map(|i| i as i8) } } impl Reader for ~Reader { - fn read(&mut self, buf: &mut [u8]) -> Option { self.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.read(buf) } } impl<'a> Reader for &'a mut Reader { - fn read(&mut self, buf: &mut [u8]) -> Option { self.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.read(buf) } } fn extend_sign(val: u64, nbytes: uint) -> i64 { @@ -860,19 +787,22 @@ fn extend_sign(val: u64, nbytes: uint) -> i64 { } pub trait Writer { - /// Write the given buffer + /// Write the entirety of a given buffer /// - /// # Failure + /// # Errors /// - /// Raises the `io_error` condition on error - fn write(&mut self, buf: &[u8]); + /// If an error happens during the I/O operation, the error is returned as + /// `Err`. Note that it is considered an error if the entire buffer could + /// not be written, and if an error is returned then it is unknown how much + /// data (if any) was actually written. + fn write(&mut self, buf: &[u8]) -> IoResult<()>; /// Flush this output stream, ensuring that all intermediately buffered /// contents reach their destination. /// /// This is by default a no-op and implementers of the `Writer` trait should /// decide whether their stream needs to be buffered or not. - fn flush(&mut self) {} + fn flush(&mut self) -> IoResult<()> { Ok(()) } /// Write a rust string into this sink. /// @@ -880,8 +810,8 @@ pub trait Writer { /// If other encodings are desired, it is recommended to compose this stream /// with another performing the conversion, or to use `write` with a /// converted byte-array instead. - fn write_str(&mut self, s: &str) { - self.write(s.as_bytes()); + fn write_str(&mut self, s: &str) -> IoResult<()> { + self.write(s.as_bytes()) } /// Writes a string into this sink, and then writes a literal newline (`\n`) @@ -891,125 +821,124 @@ pub trait Writer { /// /// If other encodings or line ending flavors are desired, it is recommended /// that the `write` method is used specifically instead. - fn write_line(&mut self, s: &str) { - self.write_str(s); - self.write(['\n' as u8]); + fn write_line(&mut self, s: &str) -> IoResult<()> { + self.write_str(s).and_then(|()| self.write(['\n' as u8])) } /// Write a single char, encoded as UTF-8. - fn write_char(&mut self, c: char) { + fn write_char(&mut self, c: char) -> IoResult<()> { let mut buf = [0u8, ..4]; let n = c.encode_utf8(buf.as_mut_slice()); - self.write(buf.slice_to(n)); + self.write(buf.slice_to(n)) } /// Write the result of passing n through `int::to_str_bytes`. - fn write_int(&mut self, n: int) { + fn write_int(&mut self, n: int) -> IoResult<()> { int::to_str_bytes(n, 10u, |bytes| self.write(bytes)) } /// Write the result of passing n through `uint::to_str_bytes`. - fn write_uint(&mut self, n: uint) { + fn write_uint(&mut self, n: uint) -> IoResult<()> { uint::to_str_bytes(n, 10u, |bytes| self.write(bytes)) } /// Write a little-endian uint (number of bytes depends on system). - fn write_le_uint(&mut self, n: uint) { + fn write_le_uint(&mut self, n: uint) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, uint::BYTES, |v| self.write(v)) } /// Write a little-endian int (number of bytes depends on system). - fn write_le_int(&mut self, n: int) { + fn write_le_int(&mut self, n: int) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, int::BYTES, |v| self.write(v)) } /// Write a big-endian uint (number of bytes depends on system). - fn write_be_uint(&mut self, n: uint) { + fn write_be_uint(&mut self, n: uint) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, uint::BYTES, |v| self.write(v)) } /// Write a big-endian int (number of bytes depends on system). - fn write_be_int(&mut self, n: int) { + fn write_be_int(&mut self, n: int) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, int::BYTES, |v| self.write(v)) } /// Write a big-endian u64 (8 bytes). - fn write_be_u64(&mut self, n: u64) { + fn write_be_u64(&mut self, n: u64) -> IoResult<()> { extensions::u64_to_be_bytes(n, 8u, |v| self.write(v)) } /// Write a big-endian u32 (4 bytes). - fn write_be_u32(&mut self, n: u32) { + fn write_be_u32(&mut self, n: u32) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a big-endian u16 (2 bytes). - fn write_be_u16(&mut self, n: u16) { + fn write_be_u16(&mut self, n: u16) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a big-endian i64 (8 bytes). - fn write_be_i64(&mut self, n: i64) { + fn write_be_i64(&mut self, n: i64) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v)) } /// Write a big-endian i32 (4 bytes). - fn write_be_i32(&mut self, n: i32) { + fn write_be_i32(&mut self, n: i32) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a big-endian i16 (2 bytes). - fn write_be_i16(&mut self, n: i16) { + fn write_be_i16(&mut self, n: i16) -> IoResult<()> { extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a big-endian IEEE754 double-precision floating-point (8 bytes). - fn write_be_f64(&mut self, f: f64) { + fn write_be_f64(&mut self, f: f64) -> IoResult<()> { unsafe { self.write_be_u64(cast::transmute(f)) } } /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). - fn write_be_f32(&mut self, f: f32) { + fn write_be_f32(&mut self, f: f32) -> IoResult<()> { unsafe { self.write_be_u32(cast::transmute(f)) } } /// Write a little-endian u64 (8 bytes). - fn write_le_u64(&mut self, n: u64) { + fn write_le_u64(&mut self, n: u64) -> IoResult<()> { extensions::u64_to_le_bytes(n, 8u, |v| self.write(v)) } /// Write a little-endian u32 (4 bytes). - fn write_le_u32(&mut self, n: u32) { + fn write_le_u32(&mut self, n: u32) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a little-endian u16 (2 bytes). - fn write_le_u16(&mut self, n: u16) { + fn write_le_u16(&mut self, n: u16) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a little-endian i64 (8 bytes). - fn write_le_i64(&mut self, n: i64) { + fn write_le_i64(&mut self, n: i64) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v)) } /// Write a little-endian i32 (4 bytes). - fn write_le_i32(&mut self, n: i32) { + fn write_le_i32(&mut self, n: i32) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v)) } /// Write a little-endian i16 (2 bytes). - fn write_le_i16(&mut self, n: i16) { + fn write_le_i16(&mut self, n: i16) -> IoResult<()> { extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v)) } /// Write a little-endian IEEE754 double-precision floating-point /// (8 bytes). - fn write_le_f64(&mut self, f: f64) { + fn write_le_f64(&mut self, f: f64) -> IoResult<()> { unsafe { self.write_le_u64(cast::transmute(f)) } @@ -1017,31 +946,31 @@ pub trait Writer { /// Write a little-endian IEEE754 single-precision floating-point /// (4 bytes). - fn write_le_f32(&mut self, f: f32) { + fn write_le_f32(&mut self, f: f32) -> IoResult<()> { unsafe { self.write_le_u32(cast::transmute(f)) } } /// Write a u8 (1 byte). - fn write_u8(&mut self, n: u8) { + fn write_u8(&mut self, n: u8) -> IoResult<()> { self.write([n]) } /// Write a i8 (1 byte). - fn write_i8(&mut self, n: i8) { + fn write_i8(&mut self, n: i8) -> IoResult<()> { self.write([n as u8]) } } impl Writer for ~Writer { - fn write(&mut self, buf: &[u8]) { self.write(buf) } - fn flush(&mut self) { self.flush() } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) } + fn flush(&mut self) -> IoResult<()> { self.flush() } } impl<'a> Writer for &'a mut Writer { - fn write(&mut self, buf: &[u8]) { self.write(buf) } - fn flush(&mut self) { self.flush() } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) } + fn flush(&mut self) -> IoResult<()> { self.flush() } } pub trait Stream: Reader + Writer { } @@ -1057,18 +986,18 @@ impl Stream for T {} /// an iteration, but continue to yield elements if iteration /// is attempted again. /// -/// # Failure +/// # Error /// -/// Raises the same conditions as the `read` method except for `EndOfFile` -/// which is swallowed. -/// Iteration yields `None` if the condition is handled. +/// This iterator will swallow all I/O errors, transforming `Err` values to +/// `None`. If errors need to be handled, it is recommended to use the +/// `read_line` method directly. pub struct Lines<'r, T> { priv buffer: &'r mut T, } impl<'r, T: Buffer> Iterator<~str> for Lines<'r, T> { fn next(&mut self) -> Option<~str> { - self.buffer.read_line() + self.buffer.read_line().ok() } } @@ -1085,11 +1014,12 @@ pub trait Buffer: Reader { /// consumed from this buffer returned to ensure that the bytes are never /// returned twice. /// - /// # Failure + /// # Error /// - /// This function will raise on the `io_error` condition if a read error is - /// encountered. - fn fill<'a>(&'a mut self) -> &'a [u8]; + /// This function will return an I/O error if the underlying reader was + /// read, but returned an error. Note that it is not an error to return a + /// 0-length buffer. + fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]>; /// Tells this buffer that `amt` bytes have been consumed from the buffer, /// so they should no longer be returned in calls to `fill` or `read`. @@ -1103,108 +1033,117 @@ pub trait Buffer: Reader { /// /// ```rust /// use std::io::{BufferedReader, stdin}; - /// # let _g = ::std::io::ignore_io_error(); /// /// let mut reader = BufferedReader::new(stdin()); /// - /// let input = reader.read_line().unwrap_or(~"nothing"); + /// let input = reader.read_line().ok().unwrap_or(~"nothing"); /// ``` /// - /// # Failure + /// # Error + /// + /// This function has the same error semantics as `read_until`: + /// + /// * All non-EOF errors will be returned immediately + /// * If an error is returned previously consumed bytes are lost + /// * EOF is only returned if no bytes have been read + /// * Reach EOF may mean that the delimiter is not present in the return + /// value /// - /// This function will raise on the `io_error` condition (except for - /// `EndOfFile` which is swallowed) if a read error is encountered. - /// The task will also fail if sequence of bytes leading up to - /// the newline character are not valid UTF-8. - fn read_line(&mut self) -> Option<~str> { - self.read_until('\n' as u8).map(|line| str::from_utf8_owned(line).unwrap()) + /// Additionally, this function can fail if the line of input read is not a + /// valid UTF-8 sequence of bytes. + fn read_line(&mut self) -> IoResult<~str> { + self.read_until('\n' as u8).and_then(|line| + match str::from_utf8_owned(line) { + Some(s) => Ok(s), + None => Err(standard_error(InvalidInput)), + } + ) } /// Create an iterator that reads a line on each iteration until EOF. /// - /// # Failure + /// # Error /// - /// Iterator raises the same conditions as the `read` method - /// except for `EndOfFile`. + /// This iterator will transform all error values to `None`, discarding the + /// cause of the error. If this is undesirable, it is recommended to call + /// `read_line` directly. fn lines<'r>(&'r mut self) -> Lines<'r, Self> { - Lines { - buffer: self, - } + Lines { buffer: self } } /// Reads a sequence of bytes leading up to a specified delimiter. Once the /// specified byte is encountered, reading ceases and the bytes up to and /// including the delimiter are returned. /// - /// # Failure + /// # Error /// - /// This function will raise on the `io_error` condition if a read error is - /// encountered, except that `EndOfFile` is swallowed. - fn read_until(&mut self, byte: u8) -> Option<~[u8]> { + /// If any I/O error is encountered other than EOF, the error is immediately + /// returned. Note that this may discard bytes which have already been read, + /// and those bytes will *not* be returned. It is recommended to use other + /// methods if this case is worrying. + /// + /// If EOF is encountered, then this function will return EOF if 0 bytes + /// have been read, otherwise the pending byte buffer is returned. This + /// is the reason that the byte buffer returned may not always contain the + /// delimiter. + fn read_until(&mut self, byte: u8) -> IoResult<~[u8]> { let mut res = ~[]; - io_error::cond.trap(|e| { - if e.kind != EndOfFile { - io_error::cond.raise(e); - } - }).inside(|| { - let mut used; - loop { - { - let available = self.fill(); - match available.iter().position(|&b| b == byte) { - Some(i) => { - res.push_all(available.slice_to(i + 1)); - used = i + 1; - break - } - None => { - res.push_all(available); - used = available.len(); - } + let mut used; + loop { + { + let available = match self.fill() { + Ok(n) => n, + Err(ref e) if res.len() > 0 && e.kind == EndOfFile => { + used = 0; + break + } + Err(e) => return Err(e) + }; + match available.iter().position(|&b| b == byte) { + Some(i) => { + res.push_all(available.slice_to(i + 1)); + used = i + 1; + break + } + None => { + res.push_all(available); + used = available.len(); } } - if used == 0 { - break - } - self.consume(used); } self.consume(used); - }); - return if res.len() == 0 {None} else {Some(res)}; - + } + self.consume(used); + Ok(res) } /// Reads the next utf8-encoded character from the underlying stream. /// - /// This will return `None` if the following sequence of bytes in the - /// stream are not a valid utf8-sequence, or if an I/O error is encountered. - /// - /// # Failure - /// - /// This function will raise on the `io_error` condition if a read error is - /// encountered. - fn read_char(&mut self) -> Option { - let width = { - let available = self.fill(); - if available.len() == 0 { return None } // read error - str::utf8_char_width(available[0]) - }; - if width == 0 { return None } // not uf8 - let mut buf = [0, ..4]; + /// # Error + /// + /// If an I/O error occurs, or EOF, then this function will return `Err`. + /// This function will also return error if the stream does not contain a + /// valid utf-8 encoded codepoint as the next few bytes in the stream. + fn read_char(&mut self) -> IoResult { + let first_byte = if_ok!(self.read_byte()); + let width = str::utf8_char_width(first_byte); + if width == 1 { return Ok(first_byte as char) } + if width == 0 { return Err(standard_error(InvalidInput)) } // not utf8 + let mut buf = [first_byte, 0, 0, 0]; { - let mut start = 0; - loop { - match self.read(buf.mut_slice(start, width)) { - Some(n) if n == width - start => break, - Some(n) if n < width - start => { start += n; } - Some(..) | None => return None // read error + let mut start = 1; + while start < width { + match if_ok!(self.read(buf.mut_slice(start, width))) { + n if n == width - start => break, + n if n < width - start => { start += n; } + _ => return Err(standard_error(InvalidInput)), } } } match str::from_utf8(buf.slice_to(width)) { - Some(s) => Some(s.char_at(0)), - None => None + Some(s) => Ok(s.char_at(0)), + None => Err(standard_error(InvalidInput)) } } } @@ -1222,7 +1161,7 @@ pub enum SeekStyle { /// * Are `u64` and `i64` the right choices? pub trait Seek { /// Return position of file cursor in the stream - fn tell(&self) -> u64; + fn tell(&self) -> IoResult; /// Seek to an offset in a stream /// @@ -1231,31 +1170,35 @@ pub trait Seek { /// # FIXME /// /// * What is the behavior when seeking past the end of a stream? - fn seek(&mut self, pos: i64, style: SeekStyle); + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()>; } -/// A listener is a value that can consume itself to start listening for connections. +/// A listener is a value that can consume itself to start listening for +/// connections. +/// /// Doing so produces some sort of Acceptor. pub trait Listener> { /// Spin up the listener and start queuing incoming connections /// - /// # Failure + /// # Error /// - /// Raises `io_error` condition. If the condition is handled, - /// then `listen` returns `None`. - fn listen(self) -> Option
; + /// Returns `Err` if this listener could not be bound to listen for + /// connections. In all cases, this listener is consumed. + fn listen(self) -> IoResult; } /// An acceptor is a value that presents incoming connections pub trait Acceptor { /// Wait for and accept an incoming connection /// - /// # Failure - /// Raise `io_error` condition. If the condition is handled, - /// then `accept` returns `None`. - fn accept(&mut self) -> Option; + /// # Error + /// + /// Returns `Err` if an I/O error is encountered. + fn accept(&mut self) -> IoResult; - /// Create an iterator over incoming connection attempts + /// Create an iterator over incoming connection attempts. + /// + /// Note that I/O errors will be yielded by the iterator itself. fn incoming<'r>(&'r mut self) -> IncomingConnections<'r, Self> { IncomingConnections { inc: self } } @@ -1264,23 +1207,22 @@ pub trait Acceptor { /// An infinite iterator over incoming connection attempts. /// Calling `next` will block the task until a connection is attempted. /// -/// Since connection attempts can continue forever, this iterator always returns Some. -/// The Some contains another Option representing whether the connection attempt was succesful. -/// A successful connection will be wrapped in Some. -/// A failed connection is represented as a None and raises a condition. +/// Since connection attempts can continue forever, this iterator always returns +/// `Some`. The `Some` contains the `IoResult` representing whether the +/// connection attempt was succesful. A successful connection will be wrapped +/// in `Ok`. A failed connection is represented as an `Err`. pub struct IncomingConnections<'a, A> { priv inc: &'a mut A, } -impl<'a, T, A: Acceptor> Iterator> for IncomingConnections<'a, A> { - fn next(&mut self) -> Option> { +impl<'a, T, A: Acceptor> Iterator> for IncomingConnections<'a, A> { + fn next(&mut self) -> Option> { Some(self.inc.accept()) } } pub fn standard_error(kind: IoErrorKind) -> IoError { let desc = match kind { - PreviousIoError => "failing due to previous I/O error", EndOfFile => "end of file", IoUnavailable => "I/O is unavailable", InvalidInput => "invalid input", @@ -1314,7 +1256,7 @@ pub enum FileMode { } /// Access permissions with which the file should be opened. `File`s -/// opened with `Read` will raise an `io_error` condition if written to. +/// opened with `Read` will return an error if written to. pub enum FileAccess { Read, Write, diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 29bf6261a0748..e9ffe97f1c356 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -17,8 +17,9 @@ getaddrinfo() */ -use option::{Option, Some, None}; +use io::IoResult; use io::net::ip::{SocketAddr, IpAddr}; +use option::{Option, Some, None}; use rt::rtio::{IoFactory, LocalIo}; use vec::ImmutableVector; @@ -69,11 +70,7 @@ pub struct Info { /// Easy name resolution. Given a hostname, returns the list of IP addresses for /// that hostname. -/// -/// # Failure -/// -/// On failure, this will raise on the `io_error` condition. -pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> { +pub fn get_host_addresses(host: &str) -> IoResult<~[IpAddr]> { lookup(Some(host), None, None).map(|a| a.map(|i| i.address.ip)) } @@ -87,14 +84,10 @@ pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> { /// * hint - see the hint structure, and "man -s 3 getaddrinfo", for how this /// controls lookup /// -/// # Failure -/// -/// On failure, this will raise on the `io_error` condition. -/// /// FIXME: this is not public because the `Hint` structure is not ready for public /// consumption just yet. fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option) - -> Option<~[Info]> { + -> IoResult<~[Info]> { LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint)) } @@ -115,6 +108,6 @@ mod test { iotest!(fn issue_10663() { // Something should happen here, but this certainly shouldn't cause // everything to die. The actual outcome we don't care too much about. - get_host_addresses("example.com"); + get_host_addresses("example.com").unwrap(); } #[ignore]) } diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 475e3b206f2ac..a0bdc193d980c 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -8,11 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::{Option, Some, None}; -use result::{Ok, Err}; use io::net::ip::SocketAddr; -use io::{Reader, Writer, Listener, Acceptor}; -use io::{io_error, EndOfFile}; +use io::{Reader, Writer, Listener, Acceptor, IoResult}; use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener}; use rt::rtio::{RtioTcpAcceptor, RtioTcpStream}; @@ -25,57 +22,27 @@ impl TcpStream { TcpStream { obj: s } } - pub fn connect(addr: SocketAddr) -> Option { + pub fn connect(addr: SocketAddr) -> IoResult { LocalIo::maybe_raise(|io| { io.tcp_connect(addr).map(TcpStream::new) }) } - pub fn peer_name(&mut self) -> Option { - match self.obj.peer_name() { - Ok(pn) => Some(pn), - Err(ioerr) => { - debug!("failed to get peer name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn peer_name(&mut self) -> IoResult { + self.obj.peer_name() } - pub fn socket_name(&mut self) -> Option { - match self.obj.socket_name() { - Ok(sn) => Some(sn), - Err(ioerr) => { - debug!("failed to get socket name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn socket_name(&mut self) -> IoResult { + self.obj.socket_name() } } impl Reader for TcpStream { - fn read(&mut self, buf: &mut [u8]) -> Option { - match self.obj.read(buf) { - Ok(read) => Some(read), - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != EndOfFile { - io_error::cond.raise(ioerr); - } - return None; - } - } - } + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.obj.read(buf) } } impl Writer for TcpStream { - fn write(&mut self, buf: &[u8]) { - match self.obj.write(buf) { - Ok(_) => (), - Err(ioerr) => io_error::cond.raise(ioerr), - } - } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } pub struct TcpListener { @@ -83,33 +50,20 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(addr: SocketAddr) -> Option { + pub fn bind(addr: SocketAddr) -> IoResult { LocalIo::maybe_raise(|io| { io.tcp_bind(addr).map(|l| TcpListener { obj: l }) }) } - pub fn socket_name(&mut self) -> Option { - match self.obj.socket_name() { - Ok(sn) => Some(sn), - Err(ioerr) => { - debug!("failed to get socket name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn socket_name(&mut self) -> IoResult { + self.obj.socket_name() } } impl Listener for TcpListener { - fn listen(self) -> Option { - match self.obj.listen() { - Ok(acceptor) => Some(TcpAcceptor { obj: acceptor }), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn listen(self) -> IoResult { + self.obj.listen().map(|acceptor| TcpAcceptor { obj: acceptor }) } } @@ -118,14 +72,8 @@ pub struct TcpAcceptor { } impl Acceptor for TcpAcceptor { - fn accept(&mut self) -> Option { - match self.obj.accept() { - Ok(s) => Some(TcpStream::new(s)), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn accept(&mut self) -> IoResult { + self.obj.accept().map(TcpStream::new) } } @@ -138,29 +86,19 @@ mod test { // FIXME #11530 this fails on android because tests are run as root iotest!(fn bind_error() { - let mut called = false; - io_error::cond.trap(|e| { - assert!(e.kind == PermissionDenied); - called = true; - }).inside(|| { - let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; - let listener = TcpListener::bind(addr); - assert!(listener.is_none()); - }); - assert!(called); + let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; + match TcpListener::bind(addr) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, PermissionDenied), + } } #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))]) iotest!(fn connect_error() { - let mut called = false; - io_error::cond.trap(|e| { - assert_eq!(e.kind, ConnectionRefused); - called = true; - }).inside(|| { - let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; - let stream = TcpStream::connect(addr); - assert!(stream.is_none()); - }); - assert!(called); + let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; + match TcpStream::connect(addr) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, ConnectionRefused), + } }) iotest!(fn smoke_test_ip4() { @@ -170,14 +108,14 @@ mod test { spawn(proc() { port.recv(); let mut stream = TcpStream::connect(addr); - stream.write([99]); + stream.write([99]).unwrap(); }); let mut acceptor = TcpListener::bind(addr).listen(); chan.send(()); let mut stream = acceptor.accept(); let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert!(buf[0] == 99); }) @@ -188,14 +126,14 @@ mod test { spawn(proc() { port.recv(); let mut stream = TcpStream::connect(addr); - stream.write([99]); + stream.write([99]).unwrap(); }); let mut acceptor = TcpListener::bind(addr).listen(); chan.send(()); let mut stream = acceptor.accept(); let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert!(buf[0] == 99); }) @@ -214,7 +152,7 @@ mod test { let mut stream = acceptor.accept(); let mut buf = [0]; let nread = stream.read(buf); - assert!(nread.is_none()); + assert!(nread.is_err()); }) iotest!(fn read_eof_ip6() { @@ -232,7 +170,7 @@ mod test { let mut stream = acceptor.accept(); let mut buf = [0]; let nread = stream.read(buf); - assert!(nread.is_none()); + assert!(nread.is_err()); }) iotest!(fn read_eof_twice_ip4() { @@ -250,17 +188,15 @@ mod test { let mut stream = acceptor.accept(); let mut buf = [0]; let nread = stream.read(buf); - assert!(nread.is_none()); - io_error::cond.trap(|e| { - if cfg!(windows) { - assert_eq!(e.kind, NotConnected); - } else { - fail!(); + assert!(nread.is_err()); + + match stream.read(buf) { + Ok(..) => fail!(), + Err(ref e) => { + assert!(e.kind == NotConnected || e.kind == EndOfFile, + "unknown kind: {:?}", e.kind); } - }).inside(|| { - let nread = stream.read(buf); - assert!(nread.is_none()); - }) + } }) iotest!(fn read_eof_twice_ip6() { @@ -278,17 +214,15 @@ mod test { let mut stream = acceptor.accept(); let mut buf = [0]; let nread = stream.read(buf); - assert!(nread.is_none()); - io_error::cond.trap(|e| { - if cfg!(windows) { - assert_eq!(e.kind, NotConnected); - } else { - fail!(); + assert!(nread.is_err()); + + match stream.read(buf) { + Ok(..) => fail!(), + Err(ref e) => { + assert!(e.kind == NotConnected || e.kind == EndOfFile, + "unknown kind: {:?}", e.kind); } - }).inside(|| { - let nread = stream.read(buf); - assert!(nread.is_none()); - }) + } }) iotest!(fn write_close_ip4() { @@ -306,19 +240,16 @@ mod test { let mut stream = acceptor.accept(); let buf = [0]; loop { - let mut stop = false; - io_error::cond.trap(|e| { - // NB: ECONNRESET on linux, EPIPE on mac, ECONNABORTED - // on windows - assert!(e.kind == ConnectionReset || - e.kind == BrokenPipe || - e.kind == ConnectionAborted, - "unknown error: {:?}", e); - stop = true; - }).inside(|| { - stream.write(buf); - }); - if stop { break } + match stream.write(buf) { + Ok(..) => {} + Err(e) => { + assert!(e.kind == ConnectionReset || + e.kind == BrokenPipe || + e.kind == ConnectionAborted, + "unknown error: {:?}", e); + break; + } + } } }) @@ -337,19 +268,16 @@ mod test { let mut stream = acceptor.accept(); let buf = [0]; loop { - let mut stop = false; - io_error::cond.trap(|e| { - // NB: ECONNRESET on linux, EPIPE on mac, ECONNABORTED - // on windows - assert!(e.kind == ConnectionReset || - e.kind == BrokenPipe || - e.kind == ConnectionAborted, - "unknown error: {:?}", e); - stop = true; - }).inside(|| { - stream.write(buf); - }); - if stop { break } + match stream.write(buf) { + Ok(..) => {} + Err(e) => { + assert!(e.kind == ConnectionReset || + e.kind == BrokenPipe || + e.kind == ConnectionAborted, + "unknown error: {:?}", e); + break; + } + } } }) @@ -362,7 +290,7 @@ mod test { port.recv(); for _ in range(0, max) { let mut stream = TcpStream::connect(addr); - stream.write([99]); + stream.write([99]).unwrap(); } }); @@ -370,7 +298,7 @@ mod test { chan.send(()); for ref mut stream in acceptor.incoming().take(max) { let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert_eq!(buf[0], 99); } }) @@ -384,7 +312,7 @@ mod test { port.recv(); for _ in range(0, max) { let mut stream = TcpStream::connect(addr); - stream.write([99]); + stream.write([99]).unwrap(); } }); @@ -392,7 +320,7 @@ mod test { chan.send(()); for ref mut stream in acceptor.incoming().take(max) { let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert_eq!(buf[0], 99); } }) @@ -410,7 +338,7 @@ mod test { spawn(proc() { let mut stream = stream; let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert!(buf[0] == i as u8); debug!("read"); }); @@ -429,7 +357,7 @@ mod test { // Connect again before writing connect(i + 1, addr); debug!("writing"); - stream.write([i as u8]); + stream.write([i as u8]).unwrap(); }); } }) @@ -447,7 +375,7 @@ mod test { spawn(proc() { let mut stream = stream; let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert!(buf[0] == i as u8); debug!("read"); }); @@ -466,7 +394,7 @@ mod test { // Connect again before writing connect(i + 1, addr); debug!("writing"); - stream.write([i as u8]); + stream.write([i as u8]).unwrap(); }); } }) @@ -484,7 +412,7 @@ mod test { spawn(proc() { let mut stream = stream; let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert!(buf[0] == 99); debug!("read"); }); @@ -503,7 +431,7 @@ mod test { // Connect again before writing connect(i + 1, addr); debug!("writing"); - stream.write([99]); + stream.write([99]).unwrap(); }); } }) @@ -521,7 +449,7 @@ mod test { spawn(proc() { let mut stream = stream; let mut buf = [0]; - stream.read(buf); + stream.read(buf).unwrap(); assert!(buf[0] == 99); debug!("read"); }); @@ -540,7 +468,7 @@ mod test { // Connect again before writing connect(i + 1, addr); debug!("writing"); - stream.write([99]); + stream.write([99]).unwrap(); }); } }) @@ -551,7 +479,7 @@ mod test { // Make sure socket_name gives // us the socket we binded to. let so_name = listener.socket_name(); - assert!(so_name.is_some()); + assert!(so_name.is_ok()); assert_eq!(addr, so_name.unwrap()); } @@ -561,20 +489,20 @@ mod test { spawn(proc() { let mut acceptor = TcpListener::bind(addr).listen(); chan.send(()); - acceptor.accept(); + acceptor.accept().unwrap(); }); port.recv(); let stream = TcpStream::connect(addr); - assert!(stream.is_some()); + assert!(stream.is_ok()); let mut stream = stream.unwrap(); // Make sure peer_name gives us the // address/port of the peer we've // connected to. let peer_name = stream.peer_name(); - assert!(peer_name.is_some()); + assert!(peer_name.is_ok()); assert_eq!(addr, peer_name.unwrap()); } @@ -593,37 +521,33 @@ mod test { let addr = next_test_ip4(); let (p, c) = Chan::new(); spawn(proc() { - let mut srv = TcpListener::bind(addr).listen(); + let mut srv = TcpListener::bind(addr).listen().unwrap(); c.send(()); let mut cl = srv.accept().unwrap(); - cl.write([10]); + cl.write([10]).unwrap(); let mut b = [0]; - cl.read(b); + cl.read(b).unwrap(); c.send(()); }); p.recv(); let mut c = TcpStream::connect(addr).unwrap(); let mut b = [0, ..10]; - assert_eq!(c.read(b), Some(1)); - c.write([1]); + assert_eq!(c.read(b), Ok(1)); + c.write([1]).unwrap(); p.recv(); }) iotest!(fn double_bind() { - let mut called = false; - io_error::cond.trap(|e| { - assert!(e.kind == ConnectionRefused || e.kind == OtherIoError); - called = true; - }).inside(|| { - let addr = next_test_ip4(); - let listener = TcpListener::bind(addr).unwrap().listen(); - assert!(listener.is_some()); - let listener2 = TcpListener::bind(addr).and_then(|l| - l.listen()); - assert!(listener2.is_none()); - }); - assert!(called); + let addr = next_test_ip4(); + let listener = TcpListener::bind(addr).unwrap().listen(); + assert!(listener.is_ok()); + match TcpListener::bind(addr).listen() { + Ok(..) => fail!(), + Err(e) => { + assert!(e.kind == ConnectionRefused || e.kind == OtherIoError); + } + } }) iotest!(fn fast_rebind() { @@ -632,7 +556,7 @@ mod test { spawn(proc() { port.recv(); - let _stream = TcpStream::connect(addr); + let _stream = TcpStream::connect(addr).unwrap(); // Close port.recv(); }); @@ -641,7 +565,7 @@ mod test { let mut acceptor = TcpListener::bind(addr).listen(); chan.send(()); { - let _stream = acceptor.accept(); + let _stream = acceptor.accept().unwrap(); // Close client chan.send(()); } diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index 1cf30d469f7aa..0ef62648afcb7 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::{Option, Some, None}; use result::{Ok, Err}; use io::net::ip::SocketAddr; -use io::{Reader, Writer}; -use io::{io_error, EndOfFile}; +use io::{Reader, Writer, IoResult}; use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo}; pub struct UdpSocket { @@ -20,45 +18,26 @@ pub struct UdpSocket { } impl UdpSocket { - pub fn bind(addr: SocketAddr) -> Option { + pub fn bind(addr: SocketAddr) -> IoResult { LocalIo::maybe_raise(|io| { io.udp_bind(addr).map(|s| UdpSocket { obj: s }) }) } - pub fn recvfrom(&mut self, buf: &mut [u8]) -> Option<(uint, SocketAddr)> { - match self.obj.recvfrom(buf) { - Ok((nread, src)) => Some((nread, src)), - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != EndOfFile { - io_error::cond.raise(ioerr); - } - None - } - } + pub fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> { + self.obj.recvfrom(buf) } - pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) { - match self.obj.sendto(buf, dst) { - Ok(_) => (), - Err(ioerr) => io_error::cond.raise(ioerr), - } + pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { + self.obj.sendto(buf, dst) } pub fn connect(self, other: SocketAddr) -> UdpStream { UdpStream { socket: self, connectedTo: other } } - pub fn socket_name(&mut self) -> Option { - match self.obj.socket_name() { - Ok(sn) => Some(sn), - Err(ioerr) => { - debug!("failed to get socket name: {:?}", ioerr); - io_error::cond.raise(ioerr); - None - } - } + pub fn socket_name(&mut self) -> IoResult { + self.obj.socket_name() } } @@ -76,21 +55,21 @@ impl UdpStream { } impl Reader for UdpStream { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let peer = self.connectedTo; self.as_socket(|sock| { match sock.recvfrom(buf) { - Some((_nread, src)) if src != peer => Some(0), - Some((nread, _src)) => Some(nread), - None => None, + Ok((_nread, src)) if src != peer => Ok(0), + Ok((nread, _src)) => Ok(nread), + Err(e) => Err(e), } }) } } impl Writer for UdpStream { - fn write(&mut self, buf: &[u8]) { - self.as_socket(|sock| sock.sendto(buf, self.connectedTo)); + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.as_socket(|sock| sock.sendto(buf, self.connectedTo)) } } @@ -101,16 +80,11 @@ mod test { // FIXME #11530 this fails on android because tests are run as root iotest!(fn bind_error() { - let mut called = false; - io_error::cond.trap(|e| { - assert_eq!(e.kind, PermissionDenied); - called = true; - }).inside(|| { - let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; - let socket = UdpSocket::bind(addr); - assert!(socket.is_none()); - }); - assert!(called); + let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; + match UdpSocket::bind(addr) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, PermissionDenied), + } } #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))]) iotest!(fn socket_smoke_test_ip4() { @@ -121,29 +95,29 @@ mod test { spawn(proc() { match UdpSocket::bind(client_ip) { - Some(ref mut client) => { + Ok(ref mut client) => { port.recv(); - client.sendto([99], server_ip) + client.sendto([99], server_ip).unwrap() } - None => fail!() + Err(..) => fail!() } chan2.send(()); }); match UdpSocket::bind(server_ip) { - Some(ref mut server) => { + Ok(ref mut server) => { chan.send(()); let mut buf = [0]; match server.recvfrom(buf) { - Some((nread, src)) => { + Ok((nread, src)) => { assert_eq!(nread, 1); assert_eq!(buf[0], 99); assert_eq!(src, client_ip); } - None => fail!() + Err(..) => fail!() } } - None => fail!() + Err(..) => fail!() } port2.recv(); }) @@ -155,28 +129,28 @@ mod test { spawn(proc() { match UdpSocket::bind(client_ip) { - Some(ref mut client) => { + Ok(ref mut client) => { port.recv(); - client.sendto([99], server_ip) + client.sendto([99], server_ip).unwrap() } - None => fail!() + Err(..) => fail!() } }); match UdpSocket::bind(server_ip) { - Some(ref mut server) => { + Ok(ref mut server) => { chan.send(()); let mut buf = [0]; match server.recvfrom(buf) { - Some((nread, src)) => { + Ok((nread, src)) => { assert_eq!(nread, 1); assert_eq!(buf[0], 99); assert_eq!(src, client_ip); } - None => fail!() + Err(..) => fail!() } } - None => fail!() + Err(..) => fail!() } }) @@ -188,32 +162,32 @@ mod test { spawn(proc() { match UdpSocket::bind(client_ip) { - Some(client) => { + Ok(client) => { let client = ~client; let mut stream = client.connect(server_ip); port.recv(); - stream.write([99]); + stream.write([99]).unwrap(); } - None => fail!() + Err(..) => fail!() } chan2.send(()); }); match UdpSocket::bind(server_ip) { - Some(server) => { + Ok(server) => { let server = ~server; let mut stream = server.connect(client_ip); chan.send(()); let mut buf = [0]; match stream.read(buf) { - Some(nread) => { + Ok(nread) => { assert_eq!(nread, 1); assert_eq!(buf[0], 99); } - None => fail!() + Err(..) => fail!() } } - None => fail!() + Err(..) => fail!() } port2.recv(); }) @@ -226,32 +200,32 @@ mod test { spawn(proc() { match UdpSocket::bind(client_ip) { - Some(client) => { + Ok(client) => { let client = ~client; let mut stream = client.connect(server_ip); port.recv(); - stream.write([99]); + stream.write([99]).unwrap(); } - None => fail!() + Err(..) => fail!() } chan2.send(()); }); match UdpSocket::bind(server_ip) { - Some(server) => { + Ok(server) => { let server = ~server; let mut stream = server.connect(client_ip); chan.send(()); let mut buf = [0]; match stream.read(buf) { - Some(nread) => { + Ok(nread) => { assert_eq!(nread, 1); assert_eq!(buf[0], 99); } - None => fail!() + Err(..) => fail!() } } - None => fail!() + Err(..) => fail!() } port2.recv(); }) @@ -259,13 +233,13 @@ mod test { pub fn socket_name(addr: SocketAddr) { let server = UdpSocket::bind(addr); - assert!(server.is_some()); + assert!(server.is_ok()); let mut server = server.unwrap(); // Make sure socket_name gives // us the socket we binded to. let so_name = server.socket_name(); - assert!(so_name.is_some()); + assert!(so_name.is_ok()); assert_eq!(addr, so_name.unwrap()); } diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/unix.rs index d470e9bfda108..ce95b987663f7 100644 --- a/src/libstd/io/net/unix.rs +++ b/src/libstd/io/net/unix.rs @@ -28,7 +28,7 @@ use c_str::ToCStr; use rt::rtio::{IoFactory, LocalIo, RtioUnixListener}; use rt::rtio::{RtioUnixAcceptor, RtioPipe}; use io::pipe::PipeStream; -use io::{io_error, Listener, Acceptor, Reader, Writer}; +use io::{Listener, Acceptor, Reader, Writer, IoResult}; /// A stream which communicates over a named pipe. pub struct UnixStream { @@ -45,20 +45,17 @@ impl UnixStream { /// /// The returned stream will be closed when the object falls out of scope. /// - /// # Failure - /// - /// This function will raise on the `io_error` condition if the connection - /// could not be made. - /// /// # Example /// - /// use std::io::net::unix::UnixStream; + /// ```rust + /// # #[allow(unused_must_use)]; + /// use std::io::net::unix::UnixStream; /// - /// let server = Path("path/to/my/socket"); - /// let mut stream = UnixStream::connect(&server); - /// stream.write([1, 2, 3]); - /// - pub fn connect(path: &P) -> Option { + /// let server = Path::new("path/to/my/socket"); + /// let mut stream = UnixStream::connect(&server); + /// stream.write([1, 2, 3]); + /// ``` + pub fn connect(path: &P) -> IoResult { LocalIo::maybe_raise(|io| { io.unix_connect(&path.to_c_str()).map(UnixStream::new) }) @@ -66,11 +63,11 @@ impl UnixStream { } impl Reader for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> Option { self.obj.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.obj.read(buf) } } impl Writer for UnixStream { - fn write(&mut self, buf: &[u8]) { self.obj.write(buf) } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } pub struct UnixListener { @@ -84,23 +81,20 @@ impl UnixListener { /// /// This listener will be closed when it falls out of scope. /// - /// # Failure - /// - /// This function will raise on the `io_error` condition if the specified - /// path could not be bound. - /// /// # Example /// - /// use std::io::net::unix::UnixListener; - /// - /// let server = Path("path/to/my/socket"); - /// let mut stream = UnixListener::bind(&server); - /// for client in stream.incoming() { - /// let mut client = client; - /// client.write([1, 2, 3, 4]); - /// } + /// ``` + /// use std::io::net::unix::UnixListener; + /// use std::io::Listener; /// - pub fn bind(path: &P) -> Option { + /// let server = Path::new("path/to/my/socket"); + /// let mut stream = UnixListener::bind(&server); + /// for client in stream.incoming() { + /// let mut client = client; + /// client.write([1, 2, 3, 4]); + /// } + /// ``` + pub fn bind(path: &P) -> IoResult { LocalIo::maybe_raise(|io| { io.unix_bind(&path.to_c_str()).map(|s| UnixListener { obj: s }) }) @@ -108,14 +102,8 @@ impl UnixListener { } impl Listener for UnixListener { - fn listen(self) -> Option { - match self.obj.listen() { - Ok(acceptor) => Some(UnixAcceptor { obj: acceptor }), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn listen(self) -> IoResult { + self.obj.listen().map(|obj| UnixAcceptor { obj: obj }) } } @@ -124,14 +112,8 @@ pub struct UnixAcceptor { } impl Acceptor for UnixAcceptor { - fn accept(&mut self) -> Option { - match self.obj.accept() { - Ok(s) => Some(UnixStream::new(s)), - Err(ioerr) => { - io_error::cond.raise(ioerr); - None - } - } + fn accept(&mut self) -> IoResult { + self.obj.accept().map(UnixStream::new) } } @@ -159,39 +141,29 @@ mod tests { #[test] fn bind_error() { - let mut called = false; - io_error::cond.trap(|e| { - assert!(e.kind == PermissionDenied); - called = true; - }).inside(|| { - let listener = UnixListener::bind(&("path/to/nowhere")); - assert!(listener.is_none()); - }); - assert!(called); + match UnixListener::bind(&("path/to/nowhere")) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, PermissionDenied), + } } #[test] fn connect_error() { - let mut called = false; - io_error::cond.trap(|e| { - assert_eq!(e.kind, - if cfg!(windows) {OtherIoError} else {FileNotFound}); - called = true; - }).inside(|| { - let stream = UnixStream::connect(&("path/to/nowhere")); - assert!(stream.is_none()); - }); - assert!(called); + match UnixStream::connect(&("path/to/nowhere")) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, + if cfg!(windows) {OtherIoError} else {FileNotFound}) + } } #[test] fn smoke() { smalltest(proc(mut server) { let mut buf = [0]; - server.read(buf); + server.read(buf).unwrap(); assert!(buf[0] == 99); }, proc(mut client) { - client.write([99]); + client.write([99]).unwrap(); }) } @@ -199,8 +171,8 @@ mod tests { fn read_eof() { smalltest(proc(mut server) { let mut buf = [0]; - assert!(server.read(buf).is_none()); - assert!(server.read(buf).is_none()); + assert!(server.read(buf).is_err()); + assert!(server.read(buf).is_err()); }, proc(_client) { // drop the client }) @@ -210,15 +182,15 @@ mod tests { fn write_begone() { smalltest(proc(mut server) { let buf = [0]; - let mut stop = false; - while !stop{ - io_error::cond.trap(|e| { - assert!(e.kind == BrokenPipe || e.kind == NotConnected, - "unknown error {:?}", e); - stop = true; - }).inside(|| { - server.write(buf); - }) + loop { + match server.write(buf) { + Ok(..) => {} + Err(e) => { + assert!(e.kind == BrokenPipe || e.kind == NotConnected, + "unknown error {:?}", e); + break; + } + } } }, proc(_client) { // drop the client @@ -236,7 +208,7 @@ mod tests { port.recv(); for _ in range(0, times) { let mut stream = UnixStream::connect(&path2); - stream.write([100]); + stream.write([100]).unwrap(); } }); @@ -245,7 +217,7 @@ mod tests { for _ in range(0, times) { let mut client = acceptor.accept(); let mut buf = [0]; - client.read(buf); + client.read(buf).unwrap(); assert_eq!(buf[0], 100); } } diff --git a/src/libstd/io/option.rs b/src/libstd/io/option.rs deleted file mode 100644 index e2eec652d9ded..0000000000000 --- a/src/libstd/io/option.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementations of I/O traits for the Option type -//! -//! I/O constructors return option types to allow errors to be handled. -//! These implementations allow e.g. `Option` to be used -//! as a `Reader` without unwrapping the option first. - -use option::*; -use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle}; -use super::{standard_error, PreviousIoError, io_error, IoError}; - -fn prev_io_error() -> IoError { - standard_error(PreviousIoError) -} - -impl Writer for Option { - fn write(&mut self, buf: &[u8]) { - match *self { - Some(ref mut writer) => writer.write(buf), - None => io_error::cond.raise(prev_io_error()) - } - } - - fn flush(&mut self) { - match *self { - Some(ref mut writer) => writer.flush(), - None => io_error::cond.raise(prev_io_error()) - } - } -} - -impl Reader for Option { - fn read(&mut self, buf: &mut [u8]) -> Option { - match *self { - Some(ref mut reader) => reader.read(buf), - None => { - io_error::cond.raise(prev_io_error()); - None - } - } - } -} - -impl Seek for Option { - fn tell(&self) -> u64 { - match *self { - Some(ref seeker) => seeker.tell(), - None => { - io_error::cond.raise(prev_io_error()); - 0 - } - } - } - fn seek(&mut self, pos: i64, style: SeekStyle) { - match *self { - Some(ref mut seeker) => seeker.seek(pos, style), - None => io_error::cond.raise(prev_io_error()) - } - } -} - -impl, L: Listener> Listener for Option { - fn listen(self) -> Option { - match self { - Some(listener) => listener.listen(), - None => { - io_error::cond.raise(prev_io_error()); - None - } - } - } -} - -impl> Acceptor for Option { - fn accept(&mut self) -> Option { - match *self { - Some(ref mut acceptor) => acceptor.accept(), - None => { - io_error::cond.raise(prev_io_error()); - None - } - } - } -} - -#[cfg(test)] -mod test { - use prelude::*; - use super::super::mem::*; - use super::super::{PreviousIoError, io_error}; - - #[test] - fn test_option_writer() { - let mut writer: Option = Some(MemWriter::new()); - writer.write([0, 1, 2]); - writer.flush(); - assert_eq!(writer.unwrap().unwrap(), ~[0, 1, 2]); - } - - #[test] - fn test_option_writer_error() { - let mut writer: Option = None; - - let mut called = false; - io_error::cond.trap(|err| { - assert_eq!(err.kind, PreviousIoError); - called = true; - }).inside(|| { - writer.write([0, 0, 0]); - }); - assert!(called); - - let mut called = false; - io_error::cond.trap(|err| { - assert_eq!(err.kind, PreviousIoError); - called = true; - }).inside(|| { - writer.flush(); - }); - assert!(called); - } - - #[test] - fn test_option_reader() { - let mut reader: Option = Some(MemReader::new(~[0, 1, 2, 3])); - let mut buf = [0, 0]; - reader.read(buf); - assert_eq!(buf, [0, 1]); - } - - #[test] - fn test_option_reader_error() { - let mut reader: Option = None; - let mut buf = []; - - let mut called = false; - io_error::cond.trap(|err| { - assert_eq!(err.kind, PreviousIoError); - called = true; - }).inside(|| { - reader.read(buf); - }); - assert!(called); - } -} diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs index 9919d333f41b4..ca85707149b92 100644 --- a/src/libstd/io/pipe.rs +++ b/src/libstd/io/pipe.rs @@ -14,7 +14,7 @@ //! enough so that pipes can be created to child processes. use prelude::*; -use io::{io_error, EndOfFile}; +use io::IoResult; use libc; use rt::rtio::{RtioPipe, LocalIo}; @@ -32,17 +32,15 @@ impl PipeStream { /// /// # Example /// - /// use std::libc; - /// use std::io::pipe; + /// ```rust + /// # #[allow(unused_must_use)]; + /// use std::libc; + /// use std::io::pipe::PipeStream; /// - /// let mut pipe = PipeStream::open(libc::STDERR_FILENO); - /// pipe.write(bytes!("Hello, stderr!")); - /// - /// # Failure - /// - /// If the pipe cannot be created, an error will be raised on the - /// `io_error` condition. - pub fn open(fd: libc::c_int) -> Option { + /// let mut pipe = PipeStream::open(libc::STDERR_FILENO); + /// pipe.write(bytes!("Hello, stderr!")); + /// ``` + pub fn open(fd: libc::c_int) -> IoResult { LocalIo::maybe_raise(|io| { io.pipe_open(fd).map(|obj| PipeStream { obj: obj }) }) @@ -54,29 +52,11 @@ impl PipeStream { } impl Reader for PipeStream { - fn read(&mut self, buf: &mut [u8]) -> Option { - match self.obj.read(buf) { - Ok(read) => Some(read), - Err(ioerr) => { - // EOF is indicated by returning None - if ioerr.kind != EndOfFile { - io_error::cond.raise(ioerr); - } - return None; - } - } - } + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.obj.read(buf) } } impl Writer for PipeStream { - fn write(&mut self, buf: &[u8]) { - match self.obj.write(buf) { - Ok(_) => (), - Err(ioerr) => { - io_error::cond.raise(ioerr); - } - } - } + fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } #[cfg(test)] @@ -91,12 +71,12 @@ mod test { let (p, c) = Chan::new(); spawn(proc() { let mut out = out; - out.write([10]); + out.write([10]).unwrap(); p.recv(); // don't close the pipe until the other read has finished }); let mut buf = [0, ..10]; - input.read(buf); + input.read(buf).unwrap(); c.send(()); }) } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 6a10f24916f2f..ccf3d4582def4 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -14,7 +14,7 @@ use prelude::*; use libc; use io; -use io::io_error; +use io::IoResult; use rt::rtio::{RtioProcess, IoFactory, LocalIo}; use fmt; @@ -93,7 +93,7 @@ pub enum ProcessExit { impl fmt::Show for ProcessExit { /// Format a ProcessExit enum, to nicely present the information. - fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) { + fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) -> fmt::Result { match *obj { ExitStatus(code) => write!(f.buf, "exit code: {}", code), ExitSignal(code) => write!(f.buf, "signal: {}", code), @@ -118,7 +118,7 @@ impl ProcessExit { impl Process { /// Creates a new pipe initialized, but not bound to any particular /// source/destination - pub fn new(config: ProcessConfig) -> Option { + pub fn new(config: ProcessConfig) -> IoResult { let mut config = Some(config); LocalIo::maybe_raise(|io| { io.spawn(config.take_unwrap()).map(|(p, io)| { @@ -141,14 +141,9 @@ impl Process { /// Note that this is purely a wrapper around libuv's `uv_process_kill` /// function. /// - /// If the signal delivery fails, then the `io_error` condition is raised on - pub fn signal(&mut self, signal: int) { - match self.handle.kill(signal) { - Ok(()) => {} - Err(err) => { - io_error::cond.raise(err) - } - } + /// If the signal delivery fails, the corresponding error is returned. + pub fn signal(&mut self, signal: int) -> IoResult<()> { + self.handle.kill(signal) } /// Wait for the child to exit completely, returning the status that it @@ -176,7 +171,6 @@ impl Drop for Process { mod tests { use io::process::{ProcessConfig, Process}; use prelude::*; - use str; // FIXME(#10380) #[cfg(unix, not(target_os="android"))] @@ -190,7 +184,7 @@ mod tests { io: io, }; let p = Process::new(args); - assert!(p.is_some()); + assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().success()); }) @@ -206,7 +200,7 @@ mod tests { cwd: None, io: io, }; - match io::result(|| Process::new(args)) { + match Process::new(args) { Ok(..) => fail!(), Err(..) => {} } @@ -224,7 +218,7 @@ mod tests { io: io, }; let p = Process::new(args); - assert!(p.is_some()); + assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().matches_exit_status(1)); }) @@ -240,7 +234,7 @@ mod tests { io: io, }; let p = Process::new(args); - assert!(p.is_some()); + assert!(p.is_ok()); let mut p = p.unwrap(); match p.wait() { process::ExitSignal(1) => {}, @@ -249,20 +243,12 @@ mod tests { }) pub fn read_all(input: &mut Reader) -> ~str { - let mut ret = ~""; - let mut buf = [0, ..1024]; - loop { - match input.read(buf) { - None => { break } - Some(n) => { ret.push_str(str::from_utf8(buf.slice_to(n)).unwrap()); } - } - } - return ret; + input.read_to_str().unwrap() } pub fn run_output(args: ProcessConfig) -> ~str { let p = Process::new(args); - assert!(p.is_some()); + assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.io[0].is_none()); assert!(p.io[1].is_some()); @@ -312,8 +298,8 @@ mod tests { cwd: None, io: io, }; - let mut p = Process::new(args).expect("didn't create a proces?!"); - p.io[0].get_mut_ref().write("foobar".as_bytes()); + let mut p = Process::new(args).unwrap(); + p.io[0].get_mut_ref().write("foobar".as_bytes()).unwrap(); p.io[0] = None; // close stdin; let out = read_all(p.io[1].get_mut_ref() as &mut Reader); assert!(p.wait().success()); diff --git a/src/libstd/io/result.rs b/src/libstd/io/result.rs new file mode 100644 index 0000000000000..8e03cffd0fb24 --- /dev/null +++ b/src/libstd/io/result.rs @@ -0,0 +1,128 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Implementations of I/O traits for the IoResult type +//! +//! I/O constructors return option types to allow errors to be handled. +//! These implementations allow e.g. `IoResult` to be used +//! as a `Reader` without unwrapping the result first. + +use clone::Clone; +use result::{Ok, Err}; +use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle, IoResult}; + +impl Writer for IoResult { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + match *self { + Ok(ref mut writer) => writer.write(buf), + Err(ref e) => Err((*e).clone()) + } + } + + fn flush(&mut self) -> IoResult<()> { + match *self { + Ok(ref mut writer) => writer.flush(), + Err(ref e) => Err(e.clone()), + } + } +} + +impl Reader for IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { + match *self { + Ok(ref mut reader) => reader.read(buf), + Err(ref e) => Err(e.clone()), + } + } +} + +impl Seek for IoResult { + fn tell(&self) -> IoResult { + match *self { + Ok(ref seeker) => seeker.tell(), + Err(ref e) => Err(e.clone()), + } + } + fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { + match *self { + Ok(ref mut seeker) => seeker.seek(pos, style), + Err(ref e) => Err(e.clone()) + } + } +} + +impl, L: Listener> Listener for IoResult { + fn listen(self) -> IoResult { + match self { + Ok(listener) => listener.listen(), + Err(e) => Err(e), + } + } +} + +impl> Acceptor for IoResult { + fn accept(&mut self) -> IoResult { + match *self { + Ok(ref mut acceptor) => acceptor.accept(), + Err(ref e) => Err(e.clone()), + } + } +} + +#[cfg(test)] +mod test { + use prelude::*; + use super::super::mem::*; + use io; + + #[test] + fn test_option_writer() { + let mut writer: io::IoResult = Ok(MemWriter::new()); + writer.write([0, 1, 2]).unwrap(); + writer.flush().unwrap(); + assert_eq!(writer.unwrap().unwrap(), ~[0, 1, 2]); + } + + #[test] + fn test_option_writer_error() { + let mut writer: io::IoResult = + Err(io::standard_error(io::EndOfFile)); + + match writer.write([0, 0, 0]) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::EndOfFile), + } + match writer.flush() { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::EndOfFile), + } + } + + #[test] + fn test_option_reader() { + let mut reader: io::IoResult = + Ok(MemReader::new(~[0, 1, 2, 3])); + let mut buf = [0, 0]; + reader.read(buf).unwrap(); + assert_eq!(buf, [0, 1]); + } + + #[test] + fn test_option_reader_error() { + let mut reader: io::IoResult = + Err(io::standard_error(io::EndOfFile)); + let mut buf = []; + + match reader.read(buf) { + Ok(..) => fail!(), + Err(e) => assert_eq!(e.kind, io::EndOfFile), + } + } +} diff --git a/src/libstd/io/signal.rs b/src/libstd/io/signal.rs index 5575e289b59a7..75804c40c5806 100644 --- a/src/libstd/io/signal.rs +++ b/src/libstd/io/signal.rs @@ -20,10 +20,11 @@ definitions for a number of signals. */ use clone::Clone; +use result::{Ok, Err}; use comm::{Port, SharedChan}; use container::{Map, MutableMap}; use hashmap; -use option::{Some, None}; +use io; use rt::rtio::{IoFactory, LocalIo, RtioSignal}; #[repr(int)] @@ -112,23 +113,22 @@ impl Listener { /// a signal, and a later call to `recv` will return the signal that was /// received while no task was waiting on it. /// - /// # Failure + /// # Error /// /// If this function fails to register a signal handler, then an error will - /// be raised on the `io_error` condition and the function will return - /// false. - pub fn register(&mut self, signum: Signum) -> bool { + /// be returned. + pub fn register(&mut self, signum: Signum) -> io::IoResult<()> { if self.handles.contains_key(&signum) { - return true; // self is already listening to signum, so succeed + return Ok(()); // self is already listening to signum, so succeed } match LocalIo::maybe_raise(|io| { io.signal(signum, self.chan.clone()) }) { - Some(handle) => { + Ok(handle) => { self.handles.insert(signum, handle); - true + Ok(()) } - None => false + Err(e) => Err(e) } } @@ -159,7 +159,7 @@ mod test { #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378) fn test_io_signal_smoketest() { let mut signal = Listener::new(); - signal.register(Interrupt); + signal.register(Interrupt).unwrap(); sigint(); timer::sleep(10); match signal.port.recv() { @@ -172,8 +172,8 @@ mod test { fn test_io_signal_two_signal_one_signum() { let mut s1 = Listener::new(); let mut s2 = Listener::new(); - s1.register(Interrupt); - s2.register(Interrupt); + s1.register(Interrupt).unwrap(); + s2.register(Interrupt).unwrap(); sigint(); timer::sleep(10); match s1.port.recv() { @@ -190,8 +190,8 @@ mod test { fn test_io_signal_unregister() { let mut s1 = Listener::new(); let mut s2 = Listener::new(); - s1.register(Interrupt); - s2.register(Interrupt); + s1.register(Interrupt).unwrap(); + s2.register(Interrupt).unwrap(); s2.unregister(Interrupt); sigint(); timer::sleep(10); @@ -203,15 +203,14 @@ mod test { fn test_io_signal_invalid_signum() { use io; use super::User1; + use result::{Ok, Err}; let mut s = Listener::new(); let mut called = false; - io::io_error::cond.trap(|_| { - called = true; - }).inside(|| { - if s.register(User1) { + match s.register(User1) { + Ok(..) => { fail!("Unexpected successful registry of signum {:?}", User1); } - }); - assert!(called); + Err(..) => {} + } } } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index d9fa2a4fc336b..937ad0783e9ab 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -18,6 +18,7 @@ about the stream or terminal that it is attached to. # Example ```rust +# #[allow(unused_must_use)]; use std::io; let mut out = io::stdout(); @@ -28,7 +29,7 @@ out.write(bytes!("Hello, world!")); use container::Container; use fmt; -use io::{Reader, Writer, io_error, IoError, OtherIoError, +use io::{Reader, Writer, IoResult, IoError, OtherIoError, standard_error, EndOfFile, LineBufferedWriter}; use libc; use option::{Option, Some, None}; @@ -114,7 +115,8 @@ fn reset_helper(w: ~Writer, match f(t.get(), w) { Some(mut w) => { drop(t); - w.flush(); + // FIXME: is failing right here? + w.flush().unwrap(); Some(w) } None => None @@ -155,9 +157,9 @@ pub fn set_stderr(stderr: ~Writer) -> Option<~Writer> { // // io1 aliases io2 // }) // }) -fn with_task_stdout(f: |&mut Writer|) { +fn with_task_stdout(f: |&mut Writer| -> IoResult<()> ) { let task: Option<~Task> = Local::try_take(); - match task { + let result = match task { Some(mut task) => { // Printing may run arbitrary code, so ensure that the task is in // TLS to allow all std services. Note that this means a print while @@ -169,7 +171,7 @@ fn with_task_stdout(f: |&mut Writer|) { if my_stdout.is_none() { my_stdout = Some(~LineBufferedWriter::new(stdout()) as ~Writer); } - f(*my_stdout.get_mut_ref()); + let ret = f(*my_stdout.get_mut_ref()); // Note that we need to be careful when putting the stdout handle // back into the task. If the handle was set to `Some` while @@ -184,22 +186,29 @@ fn with_task_stdout(f: |&mut Writer|) { let prev = util::replace(&mut t.get().stdout, my_stdout); drop(t); drop(prev); + ret } None => { struct Stdout; impl Writer for Stdout { - fn write(&mut self, data: &[u8]) { + fn write(&mut self, data: &[u8]) -> IoResult<()> { unsafe { libc::write(libc::STDOUT_FILENO, data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } + Ok(()) // just ignore the results } } let mut io = Stdout; - f(&mut io as &mut Writer); + f(&mut io as &mut Writer) } + }; + + match result { + Ok(()) => {} + Err(e) => fail!("failed printing to stdout: {}", e), } } @@ -226,8 +235,7 @@ pub fn print(s: &str) { /// `\n` character is printed to the console after the string. pub fn println(s: &str) { with_task_stdout(|io| { - io.write(s.as_bytes()); - io.write(['\n' as u8]); + io.write(s.as_bytes()).and_then(|()| io.write(['\n' as u8])) }) } @@ -249,7 +257,7 @@ pub struct StdReader { } impl Reader for StdReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let ret = match self.inner { TTY(ref mut tty) => tty.read(buf), File(ref mut file) => file.read(buf).map(|i| i as uint), @@ -260,15 +268,8 @@ impl Reader for StdReader { // return an actual EOF error, but apparently for stdin it's a // little different. Hence, here we convert a 0 length read to an // end-of-file indicator so the caller knows to stop reading. - Ok(0) => { - io_error::cond.raise(standard_error(EndOfFile)); - None - } - Ok(amt) => Some(amt), - Err(e) => { - io_error::cond.raise(e); - None - } + Ok(0) => { Err(standard_error(EndOfFile)) } + ret @ Ok(..) | ret @ Err(..) => ret, } } } @@ -283,30 +284,21 @@ impl StdWriter { /// when the writer is attached to something like a terminal, this is used /// to fetch the dimensions of the terminal. /// - /// If successful, returns Some((width, height)). + /// If successful, returns `Ok((width, height))`. /// - /// # Failure + /// # Error /// - /// This function will raise on the `io_error` condition if an error - /// happens. - pub fn winsize(&mut self) -> Option<(int, int)> { + /// This function will return an error if the output stream is not actually + /// connected to a TTY instance, or if querying the TTY instance fails. + pub fn winsize(&mut self) -> IoResult<(int, int)> { match self.inner { - TTY(ref mut tty) => { - match tty.get_winsize() { - Ok(p) => Some(p), - Err(e) => { - io_error::cond.raise(e); - None - } - } - } + TTY(ref mut tty) => tty.get_winsize(), File(..) => { - io_error::cond.raise(IoError { + Err(IoError { kind: OtherIoError, desc: "stream is not a tty", detail: None, - }); - None + }) } } } @@ -314,24 +306,19 @@ impl StdWriter { /// Controls whether this output stream is a "raw stream" or simply a normal /// stream. /// - /// # Failure + /// # Error /// - /// This function will raise on the `io_error` condition if an error - /// happens. - pub fn set_raw(&mut self, raw: bool) { + /// This function will return an error if the output stream is not actually + /// connected to a TTY instance, or if querying the TTY instance fails. + pub fn set_raw(&mut self, raw: bool) -> IoResult<()> { match self.inner { - TTY(ref mut tty) => { - match tty.set_raw(raw) { - Ok(()) => {}, - Err(e) => io_error::cond.raise(e), - } - } + TTY(ref mut tty) => tty.set_raw(raw), File(..) => { - io_error::cond.raise(IoError { + Err(IoError { kind: OtherIoError, desc: "stream is not a tty", detail: None, - }); + }) } } } @@ -346,14 +333,10 @@ impl StdWriter { } impl Writer for StdWriter { - fn write(&mut self, buf: &[u8]) { - let ret = match self.inner { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + match self.inner { TTY(ref mut tty) => tty.write(buf), File(ref mut file) => file.write(buf), - }; - match ret { - Ok(()) => {} - Err(e) => io_error::cond.raise(e) } } } @@ -376,7 +359,7 @@ mod tests { set_stdout(~w as ~Writer); println!("hello!"); }); - assert_eq!(r.read_to_str(), ~"hello!\n"); + assert_eq!(r.read_to_str().unwrap(), ~"hello!\n"); }) iotest!(fn capture_stderr() { @@ -388,7 +371,7 @@ mod tests { set_stderr(~w as ~Writer); fail!("my special message"); }); - let s = r.read_to_str(); + let s = r.read_to_str().unwrap(); assert!(s.contains("my special message")); }) } diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index 24eaf6adf3f3e..692aaa7afd05e 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -39,8 +39,8 @@ loop { */ use comm::Port; -use option::Option; use rt::rtio::{IoFactory, LocalIo, RtioTimer}; +use io::IoResult; pub struct Timer { priv obj: ~RtioTimer @@ -48,7 +48,8 @@ pub struct Timer { /// Sleep the current task for `msecs` milliseconds. pub fn sleep(msecs: u64) { - let mut timer = Timer::new().expect("timer::sleep: could not create a Timer"); + let timer = Timer::new(); + let mut timer = timer.ok().expect("timer::sleep: could not create a Timer"); timer.sleep(msecs) } @@ -57,7 +58,7 @@ impl Timer { /// Creates a new timer which can be used to put the current task to sleep /// for a number of milliseconds, or to possibly create channels which will /// get notified after an amount of time has passed. - pub fn new() -> Option { + pub fn new() -> IoResult { LocalIo::maybe_raise(|io| io.timer_init().map(|t| Timer { obj: t })) } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index a1794d24fc934..c4d92b36ecfa6 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -7,8 +7,10 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + use prelude::*; use cmp; +use io; use vec::bytes::MutableByteVector; /// Wraps a `Reader`, limiting the number of bytes that can be read from it. @@ -25,9 +27,9 @@ impl<'a, R: Reader> LimitReader<'a, R> { } impl<'a, R: Reader> Reader for LimitReader<'a, R> { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { if self.limit == 0 { - return None; + return Err(io::standard_error(io::EndOfFile)); } let len = cmp::min(self.limit, buf.len()); @@ -43,7 +45,7 @@ pub struct NullWriter; impl Writer for NullWriter { #[inline] - fn write(&mut self, _buf: &[u8]) { } + fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { Ok(()) } } /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero. @@ -51,9 +53,9 @@ pub struct ZeroReader; impl Reader for ZeroReader { #[inline] - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { buf.set_memory(0); - Some(buf.len()) + Ok(buf.len()) } } @@ -62,8 +64,8 @@ pub struct NullReader; impl Reader for NullReader { #[inline] - fn read(&mut self, _buf: &mut [u8]) -> Option { - None + fn read(&mut self, _buf: &mut [u8]) -> io::IoResult { + Err(io::standard_error(io::EndOfFile)) } } @@ -81,17 +83,21 @@ impl MultiWriter { impl Writer for MultiWriter { #[inline] - fn write(&mut self, buf: &[u8]) { + fn write(&mut self, buf: &[u8]) -> io::IoResult<()> { + let mut ret = Ok(()); for writer in self.writers.mut_iter() { - writer.write(buf); + ret = ret.and(writer.write(buf)); } + return ret; } #[inline] - fn flush(&mut self) { + fn flush(&mut self) -> io::IoResult<()> { + let mut ret = Ok(()); for writer in self.writers.mut_iter() { - writer.flush(); + ret = ret.and(writer.flush()); } + return ret; } } @@ -111,20 +117,25 @@ impl> ChainedReader { } impl> Reader for ChainedReader { - fn read(&mut self, buf: &mut [u8]) -> Option { + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { loop { - match self.cur_reader { + let err = match self.cur_reader { Some(ref mut r) => { match r.read(buf) { - Some(len) => return Some(len), - None => {} + Ok(len) => return Ok(len), + Err(ref e) if e.kind == io::EndOfFile => None, + Err(e) => Some(e), } } None => break + }; + self.cur_reader = self.readers.next(); + match err { + Some(e) => return Err(e), + None => {} } - self.cur_reader = self.readers.next() } - None + Err(io::standard_error(io::EndOfFile)) } } @@ -150,27 +161,29 @@ impl TeeReader { } impl Reader for TeeReader { - fn read(&mut self, buf: &mut [u8]) -> Option { - self.reader.read(buf).map(|len| { - self.writer.write(buf.slice_to(len)); - len + fn read(&mut self, buf: &mut [u8]) -> io::IoResult { + self.reader.read(buf).and_then(|len| { + self.writer.write(buf.slice_to(len)).map(|()| len) }) } } /// Copies all data from a `Reader` to a `Writer`. -pub fn copy(r: &mut R, w: &mut W) { +pub fn copy(r: &mut R, w: &mut W) -> io::IoResult<()> { let mut buf = [0, ..super::DEFAULT_BUF_SIZE]; loop { - match r.read(buf) { - Some(len) => w.write(buf.slice_to(len)), - None => break - } + let len = match r.read(buf) { + Ok(len) => len, + Err(ref e) if e.kind == io::EndOfFile => return Ok(()), + Err(e) => return Err(e), + }; + if_ok!(w.write(buf.slice_to(len))); } } #[cfg(test)] mod test { + use io; use io::{MemReader, MemWriter}; use super::*; use prelude::*; @@ -180,7 +193,7 @@ mod test { let mut r = MemReader::new(~[0, 1, 2]); { let mut r = LimitReader::new(&mut r, 4); - assert_eq!(~[0, 1, 2], r.read_to_end()); + assert_eq!(~[0, 1, 2], r.read_to_end().unwrap()); } } @@ -189,24 +202,24 @@ mod test { let mut r = MemReader::new(~[0, 1, 2]); { let mut r = LimitReader::new(&mut r, 2); - assert_eq!(~[0, 1], r.read_to_end()); + assert_eq!(~[0, 1], r.read_to_end().unwrap()); } - assert_eq!(~[2], r.read_to_end()); + assert_eq!(~[2], r.read_to_end().unwrap()); } #[test] fn test_null_writer() { let mut s = NullWriter; let buf = ~[0, 0, 0]; - s.write(buf); - s.flush(); + s.write(buf).unwrap(); + s.flush().unwrap(); } #[test] fn test_zero_reader() { let mut s = ZeroReader; let mut buf = ~[1, 2, 3]; - assert_eq!(s.read(buf), Some(3)); + assert_eq!(s.read(buf), Ok(3)); assert_eq!(~[0, 0, 0], buf); } @@ -214,7 +227,7 @@ mod test { fn test_null_reader() { let mut r = NullReader; let mut buf = ~[0]; - assert_eq!(r.read(buf), None); + assert!(r.read(buf).is_err()); } #[test] @@ -224,21 +237,23 @@ mod test { struct TestWriter; impl Writer for TestWriter { - fn write(&mut self, _buf: &[u8]) { + fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { unsafe { writes += 1 } + Ok(()) } - fn flush(&mut self) { + fn flush(&mut self) -> io::IoResult<()> { unsafe { flushes += 1 } + Ok(()) } } let mut multi = MultiWriter::new(~[~TestWriter as ~Writer, ~TestWriter as ~Writer]); - multi.write([1, 2, 3]); + multi.write([1, 2, 3]).unwrap(); assert_eq!(2, unsafe { writes }); assert_eq!(0, unsafe { flushes }); - multi.flush(); + multi.flush().unwrap(); assert_eq!(2, unsafe { writes }); assert_eq!(2, unsafe { flushes }); } @@ -248,14 +263,14 @@ mod test { let rs = ~[MemReader::new(~[0, 1]), MemReader::new(~[]), MemReader::new(~[2, 3])]; let mut r = ChainedReader::new(rs.move_iter()); - assert_eq!(~[0, 1, 2, 3], r.read_to_end()); + assert_eq!(~[0, 1, 2, 3], r.read_to_end().unwrap()); } #[test] fn test_tee_reader() { let mut r = TeeReader::new(MemReader::new(~[0, 1, 2]), MemWriter::new()); - assert_eq!(~[0, 1, 2], r.read_to_end()); + assert_eq!(~[0, 1, 2], r.read_to_end().unwrap()); let (_, w) = r.unwrap(); assert_eq!(~[0, 1, 2], w.unwrap()); } @@ -264,7 +279,7 @@ mod test { fn test_copy() { let mut r = MemReader::new(~[0, 1, 2, 3, 4]); let mut w = MemWriter::new(); - copy(&mut r, &mut w); + copy(&mut r, &mut w).unwrap(); assert_eq!(~[0, 1, 2, 3, 4], w.unwrap()); } } diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index 636d3ffd90a6b..c5e66ffc7be10 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -102,6 +102,7 @@ use io::Writer; use ops::Drop; use option::{Some, None, Option}; use prelude::drop; +use result::{Ok, Err}; use rt::local::Local; use rt::task::Task; use util; @@ -131,13 +132,19 @@ struct DefaultLogger { impl Logger for DefaultLogger { // by default, just ignore the level fn log(&mut self, _level: u32, args: &fmt::Arguments) { - fmt::writeln(&mut self.handle, args); + match fmt::writeln(&mut self.handle, args) { + Err(e) => fail!("failed to log: {}", e), + Ok(()) => {} + } } } impl Drop for DefaultLogger { fn drop(&mut self) { - self.handle.flush(); + match self.handle.flush() { + Err(e) => fail!("failed to flush a logger: {}", e), + Ok(()) => {} + } } } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 4032b63790bf6..b31ae92d7421d 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -197,3 +197,8 @@ macro_rules! local_data_key ( pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key; ) ) + +#[macro_export] +macro_rules! if_ok ( + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) +) diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 83cedd92a3f7d..19478e3dbb3c8 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -382,7 +382,7 @@ impl Option { impl fmt::Show for Option { #[inline] - fn fmt(s: &Option, f: &mut fmt::Formatter) { + fn fmt(s: &Option, f: &mut fmt::Formatter) -> fmt::Result { match *s { Some(ref t) => write!(f.buf, "Some({})", *t), None => write!(f.buf, "None") diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 0ea1c7510a1d2..541db01f1484f 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -372,9 +372,9 @@ pub fn self_exe_name() -> Option { fn load_self() -> Option<~[u8]> { use std::io; - match io::result(|| io::fs::readlink(&Path::new("/proc/self/exe"))) { - Ok(Some(path)) => Some(path.as_vec().to_owned()), - Ok(None) | Err(..) => None + match io::fs::readlink(&Path::new("/proc/self/exe")) { + Ok(path) => Some(path.as_vec().to_owned()), + Err(..) => None } } @@ -929,7 +929,7 @@ pub enum MapError { } impl fmt::Show for MapError { - fn fmt(val: &MapError, out: &mut fmt::Formatter) { + fn fmt(val: &MapError, out: &mut fmt::Formatter) -> fmt::Result { let str = match *val { ErrFdNotAvail => "fd not available for reading or writing", ErrInvalidFd => "Invalid fd", @@ -944,23 +944,19 @@ impl fmt::Show for MapError { ErrAlreadyExists => "File mapping for specified file already exists", ErrZeroLength => "Zero-length mapping not allowed", ErrUnknown(code) => { - write!(out.buf, "Unknown error = {}", code); - return + return write!(out.buf, "Unknown error = {}", code) }, ErrVirtualAlloc(code) => { - write!(out.buf, "VirtualAlloc failure = {}", code); - return + return write!(out.buf, "VirtualAlloc failure = {}", code) }, ErrCreateFileMappingW(code) => { - format!("CreateFileMappingW failure = {}", code); - return + return write!(out.buf, "CreateFileMappingW failure = {}", code) }, ErrMapViewOfFile(code) => { - write!(out.buf, "MapViewOfFile failure = {}", code); - return + return write!(out.buf, "MapViewOfFile failure = {}", code) } }; - write!(out.buf, "{}", str); + write!(out.buf, "{}", str) } } @@ -1496,7 +1492,6 @@ mod tests { use result::{Ok, Err}; use os::*; use libc::*; - use io; use io::fs; #[cfg(unix)] @@ -1540,9 +1535,9 @@ mod tests { assert!(*chunk.data == 0xbe); close(fd); } + drop(chunk); - let _guard = io::ignore_io_error(); - fs::unlink(&path); + fs::unlink(&path).unwrap(); } // More recursive_mkdir tests are in extra::tempfile diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 86f96a1075beb..4aa4a3feab1be 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -533,7 +533,7 @@ pub struct Display<'a, P> { } impl<'a, P: GenericPath> fmt::Show for Display<'a, P> { - fn fmt(d: &Display

, f: &mut fmt::Formatter) { + fn fmt(d: &Display

, f: &mut fmt::Formatter) -> fmt::Result { d.with_str(|s| f.pad(s)) } } diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index c359d79d27509..e9068c6b0c8a5 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -62,7 +62,7 @@ impl OSRng { pub fn new() -> OSRng { use path::Path; let reader = File::open(&Path::new("/dev/urandom")); - let reader = reader.expect("Error opening /dev/urandom"); + let reader = reader.ok().expect("Error opening /dev/urandom"); let reader_rng = ReaderRng::new(reader); OSRng { inner: reader_rng } diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index e19fbd9aaf8ba..621d70970f02f 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -11,7 +11,7 @@ //! A wrapper around any Reader to treat it as an RNG. use container::Container; -use option::{Some, None}; +use result::{Ok, Err}; use io::Reader; use rand::Rng; @@ -49,26 +49,26 @@ impl Rng for ReaderRng { // platform just involves blitting the bytes into the memory // of the u32, similarly for BE on BE; avoiding byteswapping. if cfg!(target_endian="little") { - self.reader.read_le_u32() + self.reader.read_le_u32().unwrap() } else { - self.reader.read_be_u32() + self.reader.read_be_u32().unwrap() } } fn next_u64(&mut self) -> u64 { // see above for explanation. if cfg!(target_endian="little") { - self.reader.read_le_u64() + self.reader.read_le_u64().unwrap() } else { - self.reader.read_be_u64() + self.reader.read_be_u64().unwrap() } } fn fill_bytes(&mut self, v: &mut [u8]) { if v.len() == 0 { return } match self.reader.read(v) { - Some(n) if n == v.len() => return, - Some(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \ - read {} out of {} bytes.", n, v.len()), - None => fail!("ReaderRng.fill_bytes reached eof.") + Ok(n) if n == v.len() => return, + Ok(n) => fail!("ReaderRng.fill_bytes could not fill buffer: \ + read {} out of {} bytes.", n, v.len()), + Err(e) => fail!("ReaderRng.fill_bytes error: {}", e) } } } diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index d6b4d3f565629..44ee5de7ac34c 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -66,6 +66,8 @@ impl MovePtrAdaptor { pub fn bump_past(&mut self) { self.bump(mem::size_of::()); } + + pub fn unwrap(self) -> V { self.inner } } /// Abstract type-directed pointer-movement using the MovePtr trait diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 41ddf02778768..f71649602b231 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -21,48 +21,57 @@ use char; use container::Container; use io; use iter::Iterator; -use option::{Some, None}; +use option::{Some, None, Option}; use ptr; use reflect; use reflect::{MovePtr, align}; +use result::{Ok, Err}; use str::StrSlice; use to_str::ToStr; use vec::OwnedVector; use unstable::intrinsics::{Disr, Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; use unstable::raw; +macro_rules! if_ok( ($me:expr, $e:expr) => ( + match $e { + Ok(()) => {}, + Err(e) => { $me.last_err = Some(e); return false; } + } +) ) + /// Representations trait Repr { - fn write_repr(&self, writer: &mut io::Writer); + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()>; } impl Repr for () { - fn write_repr(&self, writer: &mut io::Writer) { - writer.write("()".as_bytes()); + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { + writer.write("()".as_bytes()) } } impl Repr for bool { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = if *self { "true" } else { "false" }; writer.write(s.as_bytes()) } } impl Repr for int { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { ::int::to_str_bytes(*self, 10u, |bits| { - writer.write(bits); + writer.write(bits) }) } } macro_rules! int_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { ::$ty::to_str_bytes(*self, 10u, |bits| { - writer.write(bits); - writer.write(bytes!($suffix)); + writer.write(bits).and_then(|()| { + writer.write(bytes!($suffix)) + }) }) } })) @@ -78,10 +87,11 @@ int_repr!(u32, "u32") int_repr!(u64, "u64") macro_rules! num_repr(($ty:ident, $suffix:expr) => (impl Repr for $ty { - fn write_repr(&self, writer: &mut io::Writer) { + fn write_repr(&self, writer: &mut io::Writer) -> io::IoResult<()> { let s = self.to_str(); - writer.write(s.as_bytes()); - writer.write(bytes!($suffix)); + writer.write(s.as_bytes()).and_then(|()| { + writer.write(bytes!($suffix)) + }) } })) @@ -100,7 +110,8 @@ pub struct ReprVisitor<'a> { priv ptr: *u8, priv ptr_stk: ~[*u8], priv var_stk: ~[VariantState], - priv writer: &'a mut io::Writer + priv writer: &'a mut io::Writer, + priv last_err: Option, } pub fn ReprVisitor<'a>(ptr: *u8, @@ -110,6 +121,7 @@ pub fn ReprVisitor<'a>(ptr: *u8, ptr_stk: ~[], var_stk: ~[], writer: writer, + last_err: None, } } @@ -130,11 +142,10 @@ impl<'a> ReprVisitor<'a> { // Various helpers for the TyVisitor impl #[inline] - pub fn get(&mut self, f: |&mut ReprVisitor, &T|) -> bool { + pub fn get(&mut self, f: |&mut ReprVisitor, &T| -> bool) -> bool { unsafe { - f(self, transmute::<*u8,&T>(self.ptr)); + f(self, transmute::<*u8,&T>(self.ptr)) } - true } #[inline] @@ -152,43 +163,53 @@ impl<'a> ReprVisitor<'a> { ptr_stk: ~[], var_stk: ~[], writer: ::cast::transmute_copy(&self.writer), + last_err: None, }; let mut v = reflect::MovePtrAdaptor(u); // Obviously this should not be a thing, but blame #8401 for now visit_tydesc(inner, &mut v as &mut TyVisitor); - true + match v.unwrap().last_err { + Some(e) => { + self.last_err = Some(e); + false + } + None => true, + } } } #[inline] pub fn write(&mut self) -> bool { self.get(|this, v:&T| { - v.write_repr(unsafe { ::cast::transmute_copy(&this.writer) }); + if_ok!(this, v.write_repr(this.writer)); + true }) } - pub fn write_escaped_slice(&mut self, slice: &str) { - self.writer.write(['"' as u8]); + pub fn write_escaped_slice(&mut self, slice: &str) -> bool { + if_ok!(self, self.writer.write(['"' as u8])); for ch in slice.chars() { - self.write_escaped_char(ch, true); + if !self.write_escaped_char(ch, true) { return false } } - self.writer.write(['"' as u8]); + if_ok!(self, self.writer.write(['"' as u8])); + true } - pub fn write_mut_qualifier(&mut self, mtbl: uint) { + pub fn write_mut_qualifier(&mut self, mtbl: uint) -> bool { if mtbl == 0 { - self.writer.write("mut ".as_bytes()); + if_ok!(self, self.writer.write("mut ".as_bytes())); } else if mtbl == 1 { // skip, this is ast::m_imm } else { fail!("invalid mutability value"); } + true } pub fn write_vec_range(&mut self, ptr: *(), len: uint, inner: *TyDesc) -> bool { let mut p = ptr as *u8; let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; - self.writer.write(['[' as u8]); + if_ok!(self, self.writer.write(['[' as u8])); let mut first = true; let mut left = len; // unit structs have 0 size, and don't loop forever. @@ -197,13 +218,13 @@ impl<'a> ReprVisitor<'a> { if first { first = false; } else { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_ptr_inner(p as *u8, inner); p = align(unsafe { ptr::offset(p, sz as int) as uint }, al) as *u8; left -= dec; } - self.writer.write([']' as u8]); + if_ok!(self, self.writer.write([']' as u8])); true } @@ -211,8 +232,8 @@ impl<'a> ReprVisitor<'a> { self.write_vec_range(ptr::to_unsafe_ptr(&v.data), v.fill, inner) } - fn write_escaped_char(&mut self, ch: char, is_str: bool) { - match ch { + fn write_escaped_char(&mut self, ch: char, is_str: bool) -> bool { + if_ok!(self, match ch { '\t' => self.writer.write("\\t".as_bytes()), '\r' => self.writer.write("\\r".as_bytes()), '\n' => self.writer.write("\\n".as_bytes()), @@ -234,16 +255,18 @@ impl<'a> ReprVisitor<'a> { '\x20'..'\x7e' => self.writer.write([ch as u8]), _ => { char::escape_unicode(ch, |c| { - self.writer.write([c as u8]); - }) + let _ = self.writer.write([c as u8]); + }); + Ok(()) } - } + }); + return true; } } impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_bot(&mut self) -> bool { - self.writer.write("!".as_bytes()); + if_ok!(self, self.writer.write("!".as_bytes())); true } fn visit_nil(&mut self) -> bool { self.write::<()>() } @@ -265,9 +288,10 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_char(&mut self) -> bool { self.get::(|this, &ch| { - this.writer.write(['\'' as u8]); - this.write_escaped_char(ch, false); - this.writer.write(['\'' as u8]); + if_ok!(this, this.writer.write(['\'' as u8])); + if !this.write_escaped_char(ch, false) { return false } + if_ok!(this, this.writer.write(['\'' as u8])); + true }) } @@ -277,8 +301,8 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_estr_uniq(&mut self) -> bool { self.get::<~str>(|this, s| { - this.writer.write(['~' as u8]); - this.write_escaped_slice(*s); + if_ok!(this, this.writer.write(['~' as u8])); + this.write_escaped_slice(*s) }) } @@ -291,34 +315,35 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _align: uint) -> bool { fail!(); } fn visit_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['@' as u8]); + if_ok!(self, self.writer.write(['@' as u8])); self.write_mut_qualifier(mtbl); self.get::<&raw::Box<()>>(|this, b| { let p = ptr::to_unsafe_ptr(&b.data) as *u8; - this.visit_ptr_inner(p, inner); + this.visit_ptr_inner(p, inner) }) } fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['~' as u8]); + if_ok!(self, self.writer.write(['~' as u8])); self.get::<*u8>(|this, b| { - this.visit_ptr_inner(*b, inner); + this.visit_ptr_inner(*b, inner) }) } fn visit_ptr(&mut self, mtbl: uint, _inner: *TyDesc) -> bool { self.get::<*u8>(|this, p| { - write!(this.writer, "({} as *", *p); + if_ok!(this, write!(this.writer, "({} as *", *p)); this.write_mut_qualifier(mtbl); - this.writer.write("())".as_bytes()); + if_ok!(this, this.writer.write("())".as_bytes())); + true }) } fn visit_rptr(&mut self, mtbl: uint, inner: *TyDesc) -> bool { - self.writer.write(['&' as u8]); + if_ok!(self, self.writer.write(['&' as u8])); self.write_mut_qualifier(mtbl); self.get::<*u8>(|this, p| { - this.visit_ptr_inner(*p, inner); + this.visit_ptr_inner(*p, inner) }) } @@ -327,33 +352,33 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_unboxed_vec(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::>(|this, b| { - this.write_unboxed_vec_repr(mtbl, b, inner); + this.write_unboxed_vec_repr(mtbl, b, inner) }) } fn visit_evec_box(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<&raw::Box>>(|this, b| { - this.writer.write(['@' as u8]); + if_ok!(this, this.writer.write(['@' as u8])); this.write_mut_qualifier(mtbl); - this.write_unboxed_vec_repr(mtbl, &b.data, inner); + this.write_unboxed_vec_repr(mtbl, &b.data, inner) }) } fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::<&raw::Vec<()>>(|this, b| { - this.writer.write(['~' as u8]); - this.write_unboxed_vec_repr(mtbl, *b, inner); + if_ok!(this, this.writer.write(['~' as u8])); + this.write_unboxed_vec_repr(mtbl, *b, inner) }) } fn visit_evec_slice(&mut self, mtbl: uint, inner: *TyDesc) -> bool { self.get::>(|this, s| { - this.writer.write(['&' as u8]); + if_ok!(this, this.writer.write(['&' as u8])); this.write_mut_qualifier(mtbl); let size = unsafe { if (*inner).size == 0 { 1 } else { (*inner).size } }; - this.write_vec_range(s.data, s.len * size, inner); + this.write_vec_range(s.data, s.len * size, inner) }) } @@ -361,42 +386,42 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _: uint, inner: *TyDesc) -> bool { let assumed_size = if sz == 0 { n } else { sz }; self.get::<()>(|this, b| { - this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner); + this.write_vec_range(ptr::to_unsafe_ptr(b), assumed_size, inner) }) } fn visit_enter_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['{' as u8]); + if_ok!(self, self.writer.write(['{' as u8])); true } fn visit_rec_field(&mut self, i: uint, name: &str, mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.write_mut_qualifier(mtbl); - self.writer.write(name.as_bytes()); - self.writer.write(": ".as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); + if_ok!(self, self.writer.write(": ".as_bytes())); self.visit_inner(inner); true } fn visit_leave_rec(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['}' as u8]); + if_ok!(self, self.writer.write(['}' as u8])); true } fn visit_enter_class(&mut self, name: &str, named_fields: bool, n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); if n_fields != 0 { if named_fields { - self.writer.write(['{' as u8]); + if_ok!(self, self.writer.write(['{' as u8])); } else { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); } } true @@ -405,11 +430,11 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_class_field(&mut self, i: uint, name: &str, named: bool, _mtbl: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } if named { - self.writer.write(name.as_bytes()); - self.writer.write(": ".as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); + if_ok!(self, self.writer.write(": ".as_bytes())); } self.visit_inner(inner); true @@ -419,9 +444,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { _sz: uint, _align: uint) -> bool { if n_fields != 0 { if named_fields { - self.writer.write(['}' as u8]); + if_ok!(self, self.writer.write(['}' as u8])); } else { - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); } } true @@ -429,13 +454,13 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); true } fn visit_tup_field(&mut self, i: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } self.visit_inner(inner); true @@ -444,9 +469,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_leave_tup(&mut self, _n_fields: uint, _sz: uint, _align: uint) -> bool { if _n_fields == 1 { - self.writer.write([',' as u8]); + if_ok!(self, self.writer.write([',' as u8])); } - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); true } @@ -482,9 +507,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> { } if write { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); if n_fields > 0 { - self.writer.write(['(' as u8]); + if_ok!(self, self.writer.write(['(' as u8])); } } true @@ -498,7 +523,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { match self.var_stk[self.var_stk.len() - 1] { Matched => { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } if ! self.visit_inner(inner) { return false; @@ -516,7 +541,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { match self.var_stk[self.var_stk.len() - 1] { Matched => { if n_fields > 0 { - self.writer.write([')' as u8]); + if_ok!(self, self.writer.write([')' as u8])); } } _ => () @@ -538,28 +563,29 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_enter_fn(&mut self, _purity: uint, _proto: uint, _n_inputs: uint, _retstyle: uint) -> bool { - self.writer.write("fn(".as_bytes()); + if_ok!(self, self.writer.write("fn(".as_bytes())); true } fn visit_fn_input(&mut self, i: uint, _mode: uint, inner: *TyDesc) -> bool { if i != 0 { - self.writer.write(", ".as_bytes()); + if_ok!(self, self.writer.write(", ".as_bytes())); } let name = unsafe { (*inner).name }; - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); true } - fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, inner: *TyDesc) -> bool { + fn visit_fn_output(&mut self, _retstyle: uint, variadic: bool, + inner: *TyDesc) -> bool { if variadic { - self.writer.write(", ...".as_bytes()); + if_ok!(self, self.writer.write(", ...".as_bytes())); } - self.writer.write(")".as_bytes()); + if_ok!(self, self.writer.write(")".as_bytes())); let name = unsafe { (*inner).name }; if name != "()" { - self.writer.write(" -> ".as_bytes()); - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(" -> ".as_bytes())); + if_ok!(self, self.writer.write(name.as_bytes())); } true } @@ -569,7 +595,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_trait(&mut self, name: &str) -> bool { - self.writer.write(name.as_bytes()); + if_ok!(self, self.writer.write(name.as_bytes())); true } @@ -582,13 +608,17 @@ impl<'a> TyVisitor for ReprVisitor<'a> { fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true } } -pub fn write_repr(writer: &mut io::Writer, object: &T) { +pub fn write_repr(writer: &mut io::Writer, object: &T) -> io::IoResult<()> { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *u8; let tydesc = get_tydesc::(); let u = ReprVisitor(ptr, writer); let mut v = reflect::MovePtrAdaptor(u); visit_tydesc(tydesc, &mut v as &mut TyVisitor); + match v.unwrap().last_err { + Some(e) => Err(e), + None => Ok(()), + } } } @@ -597,7 +627,7 @@ pub fn repr_to_str(t: &T) -> ~str { use io; let mut result = io::MemWriter::new(); - write_repr(&mut result as &mut io::Writer, t); + write_repr(&mut result as &mut io::Writer, t).unwrap(); str::from_utf8_owned(result.unwrap()).unwrap() } @@ -615,7 +645,7 @@ fn test_repr() { fn exact_test(t: &T, e:&str) { let mut m = io::MemWriter::new(); - write_repr(&mut m as &mut io::Writer, t); + write_repr(&mut m as &mut io::Writer, t).unwrap(); let s = str::from_utf8_owned(m.unwrap()).unwrap(); assert_eq!(s.as_slice(), e); } diff --git a/src/libstd/result.rs b/src/libstd/result.rs index cc8fdeaccfea9..846bba7533fed 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -208,7 +208,7 @@ impl Result { impl fmt::Show for Result { #[inline] - fn fmt(s: &Result, f: &mut fmt::Formatter) { + fn fmt(s: &Result, f: &mut fmt::Formatter) -> fmt::Result { match *s { Ok(ref t) => write!(f.buf, "Ok({})", *t), Err(ref e) => write!(f.buf, "Err({})", *e) diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 455a84b4ce3cf..35b1e21df0677 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -16,13 +16,13 @@ use libc; use ops::Drop; use option::{Option, Some, None}; use path::Path; -use result::{Result, Ok, Err}; +use result::{Result, Err}; use rt::task::Task; use rt::local::Local; use ai = io::net::addrinfo; use io; -use io::IoError; +use io::{IoError, IoResult}; use io::net::ip::{IpAddr, SocketAddr}; use io::process::{ProcessConfig, ProcessExit}; use io::signal::Signum; @@ -116,23 +116,12 @@ impl<'a> LocalIo<'a> { return ret; } - pub fn maybe_raise(f: |io: &mut IoFactory| -> Result) - -> Option + pub fn maybe_raise(f: |io: &mut IoFactory| -> IoResult) + -> IoResult { match LocalIo::borrow() { - None => { - io::io_error::cond.raise(io::standard_error(io::IoUnavailable)); - None - } - Some(mut io) => { - match f(io.get()) { - Ok(t) => Some(t), - Err(ioerr) => { - io::io_error::cond.raise(ioerr); - None - } - } - } + None => Err(io::standard_error(io::IoUnavailable)), + Some(mut io) => f(io.get()), } } diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 7c43e64f17b15..515eb93001af2 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -119,6 +119,7 @@ impl Task { // Run the task main function, then do some cleanup. f.finally(|| { + #[allow(unused_must_use)] fn close_outputs() { let mut task = Local::borrow(None::); let logger = task.get().logger.take(); @@ -126,8 +127,8 @@ impl Task { let stdout = task.get().stdout.take(); drop(task); drop(logger); // loggers are responsible for flushing - match stdout { Some(mut w) => w.flush(), None => {} } - match stderr { Some(mut w) => w.flush(), None => {} } + match stdout { Some(mut w) => { w.flush(); }, None => {} } + match stderr { Some(mut w) => { w.flush(); }, None => {} } } // First, flush/destroy the user stdout/logger because these diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 4d2dcb6c51cab..9aece13b84ca1 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -464,9 +464,10 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! { match task.stderr.take() { Some(mut stderr) => { Local::put(task); - format_args!(|args| ::fmt::writeln(stderr, args), - "task '{}' failed at '{}', {}:{}", - n, msg_s, file, line); + // FIXME: what to do when the task printing fails? + let _err = format_args!(|args| ::fmt::writeln(stderr, args), + "task '{}' failed at '{}', {}:{}", + n, msg_s, file, line); task = Local::take(); match util::replace(&mut task.stderr, Some(stderr)) { diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 9c17c624987b5..69e240f30bcf0 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -11,10 +11,12 @@ use container::Container; use fmt; use from_str::FromStr; +use io::IoResult; use iter::Iterator; use libc; use option::{Some, None, Option}; use os; +use result::Ok; use str::StrSlice; use unstable::running_on_valgrind; use vec::ImmutableVector; @@ -73,16 +75,17 @@ pub fn dumb_println(args: &fmt::Arguments) { struct Stderr; impl io::Writer for Stderr { - fn write(&mut self, data: &[u8]) { + fn write(&mut self, data: &[u8]) -> IoResult<()> { unsafe { libc::write(libc::STDERR_FILENO, data.as_ptr() as *libc::c_void, data.len() as libc::size_t); } + Ok(()) // yes, we're lying } } let mut w = Stderr; - fmt::writeln(&mut w as &mut io::Writer, args); + let _ = fmt::writeln(&mut w as &mut io::Writer, args); } pub fn abort(msg: &str) -> ! { diff --git a/src/libstd/run.rs b/src/libstd/run.rs index ef2374f6095da..04e42b3eedfc5 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -11,6 +11,7 @@ //! Utilities for spawning and managing processes #[allow(missing_doc)]; +#[deny(unused_must_use)]; use comm::SharedChan; use io::Reader; @@ -119,7 +120,8 @@ impl Process { * * options - Options to configure the environment of the process, * the working directory and the standard IO streams. */ - pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Option { + pub fn new(prog: &str, args: &[~str], + options: ProcessOptions) -> io::IoResult { let ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options; let env = env.as_ref().map(|a| a.as_slice()); let cwd = dir.as_ref().map(|a| a.as_str().unwrap()); @@ -138,10 +140,7 @@ impl Process { cwd: cwd, io: rtio, }; - match process::Process::new(rtconfig) { - Some(inner) => Some(Process { inner: inner }), - None => None - } + process::Process::new(rtconfig).map(|p| Process { inner: p }) } /// Returns the unique id of the process @@ -224,19 +223,17 @@ impl Process { let ch_clone = ch.clone(); spawn(proc() { - let _guard = io::ignore_io_error(); let mut error = error; match error { Some(ref mut e) => ch.send((2, e.read_to_end())), - None => ch.send((2, ~[])) + None => ch.send((2, Ok(~[]))) } }); spawn(proc() { - let _guard = io::ignore_io_error(); let mut output = output; match output { Some(ref mut e) => ch_clone.send((1, e.read_to_end())), - None => ch_clone.send((1, ~[])) + None => ch_clone.send((1, Ok(~[]))) } }); @@ -251,8 +248,8 @@ impl Process { }; return ProcessOutput {status: status, - output: outs, - error: errs}; + output: outs.ok().unwrap_or(~[]), + error: errs.ok().unwrap_or(~[]) }; } /** @@ -262,9 +259,10 @@ impl Process { * On Posix OSs SIGTERM will be sent to the process. On Win32 * TerminateProcess(..) will be called. */ - pub fn destroy(&mut self) { - self.inner.signal(io::process::PleaseExitSignal); + pub fn destroy(&mut self) -> io::IoResult<()> { + let ret = self.inner.signal(io::process::PleaseExitSignal); self.finish(); + return ret; } /** @@ -274,9 +272,12 @@ impl Process { * On Posix OSs SIGKILL will be sent to the process. On Win32 * TerminateProcess(..) will be called. */ - pub fn force_destroy(&mut self) { - self.inner.signal(io::process::MustDieSignal); + pub fn force_destroy(&mut self) -> io::IoResult<()> { + // This should never fail because we own the process + let ret = self.inner.signal(io::process::MustDieSignal); self.finish(); + return ret; + } } @@ -293,18 +294,14 @@ impl Process { * * The process's exit code, or None if the child process could not be started */ -pub fn process_status(prog: &str, args: &[~str]) -> Option { - let mut opt_prog = Process::new(prog, args, ProcessOptions { +pub fn process_status(prog: &str, args: &[~str]) -> io::IoResult { + Process::new(prog, args, ProcessOptions { env: None, dir: None, in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }), out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }), err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) }) - }); - match opt_prog { - Some(ref mut prog) => Some(prog.finish()), - None => None - } + }).map(|mut p| p.finish()) } /** @@ -320,12 +317,10 @@ pub fn process_status(prog: &str, args: &[~str]) -> Option { * The process's stdout/stderr output and exit code, or None if the child process could not be * started. */ -pub fn process_output(prog: &str, args: &[~str]) -> Option { - let mut opt_prog = Process::new(prog, args, ProcessOptions::new()); - match opt_prog { - Some(ref mut prog) => Some(prog.finish_with_output()), - None => None - } +pub fn process_output(prog: &str, args: &[~str]) -> io::IoResult { + Process::new(prog, args, ProcessOptions::new()).map(|mut p| { + p.finish_with_output() + }) } #[cfg(test)] @@ -337,33 +332,25 @@ mod tests { use task::spawn; use unstable::running_on_valgrind; use io::pipe::PipeStream; - use io::{io_error, FileNotFound}; + use io::{FileNotFound}; use libc::c_int; #[test] #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_process_status() { - let mut status = run::process_status("false", []).expect("failed to exec `false`"); + let mut status = run::process_status("false", []).unwrap(); assert!(status.matches_exit_status(1)); - status = run::process_status("true", []).expect("failed to exec `true`"); + status = run::process_status("true", []).unwrap(); assert!(status.success()); } #[test] fn test_process_output_fail_to_start() { - // If the executable does not exist, then the io_error condition should be raised with - // IoErrorKind FileNotFound. - - let mut trapped_io_error = false; - let opt_outp = io_error::cond.trap(|e| { - trapped_io_error = true; - assert_eq!(e.kind, FileNotFound); - }).inside(|| -> Option { - run::process_output("/no-binary-by-this-name-should-exist", []) - }); - assert!(trapped_io_error); - assert!(opt_outp.is_none()); + match run::process_output("/no-binary-by-this-name-should-exist", []) { + Err(e) => assert_eq!(e.kind, FileNotFound), + Ok(..) => fail!() + } } #[test] @@ -371,7 +358,7 @@ mod tests { fn test_process_output_output() { let run::ProcessOutput {status, output, error} - = run::process_output("echo", [~"hello"]).expect("failed to exec `echo`"); + = run::process_output("echo", [~"hello"]).unwrap(); let output_str = str::from_utf8_owned(output).unwrap(); assert!(status.success()); @@ -387,7 +374,7 @@ mod tests { fn test_process_output_error() { let run::ProcessOutput {status, output, error} - = run::process_output("mkdir", [~"."]).expect("failed to exec `mkdir`"); + = run::process_output("mkdir", [~"."]).unwrap(); assert!(status.matches_exit_status(1)); assert_eq!(output, ~[]); @@ -408,7 +395,7 @@ mod tests { in_fd: Some(pipe_in.input), out_fd: Some(pipe_out.out), err_fd: Some(pipe_err.out) - }).expect("failed to exec `cat`"); + }).unwrap(); os::close(pipe_in.input as int); os::close(pipe_out.out as int); @@ -426,27 +413,18 @@ mod tests { fn writeclose(fd: c_int, s: &str) { let mut writer = PipeStream::open(fd); - writer.write(s.as_bytes()); + writer.write(s.as_bytes()).unwrap(); } fn readclose(fd: c_int) -> ~str { - let mut res = ~[]; - let mut reader = PipeStream::open(fd); - let mut buf = [0, ..1024]; - loop { - match reader.read(buf) { - Some(n) => { res.push_all(buf.slice_to(n)); } - None => break - } - } - str::from_utf8_owned(res).unwrap() + PipeStream::open(fd).read_to_str().unwrap() } #[test] #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_finish_once() { let mut prog = run::Process::new("false", [], run::ProcessOptions::new()) - .expect("failed to exec `false`"); + .unwrap(); assert!(prog.finish().matches_exit_status(1)); } @@ -454,7 +432,7 @@ mod tests { #[cfg(not(target_os="android"))] // FIXME(#10380) fn test_finish_twice() { let mut prog = run::Process::new("false", [], run::ProcessOptions::new()) - .expect("failed to exec `false`"); + .unwrap(); assert!(prog.finish().matches_exit_status(1)); assert!(prog.finish().matches_exit_status(1)); } @@ -464,7 +442,7 @@ mod tests { fn test_finish_with_output_once() { let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()) - .expect("failed to exec `echo`"); + .unwrap(); let run::ProcessOutput {status, output, error} = prog.finish_with_output(); let output_str = str::from_utf8_owned(output).unwrap(); @@ -482,7 +460,7 @@ mod tests { fn test_finish_with_output_twice() { let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()) - .expect("failed to exec `echo`"); + .unwrap(); let run::ProcessOutput {status, output, error} = prog.finish_with_output(); @@ -511,14 +489,14 @@ mod tests { run::Process::new("pwd", [], run::ProcessOptions { dir: dir, .. run::ProcessOptions::new() - }).expect("failed to exec `pwd`") + }).unwrap() } #[cfg(unix,target_os="android")] fn run_pwd(dir: Option<&Path>) -> run::Process { run::Process::new("/system/bin/sh", [~"-c",~"pwd"], run::ProcessOptions { dir: dir, .. run::ProcessOptions::new() - }).expect("failed to exec `/system/bin/sh`") + }).unwrap() } #[cfg(windows)] @@ -526,7 +504,7 @@ mod tests { run::Process::new("cmd", [~"/c", ~"cd"], run::ProcessOptions { dir: dir, .. run::ProcessOptions::new() - }).expect("failed to run `cmd`") + }).unwrap() } #[test] @@ -537,8 +515,8 @@ mod tests { let parent_dir = os::getcwd(); let child_dir = Path::new(output.trim()); - let parent_stat = parent_dir.stat(); - let child_stat = child_dir.stat(); + let parent_stat = parent_dir.stat().unwrap(); + let child_stat = child_dir.stat().unwrap(); assert_eq!(parent_stat.unstable.device, child_stat.unstable.device); assert_eq!(parent_stat.unstable.inode, child_stat.unstable.inode); @@ -554,8 +532,8 @@ mod tests { let output = str::from_utf8_owned(prog.finish_with_output().output).unwrap(); let child_dir = Path::new(output.trim()); - let parent_stat = parent_dir.stat(); - let child_stat = child_dir.stat(); + let parent_stat = parent_dir.stat().unwrap(); + let child_stat = child_dir.stat().unwrap(); assert_eq!(parent_stat.unstable.device, child_stat.unstable.device); assert_eq!(parent_stat.unstable.inode, child_stat.unstable.inode); @@ -566,14 +544,14 @@ mod tests { run::Process::new("env", [], run::ProcessOptions { env: env, .. run::ProcessOptions::new() - }).expect("failed to exec `env`") + }).unwrap() } #[cfg(unix,target_os="android")] fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process { run::Process::new("/system/bin/sh", [~"-c",~"set"], run::ProcessOptions { env: env, .. run::ProcessOptions::new() - }).expect("failed to exec `/system/bin/sh`") + }).unwrap() } #[cfg(windows)] @@ -581,7 +559,7 @@ mod tests { run::Process::new("cmd", [~"/c", ~"set"], run::ProcessOptions { env: env, .. run::ProcessOptions::new() - }).expect("failed to run `cmd`") + }).unwrap() } #[test] diff --git a/src/libstd/task.rs b/src/libstd/task.rs index c8b690830866e..5fa0c6431ab5c 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -541,7 +541,7 @@ fn test_avoid_copying_the_body_task_spawn() { #[test] fn test_avoid_copying_the_body_try() { avoid_copying_the_body(|f| { - try(proc() { + let _ = try(proc() { f() }); }) diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index 4c545de73b48b..c8bd1907c5c0e 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -349,7 +349,7 @@ impl ToBytes for A { let mut m = ::io::MemWriter::new(); self.iter_bytes(lsb0, |bytes| { - m.write(bytes); + m.write(bytes).unwrap(); true }); m.unwrap() diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 3b2c86c371217..c2fa168a47825 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -200,7 +200,7 @@ mod tests { // accesses will also fail. let x = Exclusive::new(1); let x2 = x.clone(); - task::try(proc() { + let _ = task::try(proc() { x2.with(|one| assert_eq!(*one, 2)) }); x.with(|one| assert_eq!(*one, 1)); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 90fe121160bae..5b3b436a6fc5a 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -189,58 +189,61 @@ impl Level { } } -fn print_maybe_styled(msg: &str, color: term::attr::Attr) { - local_data_key!(tls_terminal: ~Option>) +fn print_maybe_styled(msg: &str, color: term::attr::Attr) -> io::IoResult<()> { + local_data_key!(tls_terminal: Option>) + fn is_stderr_screen() -> bool { use std::libc; unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } } - fn write_pretty(term: &mut term::Terminal, s: &str, c: term::attr::Attr) { - term.attr(c); - term.write(s.as_bytes()); - term.reset(); + fn write_pretty(term: &mut term::Terminal, s: &str, + c: term::attr::Attr) -> io::IoResult<()> { + if_ok!(term.attr(c)); + if_ok!(term.write(s.as_bytes())); + if_ok!(term.reset()); + Ok(()) } if is_stderr_screen() { local_data::get_mut(tls_terminal, |term| { match term { Some(term) => { - match **term { + match *term { Some(ref mut term) => write_pretty(term, msg, color), None => io::stderr().write(msg.as_bytes()) } } None => { - let t = ~match term::Terminal::new(io::stderr()) { + let (t, ret) = match term::Terminal::new(io::stderr()) { Ok(mut term) => { - write_pretty(&mut term, msg, color); - Some(term) + let r = write_pretty(&mut term, msg, color); + (Some(term), r) } Err(_) => { - io::stderr().write(msg.as_bytes()); - None + (None, io::stderr().write(msg.as_bytes())) } }; local_data::set(tls_terminal, t); + ret } } - }); + }) } else { - io::stderr().write(msg.as_bytes()); + io::stderr().write(msg.as_bytes()) } } -fn print_diagnostic(topic: &str, lvl: Level, msg: &str) { - let mut stderr = io::stderr(); - +fn print_diagnostic(topic: &str, lvl: Level, msg: &str) -> io::IoResult<()> { if !topic.is_empty() { - write!(&mut stderr as &mut io::Writer, "{} ", topic); + let mut stderr = io::stderr(); + if_ok!(write!(&mut stderr as &mut io::Writer, "{} ", topic)); } - print_maybe_styled(format!("{}: ", lvl.to_str()), - term::attr::ForegroundColor(lvl.color())); - print_maybe_styled(format!("{}\n", msg), term::attr::Bold); + if_ok!(print_maybe_styled(format!("{}: ", lvl.to_str()), + term::attr::ForegroundColor(lvl.color()))); + if_ok!(print_maybe_styled(format!("{}\n", msg), term::attr::Bold)); + Ok(()) } pub struct DefaultEmitter; @@ -250,20 +253,28 @@ impl Emitter for DefaultEmitter { cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, lvl: Level) { - match cmsp { + let error = match cmsp { Some((cm, sp)) => emit(cm, sp, msg, lvl, false), None => print_diagnostic("", lvl, msg), + }; + + match error { + Ok(()) => {} + Err(e) => fail!("failed to print diagnostics: {}", e), } } fn custom_emit(&self, cm: &codemap::CodeMap, sp: Span, msg: &str, lvl: Level) { - emit(cm, sp, msg, lvl, true); + match emit(cm, sp, msg, lvl, true) { + Ok(()) => {} + Err(e) => fail!("failed to print diagnostics: {}", e), + } } } fn emit(cm: &codemap::CodeMap, sp: Span, - msg: &str, lvl: Level, custom: bool) { + msg: &str, lvl: Level, custom: bool) -> io::IoResult<()> { let ss = cm.span_to_str(sp); let lines = cm.span_to_lines(sp); if custom { @@ -272,19 +283,19 @@ fn emit(cm: &codemap::CodeMap, sp: Span, // the span) let span_end = Span { lo: sp.hi, hi: sp.hi, expn_info: sp.expn_info}; let ses = cm.span_to_str(span_end); - print_diagnostic(ses, lvl, msg); - custom_highlight_lines(cm, sp, lvl, lines); + if_ok!(print_diagnostic(ses, lvl, msg)); + if_ok!(custom_highlight_lines(cm, sp, lvl, lines)); } else { - print_diagnostic(ss, lvl, msg); - highlight_lines(cm, sp, lvl, lines); + if_ok!(print_diagnostic(ss, lvl, msg)); + if_ok!(highlight_lines(cm, sp, lvl, lines)); } - print_macro_backtrace(cm, sp); + print_macro_backtrace(cm, sp) } fn highlight_lines(cm: &codemap::CodeMap, sp: Span, lvl: Level, - lines: &codemap::FileLines) { + lines: &codemap::FileLines) -> io::IoResult<()> { let fm = lines.file; let mut err = io::stderr(); let err = &mut err as &mut io::Writer; @@ -297,12 +308,13 @@ fn highlight_lines(cm: &codemap::CodeMap, } // Print the offending lines for line in display_lines.iter() { - write!(err, "{}:{} {}\n", fm.name, *line + 1, fm.get_line(*line as int)); + if_ok!(write!(err, "{}:{} {}\n", fm.name, *line + 1, + fm.get_line(*line as int))); } if elided { let last_line = display_lines[display_lines.len() - 1u]; let s = format!("{}:{} ", fm.name, last_line + 1u); - write!(err, "{0:1$}...\n", "", s.len()); + if_ok!(write!(err, "{0:1$}...\n", "", s.len())); } // FIXME (#3260) @@ -334,7 +346,7 @@ fn highlight_lines(cm: &codemap::CodeMap, _ => s.push_char(' '), }; } - write!(err, "{}", s); + if_ok!(write!(err, "{}", s)); let mut s = ~"^"; let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { @@ -342,8 +354,10 @@ fn highlight_lines(cm: &codemap::CodeMap, let num_squigglies = hi.col.to_uint()-lo.col.to_uint()-1u; for _ in range(0, num_squigglies) { s.push_char('~'); } } - print_maybe_styled(s + "\n", term::attr::ForegroundColor(lvl.color())); + if_ok!(print_maybe_styled(s + "\n", + term::attr::ForegroundColor(lvl.color()))); } + Ok(()) } // Here are the differences between this and the normal `highlight_lines`: @@ -355,23 +369,23 @@ fn highlight_lines(cm: &codemap::CodeMap, fn custom_highlight_lines(cm: &codemap::CodeMap, sp: Span, lvl: Level, - lines: &codemap::FileLines) { + lines: &codemap::FileLines) -> io::IoResult<()> { let fm = lines.file; let mut err = io::stderr(); let err = &mut err as &mut io::Writer; let lines = lines.lines.as_slice(); if lines.len() > MAX_LINES { - write!(err, "{}:{} {}\n", fm.name, - lines[0] + 1, fm.get_line(lines[0] as int)); - write!(err, "...\n"); + if_ok!(write!(err, "{}:{} {}\n", fm.name, + lines[0] + 1, fm.get_line(lines[0] as int))); + if_ok!(write!(err, "...\n")); let last_line = lines[lines.len()-1]; - write!(err, "{}:{} {}\n", fm.name, - last_line + 1, fm.get_line(last_line as int)); + if_ok!(write!(err, "{}:{} {}\n", fm.name, + last_line + 1, fm.get_line(last_line as int))); } else { for line in lines.iter() { - write!(err, "{}:{} {}\n", fm.name, - *line + 1, fm.get_line(*line as int)); + if_ok!(write!(err, "{}:{} {}\n", fm.name, + *line + 1, fm.get_line(*line as int))); } } let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1); @@ -381,22 +395,24 @@ fn custom_highlight_lines(cm: &codemap::CodeMap, let mut s = ~""; for _ in range(0, skip) { s.push_char(' '); } s.push_char('^'); - print_maybe_styled(s + "\n", term::attr::ForegroundColor(lvl.color())); + print_maybe_styled(s + "\n", term::attr::ForegroundColor(lvl.color())) } -fn print_macro_backtrace(cm: &codemap::CodeMap, sp: Span) { +fn print_macro_backtrace(cm: &codemap::CodeMap, sp: Span) -> io::IoResult<()> { for ei in sp.expn_info.iter() { let ss = ei.callee.span.as_ref().map_or(~"", |span| cm.span_to_str(*span)); let (pre, post) = match ei.callee.format { codemap::MacroAttribute => ("#[", "]"), codemap::MacroBang => ("", "!") }; - print_diagnostic(ss, Note, - format!("in expansion of {}{}{}", pre, ei.callee.name, post)); + if_ok!(print_diagnostic(ss, Note, + format!("in expansion of {}{}{}", pre, + ei.callee.name, post))); let ss = cm.span_to_str(ei.call_site); - print_diagnostic(ss, Note, "expansion site"); - print_macro_backtrace(cm, ei.call_site); + if_ok!(print_diagnostic(ss, Note, "expansion site")); + if_ok!(print_macro_backtrace(cm, ei.call_site)); } + Ok(()) } pub fn expect(diag: @SpanHandler, opt: Option, msg: || -> ~str) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d8d98b2779316..ae93c235ad23c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -957,14 +957,13 @@ mod test { use ast_util; use codemap; use codemap::Spanned; - use fold; use fold::*; use ext::base::{CrateLoader, MacroCrate}; use parse; use parse::token::{fresh_mark, gensym, intern}; use parse::token; use util::parser_testing::{string_to_crate, string_to_crate_and_sess}; - use util::parser_testing::{string_to_pat, string_to_tts, strs_to_idents}; + use util::parser_testing::{string_to_pat, strs_to_idents}; use visit; use visit::Visitor; @@ -1253,14 +1252,14 @@ mod test { let varref_name = mtwt_resolve(varref.segments[0].identifier); let varref_marks = mtwt_marksof(varref.segments[0].identifier.ctxt, invalid_name); - if (!(varref_name==binding_name)){ + if !(varref_name==binding_name) { println!("uh oh, should match but doesn't:"); println!("varref: {:?}",varref); println!("binding: {:?}", bindings[binding_idx]); ast_util::display_sctable(get_sctable()); } assert_eq!(varref_name,binding_name); - if (bound_ident_check) { + if bound_ident_check { // we're checking bound-identifier=?, and the marks // should be the same, too: assert_eq!(varref_marks,binding_marks.clone()); @@ -1269,7 +1268,7 @@ mod test { let fail = (varref.segments.len() == 1) && (mtwt_resolve(varref.segments[0].identifier) == binding_name); // temp debugging: - if (fail) { + if fail { println!("failure on test {}",test_idx); println!("text of test case: \"{}\"", teststr); println!(""); diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index f3f947ec00d3d..52010b39a5446 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -20,7 +20,6 @@ use parse::token::get_ident_interner; use parse::token; use print::pprust; -use std::io; use std::io::File; use std::rc::Rc; use std::str; @@ -109,9 +108,9 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) None => return MacResult::dummy_expr() }; let file = res_rel_file(cx, sp, &Path::new(file)); - let bytes = match io::result(|| File::open(&file).read_to_end()) { + let bytes = match File::open(&file).read_to_end() { Err(e) => { - cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e.desc)); + cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e)); return MacResult::dummy_expr(); } Ok(bytes) => bytes, @@ -141,9 +140,9 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) None => return MacResult::dummy_expr() }; let file = res_rel_file(cx, sp, &Path::new(file)); - match io::result(|| File::open(&file).read_to_end()) { + match File::open(&file).read_to_end() { Err(e) => { - cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e.desc)); + cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e)); return MacResult::dummy_expr(); } Ok(bytes) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8f5bbc2cdad18..297ec6acf5105 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -861,6 +861,7 @@ pub fn noop_fold_stmt(s: &Stmt, folder: &mut T) -> SmallVector<@Stmt> #[cfg(test)] mod test { + use std::io; use ast; use util::parser_testing::{string_to_crate, matches_codepattern}; use parse::token; @@ -868,8 +869,9 @@ mod test { use super::*; // this version doesn't care about getting comments or docstrings in. - fn fake_print_crate(s: &mut pprust::State, crate: &ast::Crate) { - pprust::print_mod(s, &crate.module, crate.attrs); + fn fake_print_crate(s: &mut pprust::State, + crate: &ast::Crate) -> io::IoResult<()> { + pprust::print_mod(s, &crate.module, crate.attrs) } // change every identifier to "zz" diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index e2460b0171a20..e2aa9e3b3ee67 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -33,6 +33,11 @@ This API is completely unstable and subject to change. extern mod extra; extern mod term; +#[cfg(stage0)] +macro_rules! if_ok ( + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) +) + pub mod util { pub mod interner; #[cfg(test)] diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 7165e7b404f1c..f65bc3ad7a351 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -350,7 +350,8 @@ pub fn gather_comments_and_literals(span_diagnostic: path: ~str, srdr: &mut io::Reader) -> (~[Comment], ~[Literal]) { - let src = str::from_utf8_owned(srdr.read_to_end()).unwrap(); + let src = srdr.read_to_end().unwrap(); + let src = str::from_utf8_owned(src).unwrap(); let cm = CodeMap::new(); let filemap = cm.new_filemap(path, src); let rdr = lexer::new_low_level_string_reader(span_diagnostic, filemap); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index cec9f7c2d9f11..328f0e7f22187 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -19,7 +19,6 @@ use parse::attr::ParserAttr; use parse::parser::Parser; use std::cell::RefCell; -use std::io; use std::io::File; use std::str; @@ -232,10 +231,10 @@ pub fn file_to_filemap(sess: @ParseSess, path: &Path, spanopt: Option) None => sess.span_diagnostic.handler().fatal(msg), } }; - let bytes = match io::result(|| File::open(path).read_to_end()) { + let bytes = match File::open(path).read_to_end() { Ok(bytes) => bytes, Err(e) => { - err(format!("couldn't read {}: {}", path.display(), e.desc)); + err(format!("couldn't read {}: {}", path.display(), e)); unreachable!() } }; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 6d2acd3d803de..f1dd844fc7c68 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -588,8 +588,8 @@ impl BytesContainer for InternedString { } impl fmt::Show for InternedString { - fn fmt(obj: &InternedString, f: &mut fmt::Formatter) { - write!(f.buf, "{}", obj.string.as_slice()); + fn fmt(obj: &InternedString, f: &mut fmt::Formatter) -> fmt::Result { + write!(f.buf, "{}", obj.string.as_slice()) } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 3e1f5b4cfb353..f695226172321 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -292,16 +292,17 @@ impl Printer { pub fn replace_last_token(&mut self, t: Token) { self.token[self.right] = t; } - pub fn pretty_print(&mut self, t: Token) { + pub fn pretty_print(&mut self, t: Token) -> io::IoResult<()> { debug!("pp ~[{},{}]", self.left, self.right); match t { Eof => { if !self.scan_stack_empty { self.check_stack(0); let left = self.token[self.left].clone(); - self.advance_left(left, self.size[self.left]); + if_ok!(self.advance_left(left, self.size[self.left])); } self.indent(0); + Ok(()) } Begin(b) => { if self.scan_stack_empty { @@ -315,17 +316,19 @@ impl Printer { self.token[self.right] = t; self.size[self.right] = -self.right_total; self.scan_push(self.right); + Ok(()) } End => { if self.scan_stack_empty { debug!("pp End/print ~[{},{}]", self.left, self.right); - self.print(t, 0); + self.print(t, 0) } else { debug!("pp End/buffer ~[{},{}]", self.left, self.right); self.advance_right(); self.token[self.right] = t; self.size[self.right] = -1; self.scan_push(self.right); + Ok(()) } } Break(b) => { @@ -342,12 +345,13 @@ impl Printer { self.token[self.right] = t; self.size[self.right] = -self.right_total; self.right_total += b.blank_space; + Ok(()) } String(ref s, len) => { if self.scan_stack_empty { debug!("pp String('{}')/print ~[{},{}]", *s, self.left, self.right); - self.print(t.clone(), len); + self.print(t.clone(), len) } else { debug!("pp String('{}')/buffer ~[{},{}]", *s, self.left, self.right); @@ -355,12 +359,12 @@ impl Printer { self.token[self.right] = t.clone(); self.size[self.right] = len; self.right_total += len; - self.check_stream(); + self.check_stream() } } } } - pub fn check_stream(&mut self) { + pub fn check_stream(&mut self) -> io::IoResult<()> { debug!("check_stream ~[{}, {}] with left_total={}, right_total={}", self.left, self.right, self.left_total, self.right_total); if self.right_total - self.left_total > self.space { @@ -373,9 +377,12 @@ impl Printer { } } let left = self.token[self.left].clone(); - self.advance_left(left, self.size[self.left]); - if self.left != self.right { self.check_stream(); } + if_ok!(self.advance_left(left, self.size[self.left])); + if self.left != self.right { + if_ok!(self.check_stream()); + } } + Ok(()) } pub fn scan_push(&mut self, x: uint) { debug!("scan_push {}", x); @@ -413,11 +420,11 @@ impl Printer { self.right %= self.buf_len; assert!((self.right != self.left)); } - pub fn advance_left(&mut self, x: Token, L: int) { + pub fn advance_left(&mut self, x: Token, L: int) -> io::IoResult<()> { debug!("advnce_left ~[{},{}], sizeof({})={}", self.left, self.right, self.left, L); if L >= 0 { - self.print(x.clone(), L); + let ret = self.print(x.clone(), L); match x { Break(b) => self.left_total += b.blank_space, String(_, len) => { @@ -429,8 +436,11 @@ impl Printer { self.left += 1u; self.left %= self.buf_len; let left = self.token[self.left].clone(); - self.advance_left(left, self.size[self.left]); + if_ok!(self.advance_left(left, self.size[self.left])); } + ret + } else { + Ok(()) } } pub fn check_stack(&mut self, k: int) { @@ -456,11 +466,12 @@ impl Printer { } } } - pub fn print_newline(&mut self, amount: int) { + pub fn print_newline(&mut self, amount: int) -> io::IoResult<()> { debug!("NEWLINE {}", amount); - write!(self.out, "\n"); + let ret = write!(self.out, "\n"); self.pending_indentation = 0; self.indent(amount); + return ret; } pub fn indent(&mut self, amount: int) { debug!("INDENT {}", amount); @@ -478,14 +489,14 @@ impl Printer { } } } - pub fn print_str(&mut self, s: &str) { + pub fn print_str(&mut self, s: &str) -> io::IoResult<()> { while self.pending_indentation > 0 { - write!(self.out, " "); + if_ok!(write!(self.out, " ")); self.pending_indentation -= 1; } - write!(self.out, "{}", s); + write!(self.out, "{}", s) } - pub fn print(&mut self, x: Token, L: int) { + pub fn print(&mut self, x: Token, L: int) -> io::IoResult<()> { debug!("print {} {} (remaining line space={})", tok_str(x.clone()), L, self.space); debug!("{}", buf_str(self.token.clone(), @@ -509,12 +520,14 @@ impl Printer { pbreak: Fits }); } + Ok(()) } End => { debug!("print End -> pop End"); let print_stack = &mut self.print_stack; assert!((print_stack.len() != 0u)); print_stack.pop().unwrap(); + Ok(()) } Break(b) => { let top = self.get_top(); @@ -523,24 +536,28 @@ impl Printer { debug!("print Break({}) in fitting block", b.blank_space); self.space -= b.blank_space; self.indent(b.blank_space); + Ok(()) } Broken(Consistent) => { debug!("print Break({}+{}) in consistent block", top.offset, b.offset); - self.print_newline(top.offset + b.offset); + let ret = self.print_newline(top.offset + b.offset); self.space = self.margin - (top.offset + b.offset); + ret } Broken(Inconsistent) => { if L > self.space { debug!("print Break({}+{}) w/ newline in inconsistent", top.offset, b.offset); - self.print_newline(top.offset + b.offset); + let ret = self.print_newline(top.offset + b.offset); self.space = self.margin - (top.offset + b.offset); + ret } else { debug!("print Break({}) w/o newline in inconsistent", b.blank_space); self.indent(b.blank_space); self.space -= b.blank_space; + Ok(()) } } } @@ -550,7 +567,7 @@ impl Printer { assert_eq!(L, len); // assert!(L <= space); self.space -= len; - self.print_str(s); + self.print_str(s) } Eof => { // Eof should never get here. @@ -563,47 +580,59 @@ impl Printer { // Convenience functions to talk to the printer. // // "raw box" -pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) { +pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> { p.pretty_print(Begin(BeginToken { offset: indent as int, breaks: b - })); + })) } -pub fn ibox(p: &mut Printer, indent: uint) { rbox(p, indent, Inconsistent); } +pub fn ibox(p: &mut Printer, indent: uint) -> io::IoResult<()> { + rbox(p, indent, Inconsistent) +} -pub fn cbox(p: &mut Printer, indent: uint) { rbox(p, indent, Consistent); } +pub fn cbox(p: &mut Printer, indent: uint) -> io::IoResult<()> { + rbox(p, indent, Consistent) +} -pub fn break_offset(p: &mut Printer, n: uint, off: int) { +pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> { p.pretty_print(Break(BreakToken { offset: off, blank_space: n as int - })); + })) } -pub fn end(p: &mut Printer) { p.pretty_print(End); } +pub fn end(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(End) } -pub fn eof(p: &mut Printer) { p.pretty_print(Eof); } +pub fn eof(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(Eof) } -pub fn word(p: &mut Printer, wrd: &str) { - p.pretty_print(String(/* bad */ wrd.to_str(), wrd.len() as int)); +pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> { + p.pretty_print(String(/* bad */ wrd.to_str(), wrd.len() as int)) } -pub fn huge_word(p: &mut Printer, wrd: &str) { - p.pretty_print(String(/* bad */ wrd.to_str(), SIZE_INFINITY)); +pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> { + p.pretty_print(String(/* bad */ wrd.to_str(), SIZE_INFINITY)) } -pub fn zero_word(p: &mut Printer, wrd: &str) { - p.pretty_print(String(/* bad */ wrd.to_str(), 0)); +pub fn zero_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> { + p.pretty_print(String(/* bad */ wrd.to_str(), 0)) } -pub fn spaces(p: &mut Printer, n: uint) { break_offset(p, n, 0); } +pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> { + break_offset(p, n, 0) +} -pub fn zerobreak(p: &mut Printer) { spaces(p, 0u); } +pub fn zerobreak(p: &mut Printer) -> io::IoResult<()> { + spaces(p, 0u) +} -pub fn space(p: &mut Printer) { spaces(p, 1u); } +pub fn space(p: &mut Printer) -> io::IoResult<()> { + spaces(p, 1u) +} -pub fn hardbreak(p: &mut Printer) { spaces(p, SIZE_INFINITY as uint); } +pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> { + spaces(p, SIZE_INFINITY as uint) +} pub fn hardbreak_tok_offset(off: int) -> Token { Break(BreakToken {offset: off, blank_space: SIZE_INFINITY}) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 037c69eb918d1..e291583d121d7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -43,8 +43,8 @@ pub enum AnnNode<'a,'b> { } pub trait PpAnn { - fn pre(&self, _node: AnnNode) {} - fn post(&self, _node: AnnNode) {} + fn pre(&self, _node: AnnNode) -> io::IoResult<()> { Ok(()) } + fn post(&self, _node: AnnNode) -> io::IoResult<()> { Ok(()) } } pub struct NoAnn; @@ -67,20 +67,20 @@ pub struct State { ann: @PpAnn } -pub fn ibox(s: &mut State, u: uint) { +pub fn ibox(s: &mut State, u: uint) -> io::IoResult<()> { { let mut boxes = s.boxes.borrow_mut(); boxes.get().push(pp::Inconsistent); } - pp::ibox(&mut s.s, u); + pp::ibox(&mut s.s, u) } -pub fn end(s: &mut State) { +pub fn end(s: &mut State) -> io::IoResult<()> { { let mut boxes = s.boxes.borrow_mut(); boxes.get().pop().unwrap(); } - pp::end(&mut s.s); + pp::end(&mut s.s) } pub fn rust_printer(writer: ~io::Writer, intr: @IdentInterner) -> State { @@ -121,7 +121,7 @@ pub fn print_crate(cm: @CodeMap, input: &mut io::Reader, out: ~io::Writer, ann: @PpAnn, - is_expanded: bool) { + is_expanded: bool) -> io::IoResult<()> { let (cmnts, lits) = comments::gather_comments_and_literals( span_diagnostic, filename, @@ -147,13 +147,14 @@ pub fn print_crate(cm: @CodeMap, boxes: RefCell::new(~[]), ann: ann }; - print_crate_(&mut s, crate); + print_crate_(&mut s, crate) } -pub fn print_crate_(s: &mut State, crate: &ast::Crate) { - print_mod(s, &crate.module, crate.attrs); - print_remaining_comments(s); - eof(&mut s.s); +pub fn print_crate_(s: &mut State, crate: &ast::Crate) -> io::IoResult<()> { + if_ok!(print_mod(s, &crate.module, crate.attrs)); + if_ok!(print_remaining_comments(s)); + if_ok!(eof(&mut s.s)); + Ok(()) } pub fn ty_to_str(ty: &ast::Ty, intr: @IdentInterner) -> ~str { @@ -203,10 +204,10 @@ pub fn fun_to_str(decl: &ast::FnDecl, purity: ast::Purity, name: ast::Ident, let wr = ~MemWriter::new(); let mut s = rust_printer(wr as ~io::Writer, intr); print_fn(&mut s, decl, Some(purity), AbiSet::Rust(), - name, generics, opt_explicit_self, ast::Inherited); - end(&mut s); // Close the head box - end(&mut s); // Close the outer box - eof(&mut s.s); + name, generics, opt_explicit_self, ast::Inherited).unwrap(); + end(&mut s).unwrap(); // Close the head box + end(&mut s).unwrap(); // Close the outer box + eof(&mut s.s).unwrap(); unsafe { get_mem_writer(&mut s.s.out) } @@ -216,11 +217,11 @@ pub fn block_to_str(blk: &ast::Block, intr: @IdentInterner) -> ~str { let wr = ~MemWriter::new(); let mut s = rust_printer(wr as ~io::Writer, intr); // containing cbox, will be closed by print-block at } - cbox(&mut s, indent_unit); + cbox(&mut s, indent_unit).unwrap(); // head-ibox, will be closed by print-block after { - ibox(&mut s, 0u); - print_block(&mut s, blk); - eof(&mut s.s); + ibox(&mut s, 0u).unwrap(); + print_block(&mut s, blk).unwrap(); + eof(&mut s.s).unwrap(); unsafe { get_mem_writer(&mut s.s.out) } @@ -238,63 +239,73 @@ pub fn variant_to_str(var: &ast::Variant, intr: @IdentInterner) -> ~str { to_str(var, print_variant, intr) } -pub fn cbox(s: &mut State, u: uint) { +pub fn cbox(s: &mut State, u: uint) -> io::IoResult<()> { { let mut boxes = s.boxes.borrow_mut(); boxes.get().push(pp::Consistent); } - pp::cbox(&mut s.s, u); + pp::cbox(&mut s.s, u) } // "raw box" -pub fn rbox(s: &mut State, u: uint, b: pp::Breaks) { +pub fn rbox(s: &mut State, u: uint, b: pp::Breaks) -> io::IoResult<()> { { let mut boxes = s.boxes.borrow_mut(); boxes.get().push(b); } - pp::rbox(&mut s.s, u, b); + pp::rbox(&mut s.s, u, b) } -pub fn nbsp(s: &mut State) { word(&mut s.s, " "); } +pub fn nbsp(s: &mut State) -> io::IoResult<()> { word(&mut s.s, " ") } -pub fn word_nbsp(s: &mut State, w: &str) { word(&mut s.s, w); nbsp(s); } +pub fn word_nbsp(s: &mut State, w: &str) -> io::IoResult<()> { + if_ok!(word(&mut s.s, w)); + nbsp(s) +} -pub fn word_space(s: &mut State, w: &str) { word(&mut s.s, w); space(&mut s.s); } +pub fn word_space(s: &mut State, w: &str) -> io::IoResult<()> { + if_ok!(word(&mut s.s, w)); + space(&mut s.s) +} -pub fn popen(s: &mut State) { word(&mut s.s, "("); } +pub fn popen(s: &mut State) -> io::IoResult<()> { word(&mut s.s, "(") } -pub fn pclose(s: &mut State) { word(&mut s.s, ")"); } +pub fn pclose(s: &mut State) -> io::IoResult<()> { word(&mut s.s, ")") } -pub fn head(s: &mut State, w: &str) { +pub fn head(s: &mut State, w: &str) -> io::IoResult<()> { // outer-box is consistent - cbox(s, indent_unit); + if_ok!(cbox(s, indent_unit)); // head-box is inconsistent - ibox(s, w.len() + 1); + if_ok!(ibox(s, w.len() + 1)); // keyword that starts the head if !w.is_empty() { - word_nbsp(s, w); + if_ok!(word_nbsp(s, w)); } + Ok(()) } -pub fn bopen(s: &mut State) { - word(&mut s.s, "{"); - end(s); // close the head-box +pub fn bopen(s: &mut State) -> io::IoResult<()> { + if_ok!(word(&mut s.s, "{")); + if_ok!(end(s)); // close the head-box + Ok(()) } -pub fn bclose_(s: &mut State, span: codemap::Span, indented: uint) { - bclose_maybe_open(s, span, indented, true); +pub fn bclose_(s: &mut State, span: codemap::Span, + indented: uint) -> io::IoResult<()> { + bclose_maybe_open(s, span, indented, true) } pub fn bclose_maybe_open (s: &mut State, span: codemap::Span, - indented: uint, close_box: bool) { - maybe_print_comment(s, span.hi); - break_offset_if_not_bol(s, 1u, -(indented as int)); - word(&mut s.s, "}"); + indented: uint, close_box: bool) -> io::IoResult<()> { + if_ok!(maybe_print_comment(s, span.hi)); + if_ok!(break_offset_if_not_bol(s, 1u, -(indented as int))); + if_ok!(word(&mut s.s, "}")); if close_box { - end(s); // close the outer-box + if_ok!(end(s)); // close the outer-box } + Ok(()) } -pub fn bclose(s: &mut State, span: codemap::Span) { - bclose_(s, span, indent_unit); +pub fn bclose(s: &mut State, span: codemap::Span) -> io::IoResult<()> { + bclose_(s, span, indent_unit) } pub fn is_begin(s: &mut State) -> bool { @@ -316,15 +327,20 @@ pub fn in_cbox(s: &mut State) -> bool { return boxes.get()[len - 1u] == pp::Consistent; } -pub fn hardbreak_if_not_bol(s: &mut State) { +pub fn hardbreak_if_not_bol(s: &mut State) -> io::IoResult<()> { if !is_bol(s) { - hardbreak(&mut s.s) + if_ok!(hardbreak(&mut s.s)) } + Ok(()) +} +pub fn space_if_not_bol(s: &mut State) -> io::IoResult<()> { + if !is_bol(s) { if_ok!(space(&mut s.s)); } + Ok(()) } -pub fn space_if_not_bol(s: &mut State) { if !is_bol(s) { space(&mut s.s); } } -pub fn break_offset_if_not_bol(s: &mut State, n: uint, off: int) { +pub fn break_offset_if_not_bol(s: &mut State, n: uint, + off: int) -> io::IoResult<()> { if !is_bol(s) { - break_offset(&mut s.s, n, off); + if_ok!(break_offset(&mut s.s, n, off)); } else { if off != 0 && s.s.last_token().is_hardbreak_tok() { // We do something pretty sketchy here: tuck the nonzero @@ -333,26 +349,31 @@ pub fn break_offset_if_not_bol(s: &mut State, n: uint, off: int) { s.s.replace_last_token(pp::hardbreak_tok_offset(off)); } } + Ok(()) } // Synthesizes a comment that was not textually present in the original source // file. -pub fn synth_comment(s: &mut State, text: ~str) { - word(&mut s.s, "/*"); - space(&mut s.s); - word(&mut s.s, text); - space(&mut s.s); - word(&mut s.s, "*/"); -} - -pub fn commasep(s: &mut State, b: Breaks, elts: &[T], op: |&mut State, &T|) { - rbox(s, 0u, b); +pub fn synth_comment(s: &mut State, text: ~str) -> io::IoResult<()> { + if_ok!(word(&mut s.s, "/*")); + if_ok!(space(&mut s.s)); + if_ok!(word(&mut s.s, text)); + if_ok!(space(&mut s.s)); + if_ok!(word(&mut s.s, "*/")); + Ok(()) +} + +pub fn commasep(s: &mut State, b: Breaks, elts: &[T], + op: |&mut State, &T| -> io::IoResult<()>) + -> io::IoResult<()> +{ + if_ok!(rbox(s, 0u, b)); let mut first = true; for elt in elts.iter() { - if first { first = false; } else { word_space(s, ","); } - op(s, elt); + if first { first = false; } else { if_ok!(word_space(s, ",")); } + if_ok!(op(s, elt)); } - end(s); + end(s) } @@ -360,177 +381,200 @@ pub fn commasep_cmnt( s: &mut State, b: Breaks, elts: &[T], - op: |&mut State, &T|, - get_span: |&T| -> codemap::Span) { - rbox(s, 0u, b); + op: |&mut State, &T| -> io::IoResult<()>, + get_span: |&T| -> codemap::Span) -> io::IoResult<()> { + if_ok!(rbox(s, 0u, b)); let len = elts.len(); let mut i = 0u; for elt in elts.iter() { - maybe_print_comment(s, get_span(elt).hi); - op(s, elt); + if_ok!(maybe_print_comment(s, get_span(elt).hi)); + if_ok!(op(s, elt)); i += 1u; if i < len { - word(&mut s.s, ","); - maybe_print_trailing_comment(s, get_span(elt), - Some(get_span(&elts[i]).hi)); - space_if_not_bol(s); + if_ok!(word(&mut s.s, ",")); + if_ok!(maybe_print_trailing_comment(s, get_span(elt), + Some(get_span(&elts[i]).hi))); + if_ok!(space_if_not_bol(s)); } } - end(s); + end(s) } -pub fn commasep_exprs(s: &mut State, b: Breaks, exprs: &[@ast::Expr]) { - commasep_cmnt(s, b, exprs, |p, &e| print_expr(p, e), |e| e.span); +pub fn commasep_exprs(s: &mut State, b: Breaks, + exprs: &[@ast::Expr]) -> io::IoResult<()> { + commasep_cmnt(s, b, exprs, |p, &e| print_expr(p, e), |e| e.span) } -pub fn print_mod(s: &mut State, _mod: &ast::Mod, attrs: &[ast::Attribute]) { - print_inner_attributes(s, attrs); +pub fn print_mod(s: &mut State, _mod: &ast::Mod, + attrs: &[ast::Attribute]) -> io::IoResult<()> { + if_ok!(print_inner_attributes(s, attrs)); for vitem in _mod.view_items.iter() { - print_view_item(s, vitem); + if_ok!(print_view_item(s, vitem)); } - for item in _mod.items.iter() { print_item(s, *item); } + for item in _mod.items.iter() { + if_ok!(print_item(s, *item)); + } + Ok(()) } pub fn print_foreign_mod(s: &mut State, nmod: &ast::ForeignMod, - attrs: &[ast::Attribute]) { - print_inner_attributes(s, attrs); + attrs: &[ast::Attribute]) -> io::IoResult<()> { + if_ok!(print_inner_attributes(s, attrs)); for vitem in nmod.view_items.iter() { - print_view_item(s, vitem); + if_ok!(print_view_item(s, vitem)); + } + for item in nmod.items.iter() { + if_ok!(print_foreign_item(s, *item)); } - for item in nmod.items.iter() { print_foreign_item(s, *item); } + Ok(()) } -pub fn print_opt_lifetime(s: &mut State, lifetime: &Option) { +pub fn print_opt_lifetime(s: &mut State, + lifetime: &Option) -> io::IoResult<()> { for l in lifetime.iter() { - print_lifetime(s, l); - nbsp(s); + if_ok!(print_lifetime(s, l)); + if_ok!(nbsp(s)); } + Ok(()) } -pub fn print_type(s: &mut State, ty: &ast::Ty) { - maybe_print_comment(s, ty.span.lo); - ibox(s, 0u); +pub fn print_type(s: &mut State, ty: &ast::Ty) -> io::IoResult<()> { + if_ok!(maybe_print_comment(s, ty.span.lo)); + if_ok!(ibox(s, 0u)); match ty.node { - ast::TyNil => word(&mut s.s, "()"), - ast::TyBot => word(&mut s.s, "!"), - ast::TyBox(ty) => { word(&mut s.s, "@"); print_type(s, ty); } - ast::TyUniq(ty) => { word(&mut s.s, "~"); print_type(s, ty); } + ast::TyNil => if_ok!(word(&mut s.s, "()")), + ast::TyBot => if_ok!(word(&mut s.s, "!")), + ast::TyBox(ty) => { + if_ok!(word(&mut s.s, "@")); + if_ok!(print_type(s, ty)); + } + ast::TyUniq(ty) => { + if_ok!(word(&mut s.s, "~")); + if_ok!(print_type(s, ty)); + } ast::TyVec(ty) => { - word(&mut s.s, "["); - print_type(s, ty); - word(&mut s.s, "]"); + if_ok!(word(&mut s.s, "[")); + if_ok!(print_type(s, ty)); + if_ok!(word(&mut s.s, "]")); + } + ast::TyPtr(ref mt) => { + if_ok!(word(&mut s.s, "*")); + if_ok!(print_mt(s, mt)); } - ast::TyPtr(ref mt) => { word(&mut s.s, "*"); print_mt(s, mt); } ast::TyRptr(ref lifetime, ref mt) => { - word(&mut s.s, "&"); - print_opt_lifetime(s, lifetime); - print_mt(s, mt); + if_ok!(word(&mut s.s, "&")); + if_ok!(print_opt_lifetime(s, lifetime)); + if_ok!(print_mt(s, mt)); } ast::TyTup(ref elts) => { - popen(s); - commasep(s, Inconsistent, *elts, print_type_ref); + if_ok!(popen(s)); + if_ok!(commasep(s, Inconsistent, *elts, print_type_ref)); if elts.len() == 1 { - word(&mut s.s, ","); + if_ok!(word(&mut s.s, ",")); } - pclose(s); + if_ok!(pclose(s)); } ast::TyBareFn(f) => { let generics = ast::Generics { lifetimes: f.lifetimes.clone(), ty_params: opt_vec::Empty }; - print_ty_fn(s, Some(f.abis), None, &None, - f.purity, ast::Many, f.decl, None, &None, - Some(&generics), None); + if_ok!(print_ty_fn(s, Some(f.abis), None, &None, + f.purity, ast::Many, f.decl, None, &None, + Some(&generics), None)); } ast::TyClosure(f) => { let generics = ast::Generics { lifetimes: f.lifetimes.clone(), ty_params: opt_vec::Empty }; - print_ty_fn(s, None, Some(f.sigil), &f.region, - f.purity, f.onceness, f.decl, None, &f.bounds, - Some(&generics), None); + if_ok!(print_ty_fn(s, None, Some(f.sigil), &f.region, + f.purity, f.onceness, f.decl, None, &f.bounds, + Some(&generics), None)); + } + ast::TyPath(ref path, ref bounds, _) => { + if_ok!(print_bounded_path(s, path, bounds)); } - ast::TyPath(ref path, ref bounds, _) => print_bounded_path(s, path, bounds), ast::TyFixedLengthVec(ty, v) => { - word(&mut s.s, "["); - print_type(s, ty); - word(&mut s.s, ", .."); - print_expr(s, v); - word(&mut s.s, "]"); + if_ok!(word(&mut s.s, "[")); + if_ok!(print_type(s, ty)); + if_ok!(word(&mut s.s, ", ..")); + if_ok!(print_expr(s, v)); + if_ok!(word(&mut s.s, "]")); } ast::TyTypeof(e) => { - word(&mut s.s, "typeof("); - print_expr(s, e); - word(&mut s.s, ")"); + if_ok!(word(&mut s.s, "typeof(")); + if_ok!(print_expr(s, e)); + if_ok!(word(&mut s.s, ")")); } ast::TyInfer => { fail!("print_type shouldn't see a ty_infer"); } } - end(s); + end(s) } -pub fn print_type_ref(s: &mut State, ty: &P) { - print_type(s, *ty); +pub fn print_type_ref(s: &mut State, ty: &P) -> io::IoResult<()> { + print_type(s, *ty) } -pub fn print_foreign_item(s: &mut State, item: &ast::ForeignItem) { - hardbreak_if_not_bol(s); - maybe_print_comment(s, item.span.lo); - print_outer_attributes(s, item.attrs); +pub fn print_foreign_item(s: &mut State, + item: &ast::ForeignItem) -> io::IoResult<()> { + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, item.span.lo)); + if_ok!(print_outer_attributes(s, item.attrs)); match item.node { - ast::ForeignItemFn(decl, ref generics) => { - print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics, None, - item.vis); - end(s); // end head-ibox - word(&mut s.s, ";"); - end(s); // end the outer fn box - } - ast::ForeignItemStatic(t, m) => { - head(s, visibility_qualified(item.vis, "static")); - if m { - word_space(s, "mut"); + ast::ForeignItemFn(decl, ref generics) => { + if_ok!(print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics, + None, item.vis)); + if_ok!(end(s)); // end head-ibox + if_ok!(word(&mut s.s, ";")); + if_ok!(end(s)); // end the outer fn box + } + ast::ForeignItemStatic(t, m) => { + if_ok!(head(s, visibility_qualified(item.vis, "static"))); + if m { + if_ok!(word_space(s, "mut")); + } + if_ok!(print_ident(s, item.ident)); + if_ok!(word_space(s, ":")); + if_ok!(print_type(s, t)); + if_ok!(word(&mut s.s, ";")); + if_ok!(end(s)); // end the head-ibox + if_ok!(end(s)); // end the outer cbox } - print_ident(s, item.ident); - word_space(s, ":"); - print_type(s, t); - word(&mut s.s, ";"); - end(s); // end the head-ibox - end(s); // end the outer cbox - } } + Ok(()) } -pub fn print_item(s: &mut State, item: &ast::Item) { - hardbreak_if_not_bol(s); - maybe_print_comment(s, item.span.lo); - print_outer_attributes(s, item.attrs); +pub fn print_item(s: &mut State, item: &ast::Item) -> io::IoResult<()> { + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, item.span.lo)); + if_ok!(print_outer_attributes(s, item.attrs)); { let ann_node = NodeItem(s, item); - s.ann.pre(ann_node); + if_ok!(s.ann.pre(ann_node)); } match item.node { ast::ItemStatic(ty, m, expr) => { - head(s, visibility_qualified(item.vis, "static")); + if_ok!(head(s, visibility_qualified(item.vis, "static"))); if m == ast::MutMutable { - word_space(s, "mut"); + if_ok!(word_space(s, "mut")); } - print_ident(s, item.ident); - word_space(s, ":"); - print_type(s, ty); - space(&mut s.s); - end(s); // end the head-ibox + if_ok!(print_ident(s, item.ident)); + if_ok!(word_space(s, ":")); + if_ok!(print_type(s, ty)); + if_ok!(space(&mut s.s)); + if_ok!(end(s)); // end the head-ibox - word_space(s, "="); - print_expr(s, expr); - word(&mut s.s, ";"); - end(s); // end the outer cbox + if_ok!(word_space(s, "=")); + if_ok!(print_expr(s, expr)); + if_ok!(word(&mut s.s, ";")); + if_ok!(end(s)); // end the outer cbox } ast::ItemFn(decl, purity, abi, ref typarams, body) => { - print_fn( + if_ok!(print_fn( s, decl, Some(purity), @@ -539,150 +583,153 @@ pub fn print_item(s: &mut State, item: &ast::Item) { typarams, None, item.vis - ); - word(&mut s.s, " "); - print_block_with_attrs(s, body, item.attrs); + )); + if_ok!(word(&mut s.s, " ")); + if_ok!(print_block_with_attrs(s, body, item.attrs)); } ast::ItemMod(ref _mod) => { - head(s, visibility_qualified(item.vis, "mod")); - print_ident(s, item.ident); - nbsp(s); - bopen(s); - print_mod(s, _mod, item.attrs); - bclose(s, item.span); + if_ok!(head(s, visibility_qualified(item.vis, "mod"))); + if_ok!(print_ident(s, item.ident)); + if_ok!(nbsp(s)); + if_ok!(bopen(s)); + if_ok!(print_mod(s, _mod, item.attrs)); + if_ok!(bclose(s, item.span)); } ast::ItemForeignMod(ref nmod) => { - head(s, "extern"); - word_nbsp(s, nmod.abis.to_str()); - bopen(s); - print_foreign_mod(s, nmod, item.attrs); - bclose(s, item.span); + if_ok!(head(s, "extern")); + if_ok!(word_nbsp(s, nmod.abis.to_str())); + if_ok!(bopen(s)); + if_ok!(print_foreign_mod(s, nmod, item.attrs)); + if_ok!(bclose(s, item.span)); } ast::ItemTy(ty, ref params) => { - ibox(s, indent_unit); - ibox(s, 0u); - word_nbsp(s, visibility_qualified(item.vis, "type")); - print_ident(s, item.ident); - print_generics(s, params); - end(s); // end the inner ibox - - space(&mut s.s); - word_space(s, "="); - print_type(s, ty); - word(&mut s.s, ";"); - end(s); // end the outer ibox + if_ok!(ibox(s, indent_unit)); + if_ok!(ibox(s, 0u)); + if_ok!(word_nbsp(s, visibility_qualified(item.vis, "type"))); + if_ok!(print_ident(s, item.ident)); + if_ok!(print_generics(s, params)); + if_ok!(end(s)); // end the inner ibox + + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "=")); + if_ok!(print_type(s, ty)); + if_ok!(word(&mut s.s, ";")); + if_ok!(end(s)); // end the outer ibox } ast::ItemEnum(ref enum_definition, ref params) => { - print_enum_def( + if_ok!(print_enum_def( s, enum_definition, params, item.ident, item.span, item.vis - ); + )); } ast::ItemStruct(struct_def, ref generics) => { - head(s, visibility_qualified(item.vis, "struct")); - print_struct(s, struct_def, generics, item.ident, item.span); + if_ok!(head(s, visibility_qualified(item.vis, "struct"))); + if_ok!(print_struct(s, struct_def, generics, item.ident, item.span)); } ast::ItemImpl(ref generics, ref opt_trait, ty, ref methods) => { - head(s, visibility_qualified(item.vis, "impl")); + if_ok!(head(s, visibility_qualified(item.vis, "impl"))); if generics.is_parameterized() { - print_generics(s, generics); - space(&mut s.s); + if_ok!(print_generics(s, generics)); + if_ok!(space(&mut s.s)); } match opt_trait { &Some(ref t) => { - print_trait_ref(s, t); - space(&mut s.s); - word_space(s, "for"); + if_ok!(print_trait_ref(s, t)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "for")); } &None => () }; - print_type(s, ty); + if_ok!(print_type(s, ty)); - space(&mut s.s); - bopen(s); - print_inner_attributes(s, item.attrs); + if_ok!(space(&mut s.s)); + if_ok!(bopen(s)); + if_ok!(print_inner_attributes(s, item.attrs)); for meth in methods.iter() { - print_method(s, *meth); + if_ok!(print_method(s, *meth)); } - bclose(s, item.span); + if_ok!(bclose(s, item.span)); } ast::ItemTrait(ref generics, ref traits, ref methods) => { - head(s, visibility_qualified(item.vis, "trait")); - print_ident(s, item.ident); - print_generics(s, generics); + if_ok!(head(s, visibility_qualified(item.vis, "trait"))); + if_ok!(print_ident(s, item.ident)); + if_ok!(print_generics(s, generics)); if traits.len() != 0u { - word(&mut s.s, ":"); + if_ok!(word(&mut s.s, ":")); for (i, trait_) in traits.iter().enumerate() { - nbsp(s); + if_ok!(nbsp(s)); if i != 0 { - word_space(s, "+"); + if_ok!(word_space(s, "+")); } - print_path(s, &trait_.path, false); + if_ok!(print_path(s, &trait_.path, false)); } } - word(&mut s.s, " "); - bopen(s); + if_ok!(word(&mut s.s, " ")); + if_ok!(bopen(s)); for meth in methods.iter() { - print_trait_method(s, meth); + if_ok!(print_trait_method(s, meth)); } - bclose(s, item.span); + if_ok!(bclose(s, item.span)); } // I think it's reasonable to hide the context here: ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { - print_visibility(s, item.vis); - print_path(s, pth, false); - word(&mut s.s, "! "); - print_ident(s, item.ident); - cbox(s, indent_unit); - popen(s); - print_tts(s, &(tts.as_slice())); - pclose(s); - end(s); + if_ok!(print_visibility(s, item.vis)); + if_ok!(print_path(s, pth, false)); + if_ok!(word(&mut s.s, "! ")); + if_ok!(print_ident(s, item.ident)); + if_ok!(cbox(s, indent_unit)); + if_ok!(popen(s)); + if_ok!(print_tts(s, &(tts.as_slice()))); + if_ok!(pclose(s)); + if_ok!(end(s)); } } { let ann_node = NodeItem(s, item); - s.ann.post(ann_node); + if_ok!(s.ann.post(ann_node)); } + Ok(()) } -fn print_trait_ref(s: &mut State, t: &ast::TraitRef) { - print_path(s, &t.path, false); +fn print_trait_ref(s: &mut State, t: &ast::TraitRef) -> io::IoResult<()> { + print_path(s, &t.path, false) } pub fn print_enum_def(s: &mut State, enum_definition: &ast::EnumDef, generics: &ast::Generics, ident: ast::Ident, - span: codemap::Span, visibility: ast::Visibility) { - head(s, visibility_qualified(visibility, "enum")); - print_ident(s, ident); - print_generics(s, generics); - space(&mut s.s); - print_variants(s, enum_definition.variants, span); + span: codemap::Span, + visibility: ast::Visibility) -> io::IoResult<()> { + if_ok!(head(s, visibility_qualified(visibility, "enum"))); + if_ok!(print_ident(s, ident)); + if_ok!(print_generics(s, generics)); + if_ok!(space(&mut s.s)); + if_ok!(print_variants(s, enum_definition.variants, span)); + Ok(()) } pub fn print_variants(s: &mut State, variants: &[P], - span: codemap::Span) { - bopen(s); + span: codemap::Span) -> io::IoResult<()> { + if_ok!(bopen(s)); for &v in variants.iter() { - space_if_not_bol(s); - maybe_print_comment(s, v.span.lo); - print_outer_attributes(s, v.node.attrs); - ibox(s, indent_unit); - print_variant(s, v); - word(&mut s.s, ","); - end(s); - maybe_print_trailing_comment(s, v.span, None); + if_ok!(space_if_not_bol(s)); + if_ok!(maybe_print_comment(s, v.span.lo)); + if_ok!(print_outer_attributes(s, v.node.attrs)); + if_ok!(ibox(s, indent_unit)); + if_ok!(print_variant(s, v)); + if_ok!(word(&mut s.s, ",")); + if_ok!(end(s)); + if_ok!(maybe_print_trailing_comment(s, v.span, None)); } - bclose(s, span); + bclose(s, span) } pub fn visibility_to_str(vis: ast::Visibility) -> ~str { @@ -700,60 +747,62 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> ~str { } } -pub fn print_visibility(s: &mut State, vis: ast::Visibility) { +pub fn print_visibility(s: &mut State, vis: ast::Visibility) -> io::IoResult<()> { match vis { ast::Private | ast::Public => - word_nbsp(s, visibility_to_str(vis)), + if_ok!(word_nbsp(s, visibility_to_str(vis))), ast::Inherited => () } + Ok(()) } pub fn print_struct(s: &mut State, struct_def: &ast::StructDef, generics: &ast::Generics, ident: ast::Ident, - span: codemap::Span) { - print_ident(s, ident); - print_generics(s, generics); + span: codemap::Span) -> io::IoResult<()> { + if_ok!(print_ident(s, ident)); + if_ok!(print_generics(s, generics)); if ast_util::struct_def_is_tuple_like(struct_def) { if !struct_def.fields.is_empty() { - popen(s); - commasep(s, Inconsistent, struct_def.fields, |s, field| { + if_ok!(popen(s)); + if_ok!(commasep(s, Inconsistent, struct_def.fields, |s, field| { match field.node.kind { ast::NamedField(..) => fail!("unexpected named field"), ast::UnnamedField => { - maybe_print_comment(s, field.span.lo); - print_type(s, field.node.ty); + if_ok!(maybe_print_comment(s, field.span.lo)); + if_ok!(print_type(s, field.node.ty)); } } - }); - pclose(s); + Ok(()) + })); + if_ok!(pclose(s)); } - word(&mut s.s, ";"); - end(s); - end(s); // close the outer-box + if_ok!(word(&mut s.s, ";")); + if_ok!(end(s)); + end(s) // close the outer-box } else { - nbsp(s); - bopen(s); - hardbreak_if_not_bol(s); + if_ok!(nbsp(s)); + if_ok!(bopen(s)); + if_ok!(hardbreak_if_not_bol(s)); for field in struct_def.fields.iter() { match field.node.kind { ast::UnnamedField => fail!("unexpected unnamed field"), ast::NamedField(ident, visibility) => { - hardbreak_if_not_bol(s); - maybe_print_comment(s, field.span.lo); - print_outer_attributes(s, field.node.attrs); - print_visibility(s, visibility); - print_ident(s, ident); - word_nbsp(s, ":"); - print_type(s, field.node.ty); - word(&mut s.s, ","); + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, field.span.lo)); + if_ok!(print_outer_attributes(s, field.node.attrs)); + if_ok!(print_visibility(s, visibility)); + if_ok!(print_ident(s, ident)); + if_ok!(word_nbsp(s, ":")); + if_ok!(print_type(s, field.node.ty)); + if_ok!(word(&mut s.s, ",")); } } } - bclose(s, span); + bclose(s, span) } } @@ -764,191 +813,215 @@ pub fn print_struct(s: &mut State, /// appropriate macro, transcribe back into the grammar we just parsed from, /// and then pretty-print the resulting AST nodes (so, e.g., we print /// expression arguments as expressions). It can be done! I think. -pub fn print_tt(s: &mut State, tt: &ast::TokenTree) { +pub fn print_tt(s: &mut State, tt: &ast::TokenTree) -> io::IoResult<()> { match *tt { - ast::TTDelim(ref tts) => print_tts(s, &(tts.as_slice())), - ast::TTTok(_, ref tk) => { - word(&mut s.s, parse::token::to_str(s.intr, tk)); - } - ast::TTSeq(_, ref tts, ref sep, zerok) => { - word(&mut s.s, "$("); - for tt_elt in (*tts).iter() { print_tt(s, tt_elt); } - word(&mut s.s, ")"); - match *sep { - Some(ref tk) => word(&mut s.s, parse::token::to_str(s.intr, tk)), - None => () + ast::TTDelim(ref tts) => print_tts(s, &(tts.as_slice())), + ast::TTTok(_, ref tk) => { + word(&mut s.s, parse::token::to_str(s.intr, tk)) + } + ast::TTSeq(_, ref tts, ref sep, zerok) => { + if_ok!(word(&mut s.s, "$(")); + for tt_elt in (*tts).iter() { + if_ok!(print_tt(s, tt_elt)); + } + if_ok!(word(&mut s.s, ")")); + match *sep { + Some(ref tk) => { + if_ok!(word(&mut s.s, parse::token::to_str(s.intr, tk))); + } + None => () + } + word(&mut s.s, if zerok { "*" } else { "+" }) + } + ast::TTNonterminal(_, name) => { + if_ok!(word(&mut s.s, "$")); + print_ident(s, name) } - word(&mut s.s, if zerok { "*" } else { "+" }); - } - ast::TTNonterminal(_, name) => { - word(&mut s.s, "$"); - print_ident(s, name); - } } } -pub fn print_tts(s: &mut State, tts: & &[ast::TokenTree]) { - ibox(s, 0); +pub fn print_tts(s: &mut State, tts: & &[ast::TokenTree]) -> io::IoResult<()> { + if_ok!(ibox(s, 0)); for (i, tt) in tts.iter().enumerate() { if i != 0 { - space(&mut s.s); + if_ok!(space(&mut s.s)); } - print_tt(s, tt); + if_ok!(print_tt(s, tt)); } - end(s); + end(s) } -pub fn print_variant(s: &mut State, v: &ast::Variant) { - print_visibility(s, v.node.vis); +pub fn print_variant(s: &mut State, v: &ast::Variant) -> io::IoResult<()> { + if_ok!(print_visibility(s, v.node.vis)); match v.node.kind { ast::TupleVariantKind(ref args) => { - print_ident(s, v.node.name); + if_ok!(print_ident(s, v.node.name)); if !args.is_empty() { - popen(s); - fn print_variant_arg(s: &mut State, arg: &ast::VariantArg) { - print_type(s, arg.ty); + if_ok!(popen(s)); + fn print_variant_arg(s: &mut State, + arg: &ast::VariantArg) -> io::IoResult<()> { + print_type(s, arg.ty) } - commasep(s, Consistent, *args, print_variant_arg); - pclose(s); + if_ok!(commasep(s, Consistent, *args, print_variant_arg)); + if_ok!(pclose(s)); } } ast::StructVariantKind(struct_def) => { - head(s, ""); + if_ok!(head(s, "")); let generics = ast_util::empty_generics(); - print_struct(s, struct_def, &generics, v.node.name, v.span); + if_ok!(print_struct(s, struct_def, &generics, v.node.name, v.span)); } } match v.node.disr_expr { Some(d) => { - space(&mut s.s); - word_space(s, "="); - print_expr(s, d); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "=")); + if_ok!(print_expr(s, d)); } _ => () } -} - -pub fn print_ty_method(s: &mut State, m: &ast::TypeMethod) { - hardbreak_if_not_bol(s); - maybe_print_comment(s, m.span.lo); - print_outer_attributes(s, m.attrs); - print_ty_fn(s, - None, - None, - &None, - m.purity, - ast::Many, - m.decl, - Some(m.ident), - &None, - Some(&m.generics), - Some(m.explicit_self.node)); - word(&mut s.s, ";"); -} - -pub fn print_trait_method(s: &mut State, m: &ast::TraitMethod) { + Ok(()) +} + +pub fn print_ty_method(s: &mut State, m: &ast::TypeMethod) -> io::IoResult<()> { + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, m.span.lo)); + if_ok!(print_outer_attributes(s, m.attrs)); + if_ok!(print_ty_fn(s, + None, + None, + &None, + m.purity, + ast::Many, + m.decl, + Some(m.ident), + &None, + Some(&m.generics), + Some(m.explicit_self.node))); + word(&mut s.s, ";") +} + +pub fn print_trait_method(s: &mut State, + m: &ast::TraitMethod) -> io::IoResult<()> { match *m { Required(ref ty_m) => print_ty_method(s, ty_m), Provided(m) => print_method(s, m) } } -pub fn print_method(s: &mut State, meth: &ast::Method) { - hardbreak_if_not_bol(s); - maybe_print_comment(s, meth.span.lo); - print_outer_attributes(s, meth.attrs); - print_fn(s, meth.decl, Some(meth.purity), AbiSet::Rust(), - meth.ident, &meth.generics, Some(meth.explicit_self.node), - meth.vis); - word(&mut s.s, " "); - print_block_with_attrs(s, meth.body, meth.attrs); +pub fn print_method(s: &mut State, meth: &ast::Method) -> io::IoResult<()> { + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, meth.span.lo)); + if_ok!(print_outer_attributes(s, meth.attrs)); + if_ok!(print_fn(s, meth.decl, Some(meth.purity), AbiSet::Rust(), + meth.ident, &meth.generics, Some(meth.explicit_self.node), + meth.vis)); + if_ok!(word(&mut s.s, " ")); + print_block_with_attrs(s, meth.body, meth.attrs) } -pub fn print_outer_attributes(s: &mut State, attrs: &[ast::Attribute]) { +pub fn print_outer_attributes(s: &mut State, + attrs: &[ast::Attribute]) -> io::IoResult<()> { let mut count = 0; for attr in attrs.iter() { match attr.node.style { - ast::AttrOuter => { print_attribute(s, attr); count += 1; } + ast::AttrOuter => { + if_ok!(print_attribute(s, attr)); + count += 1; + } _ => {/* fallthrough */ } } } - if count > 0 { hardbreak_if_not_bol(s); } + if count > 0 { + if_ok!(hardbreak_if_not_bol(s)); + } + Ok(()) } -pub fn print_inner_attributes(s: &mut State, attrs: &[ast::Attribute]) { +pub fn print_inner_attributes(s: &mut State, + attrs: &[ast::Attribute]) -> io::IoResult<()> { let mut count = 0; for attr in attrs.iter() { match attr.node.style { ast::AttrInner => { - print_attribute(s, attr); + if_ok!(print_attribute(s, attr)); if !attr.node.is_sugared_doc { - word(&mut s.s, ";"); + if_ok!(word(&mut s.s, ";")); } count += 1; } _ => {/* fallthrough */ } } } - if count > 0 { hardbreak_if_not_bol(s); } + if count > 0 { + if_ok!(hardbreak_if_not_bol(s)); + } + Ok(()) } -pub fn print_attribute(s: &mut State, attr: &ast::Attribute) { - hardbreak_if_not_bol(s); - maybe_print_comment(s, attr.span.lo); +pub fn print_attribute(s: &mut State, attr: &ast::Attribute) -> io::IoResult<()> { + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, attr.span.lo)); if attr.node.is_sugared_doc { let comment = attr.value_str().unwrap(); - word(&mut s.s, comment.get()); + if_ok!(word(&mut s.s, comment.get())); } else { - word(&mut s.s, "#["); - print_meta_item(s, attr.meta()); - word(&mut s.s, "]"); + if_ok!(word(&mut s.s, "#[")); + if_ok!(print_meta_item(s, attr.meta())); + if_ok!(word(&mut s.s, "]")); } + Ok(()) } -pub fn print_stmt(s: &mut State, st: &ast::Stmt) { - maybe_print_comment(s, st.span.lo); +pub fn print_stmt(s: &mut State, st: &ast::Stmt) -> io::IoResult<()> { + if_ok!(maybe_print_comment(s, st.span.lo)); match st.node { ast::StmtDecl(decl, _) => { - print_decl(s, decl); + if_ok!(print_decl(s, decl)); } ast::StmtExpr(expr, _) => { - space_if_not_bol(s); - print_expr(s, expr); + if_ok!(space_if_not_bol(s)); + if_ok!(print_expr(s, expr)); } ast::StmtSemi(expr, _) => { - space_if_not_bol(s); - print_expr(s, expr); - word(&mut s.s, ";"); + if_ok!(space_if_not_bol(s)); + if_ok!(print_expr(s, expr)); + if_ok!(word(&mut s.s, ";")); } ast::StmtMac(ref mac, semi) => { - space_if_not_bol(s); - print_mac(s, mac); - if semi { word(&mut s.s, ";"); } + if_ok!(space_if_not_bol(s)); + if_ok!(print_mac(s, mac)); + if semi { + if_ok!(word(&mut s.s, ";")); + } } } - if parse::classify::stmt_ends_with_semi(st) { word(&mut s.s, ";"); } - maybe_print_trailing_comment(s, st.span, None); + if parse::classify::stmt_ends_with_semi(st) { + if_ok!(word(&mut s.s, ";")); + } + maybe_print_trailing_comment(s, st.span, None) } -pub fn print_block(s: &mut State, blk: &ast::Block) { - print_possibly_embedded_block(s, blk, BlockNormal, indent_unit); +pub fn print_block(s: &mut State, blk: &ast::Block) -> io::IoResult<()> { + print_possibly_embedded_block(s, blk, BlockNormal, indent_unit) } -pub fn print_block_unclosed(s: &mut State, blk: &ast::Block) { +pub fn print_block_unclosed(s: &mut State, blk: &ast::Block) -> io::IoResult<()> { print_possibly_embedded_block_(s, blk, BlockNormal, indent_unit, &[], - false); + false) } -pub fn print_block_unclosed_indent(s: &mut State, blk: &ast::Block, indented: uint) { - print_possibly_embedded_block_(s, blk, BlockNormal, indented, &[], false); +pub fn print_block_unclosed_indent(s: &mut State, blk: &ast::Block, + indented: uint) -> io::IoResult<()> { + print_possibly_embedded_block_(s, blk, BlockNormal, indented, &[], false) } pub fn print_block_with_attrs(s: &mut State, blk: &ast::Block, - attrs: &[ast::Attribute]) { + attrs: &[ast::Attribute]) -> io::IoResult<()> { print_possibly_embedded_block_(s, blk, BlockNormal, indent_unit, attrs, - true); + true) } enum EmbedType { @@ -959,9 +1032,9 @@ enum EmbedType { pub fn print_possibly_embedded_block(s: &mut State, blk: &ast::Block, embedded: EmbedType, - indented: uint) { + indented: uint) -> io::IoResult<()> { print_possibly_embedded_block_( - s, blk, embedded, indented, &[], true); + s, blk, embedded, indented, &[], true) } pub fn print_possibly_embedded_block_(s: &mut State, @@ -969,102 +1042,106 @@ pub fn print_possibly_embedded_block_(s: &mut State, embedded: EmbedType, indented: uint, attrs: &[ast::Attribute], - close_box: bool) { + close_box: bool) -> io::IoResult<()> { match blk.rules { - ast::UnsafeBlock(..) => word_space(s, "unsafe"), + ast::UnsafeBlock(..) => if_ok!(word_space(s, "unsafe")), ast::DefaultBlock => () } - maybe_print_comment(s, blk.span.lo); + if_ok!(maybe_print_comment(s, blk.span.lo)); { let ann_node = NodeBlock(s, blk); - s.ann.pre(ann_node); + if_ok!(s.ann.pre(ann_node)); } - match embedded { + if_ok!(match embedded { BlockBlockFn => end(s), BlockNormal => bopen(s) - } + }); - print_inner_attributes(s, attrs); + if_ok!(print_inner_attributes(s, attrs)); - for vi in blk.view_items.iter() { print_view_item(s, vi); } + for vi in blk.view_items.iter() { + if_ok!(print_view_item(s, vi)); + } for st in blk.stmts.iter() { - print_stmt(s, *st); + if_ok!(print_stmt(s, *st)); } match blk.expr { Some(expr) => { - space_if_not_bol(s); - print_expr(s, expr); - maybe_print_trailing_comment(s, expr.span, Some(blk.span.hi)); + if_ok!(space_if_not_bol(s)); + if_ok!(print_expr(s, expr)); + if_ok!(maybe_print_trailing_comment(s, expr.span, Some(blk.span.hi))); } _ => () } - bclose_maybe_open(s, blk.span, indented, close_box); + if_ok!(bclose_maybe_open(s, blk.span, indented, close_box)); { let ann_node = NodeBlock(s, blk); - s.ann.post(ann_node); + if_ok!(s.ann.post(ann_node)); } + Ok(()) } pub fn print_if(s: &mut State, test: &ast::Expr, blk: &ast::Block, - elseopt: Option<@ast::Expr>, chk: bool) { - head(s, "if"); - if chk { word_nbsp(s, "check"); } - print_expr(s, test); - space(&mut s.s); - print_block(s, blk); - fn do_else(s: &mut State, els: Option<@ast::Expr>) { + elseopt: Option<@ast::Expr>, chk: bool) -> io::IoResult<()> { + if_ok!(head(s, "if")); + if chk { if_ok!(word_nbsp(s, "check")); } + if_ok!(print_expr(s, test)); + if_ok!(space(&mut s.s)); + if_ok!(print_block(s, blk)); + fn do_else(s: &mut State, els: Option<@ast::Expr>) -> io::IoResult<()> { match els { - Some(_else) => { - match _else.node { - // "another else-if" - ast::ExprIf(i, t, e) => { - cbox(s, indent_unit - 1u); - ibox(s, 0u); - word(&mut s.s, " else if "); - print_expr(s, i); - space(&mut s.s); - print_block(s, t); - do_else(s, e); - } - // "final else" - ast::ExprBlock(b) => { - cbox(s, indent_unit - 1u); - ibox(s, 0u); - word(&mut s.s, " else "); - print_block(s, b); - } - // BLEAH, constraints would be great here - _ => { - fail!("print_if saw if with weird alternative"); - } + Some(_else) => { + match _else.node { + // "another else-if" + ast::ExprIf(i, t, e) => { + if_ok!(cbox(s, indent_unit - 1u)); + if_ok!(ibox(s, 0u)); + if_ok!(word(&mut s.s, " else if ")); + if_ok!(print_expr(s, i)); + if_ok!(space(&mut s.s)); + if_ok!(print_block(s, t)); + if_ok!(do_else(s, e)); + } + // "final else" + ast::ExprBlock(b) => { + if_ok!(cbox(s, indent_unit - 1u)); + if_ok!(ibox(s, 0u)); + if_ok!(word(&mut s.s, " else ")); + if_ok!(print_block(s, b)); + } + // BLEAH, constraints would be great here + _ => { + fail!("print_if saw if with weird alternative"); + } + } } - } - _ => {/* fall through */ } + _ => {/* fall through */ } } + Ok(()) } - do_else(s, elseopt); + do_else(s, elseopt) } -pub fn print_mac(s: &mut State, m: &ast::Mac) { +pub fn print_mac(s: &mut State, m: &ast::Mac) -> io::IoResult<()> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { - print_path(s, pth, false); - word(&mut s.s, "!"); - popen(s); - print_tts(s, &tts.as_slice()); - pclose(s); + if_ok!(print_path(s, pth, false)); + if_ok!(word(&mut s.s, "!")); + if_ok!(popen(s)); + if_ok!(print_tts(s, &tts.as_slice())); + pclose(s) } } } -pub fn print_expr_vstore(s: &mut State, t: ast::ExprVstore) { +pub fn print_expr_vstore(s: &mut State, t: ast::ExprVstore) -> io::IoResult<()> { match t { ast::ExprVstoreUniq => word(&mut s.s, "~"), ast::ExprVstoreSlice => word(&mut s.s, "&"), ast::ExprVstoreMutSlice => { - word(&mut s.s, "&"); - word(&mut s.s, "mut"); + if_ok!(word(&mut s.s, "&")); + word(&mut s.s, "mut") } } } @@ -1072,222 +1149,227 @@ pub fn print_expr_vstore(s: &mut State, t: ast::ExprVstore) { pub fn print_call_pre(s: &mut State, sugar: ast::CallSugar, base_args: &mut ~[@ast::Expr]) - -> Option<@ast::Expr> { + -> io::IoResult> { match sugar { ast::ForSugar => { - head(s, "for"); - Some(base_args.pop().unwrap()) + if_ok!(head(s, "for")); + Ok(Some(base_args.pop().unwrap())) } - ast::NoSugar => None + ast::NoSugar => Ok(None) } } pub fn print_call_post(s: &mut State, sugar: ast::CallSugar, blk: &Option<@ast::Expr>, - base_args: &mut ~[@ast::Expr]) { + base_args: &mut ~[@ast::Expr]) -> io::IoResult<()> { if sugar == ast::NoSugar || !base_args.is_empty() { - popen(s); - commasep_exprs(s, Inconsistent, *base_args); - pclose(s); + if_ok!(popen(s)); + if_ok!(commasep_exprs(s, Inconsistent, *base_args)); + if_ok!(pclose(s)); } if sugar != ast::NoSugar { - nbsp(s); + if_ok!(nbsp(s)); // not sure if this can happen - print_expr(s, blk.unwrap()); + if_ok!(print_expr(s, blk.unwrap())); } + Ok(()) } -pub fn print_expr(s: &mut State, expr: &ast::Expr) { - fn print_field(s: &mut State, field: &ast::Field) { - ibox(s, indent_unit); - print_ident(s, field.ident.node); - word_space(s, ":"); - print_expr(s, field.expr); - end(s); +pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> { + fn print_field(s: &mut State, field: &ast::Field) -> io::IoResult<()> { + if_ok!(ibox(s, indent_unit)); + if_ok!(print_ident(s, field.ident.node)); + if_ok!(word_space(s, ":")); + if_ok!(print_expr(s, field.expr)); + if_ok!(end(s)); + Ok(()) } fn get_span(field: &ast::Field) -> codemap::Span { return field.span; } - maybe_print_comment(s, expr.span.lo); - ibox(s, indent_unit); + if_ok!(maybe_print_comment(s, expr.span.lo)); + if_ok!(ibox(s, indent_unit)); { let ann_node = NodeExpr(s, expr); - s.ann.pre(ann_node); + if_ok!(s.ann.pre(ann_node)); } match expr.node { ast::ExprVstore(e, v) => { - print_expr_vstore(s, v); - print_expr(s, e); + if_ok!(print_expr_vstore(s, v)); + if_ok!(print_expr(s, e)); }, ast::ExprBox(p, e) => { - word(&mut s.s, "box"); - word(&mut s.s, "("); - print_expr(s, p); - word_space(s, ")"); - print_expr(s, e); + if_ok!(word(&mut s.s, "box")); + if_ok!(word(&mut s.s, "(")); + if_ok!(print_expr(s, p)); + if_ok!(word_space(s, ")")); + if_ok!(print_expr(s, e)); } ast::ExprVec(ref exprs, mutbl) => { - ibox(s, indent_unit); - word(&mut s.s, "["); + if_ok!(ibox(s, indent_unit)); + if_ok!(word(&mut s.s, "[")); if mutbl == ast::MutMutable { - word(&mut s.s, "mut"); - if exprs.len() > 0u { nbsp(s); } + if_ok!(word(&mut s.s, "mut")); + if exprs.len() > 0u { if_ok!(nbsp(s)); } } - commasep_exprs(s, Inconsistent, *exprs); - word(&mut s.s, "]"); - end(s); + if_ok!(commasep_exprs(s, Inconsistent, *exprs)); + if_ok!(word(&mut s.s, "]")); + if_ok!(end(s)); } ast::ExprRepeat(element, count, mutbl) => { - ibox(s, indent_unit); - word(&mut s.s, "["); + if_ok!(ibox(s, indent_unit)); + if_ok!(word(&mut s.s, "[")); if mutbl == ast::MutMutable { - word(&mut s.s, "mut"); - nbsp(s); + if_ok!(word(&mut s.s, "mut")); + if_ok!(nbsp(s)); } - print_expr(s, element); - word(&mut s.s, ","); - word(&mut s.s, ".."); - print_expr(s, count); - word(&mut s.s, "]"); - end(s); + if_ok!(print_expr(s, element)); + if_ok!(word(&mut s.s, ",")); + if_ok!(word(&mut s.s, "..")); + if_ok!(print_expr(s, count)); + if_ok!(word(&mut s.s, "]")); + if_ok!(end(s)); } ast::ExprStruct(ref path, ref fields, wth) => { - print_path(s, path, true); - word(&mut s.s, "{"); - commasep_cmnt(s, Consistent, (*fields), print_field, get_span); + if_ok!(print_path(s, path, true)); + if_ok!(word(&mut s.s, "{")); + if_ok!(commasep_cmnt(s, Consistent, (*fields), print_field, get_span)); match wth { Some(expr) => { - ibox(s, indent_unit); + if_ok!(ibox(s, indent_unit)); if !fields.is_empty() { - word(&mut s.s, ","); - space(&mut s.s); + if_ok!(word(&mut s.s, ",")); + if_ok!(space(&mut s.s)); } - word(&mut s.s, ".."); - print_expr(s, expr); - end(s); + if_ok!(word(&mut s.s, "..")); + if_ok!(print_expr(s, expr)); + if_ok!(end(s)); } - _ => (word(&mut s.s, ",")) + _ => if_ok!(word(&mut s.s, ",")) } - word(&mut s.s, "}"); + if_ok!(word(&mut s.s, "}")); } ast::ExprTup(ref exprs) => { - popen(s); - commasep_exprs(s, Inconsistent, *exprs); + if_ok!(popen(s)); + if_ok!(commasep_exprs(s, Inconsistent, *exprs)); if exprs.len() == 1 { - word(&mut s.s, ","); + if_ok!(word(&mut s.s, ",")); } - pclose(s); + if_ok!(pclose(s)); } ast::ExprCall(func, ref args, sugar) => { let mut base_args = (*args).clone(); - let blk = print_call_pre(s, sugar, &mut base_args); - print_expr(s, func); - print_call_post(s, sugar, &blk, &mut base_args); + let blk = if_ok!(print_call_pre(s, sugar, &mut base_args)); + if_ok!(print_expr(s, func)); + if_ok!(print_call_post(s, sugar, &blk, &mut base_args)); } ast::ExprMethodCall(_, ident, ref tys, ref args, sugar) => { let mut base_args = args.slice_from(1).to_owned(); - let blk = print_call_pre(s, sugar, &mut base_args); - print_expr(s, args[0]); - word(&mut s.s, "."); - print_ident(s, ident); + let blk = if_ok!(print_call_pre(s, sugar, &mut base_args)); + if_ok!(print_expr(s, args[0])); + if_ok!(word(&mut s.s, ".")); + if_ok!(print_ident(s, ident)); if tys.len() > 0u { - word(&mut s.s, "::<"); - commasep(s, Inconsistent, *tys, print_type_ref); - word(&mut s.s, ">"); + if_ok!(word(&mut s.s, "::<")); + if_ok!(commasep(s, Inconsistent, *tys, print_type_ref)); + if_ok!(word(&mut s.s, ">")); } - print_call_post(s, sugar, &blk, &mut base_args); + if_ok!(print_call_post(s, sugar, &blk, &mut base_args)); } ast::ExprBinary(_, op, lhs, rhs) => { - print_expr(s, lhs); - space(&mut s.s); - word_space(s, ast_util::binop_to_str(op)); - print_expr(s, rhs); + if_ok!(print_expr(s, lhs)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, ast_util::binop_to_str(op))); + if_ok!(print_expr(s, rhs)); } ast::ExprUnary(_, op, expr) => { - word(&mut s.s, ast_util::unop_to_str(op)); - print_expr(s, expr); + if_ok!(word(&mut s.s, ast_util::unop_to_str(op))); + if_ok!(print_expr(s, expr)); } ast::ExprAddrOf(m, expr) => { - word(&mut s.s, "&"); - print_mutability(s, m); + if_ok!(word(&mut s.s, "&")); + if_ok!(print_mutability(s, m)); // Avoid `& &e` => `&&e`. match (m, &expr.node) { - (ast::MutImmutable, &ast::ExprAddrOf(..)) => space(&mut s.s), + (ast::MutImmutable, &ast::ExprAddrOf(..)) => if_ok!(space(&mut s.s)), _ => { } } - print_expr(s, expr); + if_ok!(print_expr(s, expr)); } - ast::ExprLit(lit) => print_literal(s, lit), + ast::ExprLit(lit) => if_ok!(print_literal(s, lit)), ast::ExprCast(expr, ty) => { - print_expr(s, expr); - space(&mut s.s); - word_space(s, "as"); - print_type(s, ty); + if_ok!(print_expr(s, expr)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "as")); + if_ok!(print_type(s, ty)); } ast::ExprIf(test, blk, elseopt) => { - print_if(s, test, blk, elseopt, false); + if_ok!(print_if(s, test, blk, elseopt, false)); } ast::ExprWhile(test, blk) => { - head(s, "while"); - print_expr(s, test); - space(&mut s.s); - print_block(s, blk); + if_ok!(head(s, "while")); + if_ok!(print_expr(s, test)); + if_ok!(space(&mut s.s)); + if_ok!(print_block(s, blk)); } ast::ExprForLoop(pat, iter, blk, opt_ident) => { for ident in opt_ident.iter() { - word(&mut s.s, "'"); - print_ident(s, *ident); - word_space(s, ":"); - } - head(s, "for"); - print_pat(s, pat); - space(&mut s.s); - word_space(s, "in"); - print_expr(s, iter); - space(&mut s.s); - print_block(s, blk); + if_ok!(word(&mut s.s, "'")); + if_ok!(print_ident(s, *ident)); + if_ok!(word_space(s, ":")); + } + if_ok!(head(s, "for")); + if_ok!(print_pat(s, pat)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "in")); + if_ok!(print_expr(s, iter)); + if_ok!(space(&mut s.s)); + if_ok!(print_block(s, blk)); } ast::ExprLoop(blk, opt_ident) => { for ident in opt_ident.iter() { - word(&mut s.s, "'"); - print_ident(s, *ident); - word_space(s, ":"); + if_ok!(word(&mut s.s, "'")); + if_ok!(print_ident(s, *ident)); + if_ok!(word_space(s, ":")); } - head(s, "loop"); - space(&mut s.s); - print_block(s, blk); + if_ok!(head(s, "loop")); + if_ok!(space(&mut s.s)); + if_ok!(print_block(s, blk)); } ast::ExprMatch(expr, ref arms) => { - cbox(s, indent_unit); - ibox(s, 4); - word_nbsp(s, "match"); - print_expr(s, expr); - space(&mut s.s); - bopen(s); + if_ok!(cbox(s, indent_unit)); + if_ok!(ibox(s, 4)); + if_ok!(word_nbsp(s, "match")); + if_ok!(print_expr(s, expr)); + if_ok!(space(&mut s.s)); + if_ok!(bopen(s)); let len = arms.len(); for (i, arm) in arms.iter().enumerate() { - space(&mut s.s); - cbox(s, indent_unit); - ibox(s, 0u); + if_ok!(space(&mut s.s)); + if_ok!(cbox(s, indent_unit)); + if_ok!(ibox(s, 0u)); let mut first = true; for p in arm.pats.iter() { if first { first = false; - } else { space(&mut s.s); word_space(s, "|"); } - print_pat(s, *p); + } else { + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "|")); + } + if_ok!(print_pat(s, *p)); } - space(&mut s.s); + if_ok!(space(&mut s.s)); match arm.guard { Some(e) => { - word_space(s, "if"); - print_expr(s, e); - space(&mut s.s); + if_ok!(word_space(s, "if")); + if_ok!(print_expr(s, e)); + if_ok!(space(&mut s.s)); } None => () } - word_space(s, "=>"); + if_ok!(word_space(s, "=>")); // Extract the expression from the extra block the parser adds // in the case of foo => expr @@ -1301,28 +1383,28 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) { match expr.node { ast::ExprBlock(blk) => { // the block will close the pattern's ibox - print_block_unclosed_indent( - s, blk, indent_unit); + if_ok!(print_block_unclosed_indent( + s, blk, indent_unit)); } _ => { - end(s); // close the ibox for the pattern - print_expr(s, expr); + if_ok!(end(s)); // close the ibox for the pattern + if_ok!(print_expr(s, expr)); } } if !expr_is_simple_block(expr) && i < len - 1 { - word(&mut s.s, ","); + if_ok!(word(&mut s.s, ",")); } - end(s); // close enclosing cbox + if_ok!(end(s)); // close enclosing cbox } None => fail!() } } else { // the block will close the pattern's ibox - print_block_unclosed_indent(s, arm.body, indent_unit); + if_ok!(print_block_unclosed_indent(s, arm.body, indent_unit)); } } - bclose_(s, expr.span, indent_unit); + if_ok!(bclose_(s, expr.span, indent_unit)); } ast::ExprFnBlock(decl, body) => { // in do/for blocks we don't want to show an empty @@ -1330,26 +1412,26 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) { // we are inside. // // if !decl.inputs.is_empty() { - print_fn_block_args(s, decl); - space(&mut s.s); + if_ok!(print_fn_block_args(s, decl)); + if_ok!(space(&mut s.s)); // } assert!(body.stmts.is_empty()); assert!(body.expr.is_some()); // we extract the block, so as not to create another set of boxes match body.expr.unwrap().node { ast::ExprBlock(blk) => { - print_block_unclosed(s, blk); + if_ok!(print_block_unclosed(s, blk)); } _ => { // this is a bare expression - print_expr(s, body.expr.unwrap()); - end(s); // need to close a box + if_ok!(print_expr(s, body.expr.unwrap())); + if_ok!(end(s)); // need to close a box } } // a box will be closed by print_expr, but we didn't want an overall // wrapper so we closed the corresponding opening. so create an // empty box to satisfy the close. - ibox(s, 0); + if_ok!(ibox(s, 0)); } ast::ExprProc(decl, body) => { // in do/for blocks we don't want to show an empty @@ -1357,197 +1439,208 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) { // we are inside. // // if !decl.inputs.is_empty() { - print_proc_args(s, decl); - space(&mut s.s); + if_ok!(print_proc_args(s, decl)); + if_ok!(space(&mut s.s)); // } assert!(body.stmts.is_empty()); assert!(body.expr.is_some()); // we extract the block, so as not to create another set of boxes match body.expr.unwrap().node { ast::ExprBlock(blk) => { - print_block_unclosed(s, blk); + if_ok!(print_block_unclosed(s, blk)); } _ => { // this is a bare expression - print_expr(s, body.expr.unwrap()); - end(s); // need to close a box + if_ok!(print_expr(s, body.expr.unwrap())); + if_ok!(end(s)); // need to close a box } } // a box will be closed by print_expr, but we didn't want an overall // wrapper so we closed the corresponding opening. so create an // empty box to satisfy the close. - ibox(s, 0); + if_ok!(ibox(s, 0)); } ast::ExprBlock(blk) => { // containing cbox, will be closed by print-block at } - cbox(s, indent_unit); + if_ok!(cbox(s, indent_unit)); // head-box, will be closed by print-block after { - ibox(s, 0u); - print_block(s, blk); + if_ok!(ibox(s, 0u)); + if_ok!(print_block(s, blk)); } ast::ExprAssign(lhs, rhs) => { - print_expr(s, lhs); - space(&mut s.s); - word_space(s, "="); - print_expr(s, rhs); + if_ok!(print_expr(s, lhs)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "=")); + if_ok!(print_expr(s, rhs)); } ast::ExprAssignOp(_, op, lhs, rhs) => { - print_expr(s, lhs); - space(&mut s.s); - word(&mut s.s, ast_util::binop_to_str(op)); - word_space(s, "="); - print_expr(s, rhs); + if_ok!(print_expr(s, lhs)); + if_ok!(space(&mut s.s)); + if_ok!(word(&mut s.s, ast_util::binop_to_str(op))); + if_ok!(word_space(s, "=")); + if_ok!(print_expr(s, rhs)); } ast::ExprField(expr, id, ref tys) => { - print_expr(s, expr); - word(&mut s.s, "."); - print_ident(s, id); + if_ok!(print_expr(s, expr)); + if_ok!(word(&mut s.s, ".")); + if_ok!(print_ident(s, id)); if tys.len() > 0u { - word(&mut s.s, "::<"); - commasep(s, Inconsistent, *tys, print_type_ref); - word(&mut s.s, ">"); + if_ok!(word(&mut s.s, "::<")); + if_ok!(commasep(s, Inconsistent, *tys, print_type_ref)); + if_ok!(word(&mut s.s, ">")); } } ast::ExprIndex(_, expr, index) => { - print_expr(s, expr); - word(&mut s.s, "["); - print_expr(s, index); - word(&mut s.s, "]"); + if_ok!(print_expr(s, expr)); + if_ok!(word(&mut s.s, "[")); + if_ok!(print_expr(s, index)); + if_ok!(word(&mut s.s, "]")); } - ast::ExprPath(ref path) => print_path(s, path, true), + ast::ExprPath(ref path) => if_ok!(print_path(s, path, true)), ast::ExprBreak(opt_ident) => { - word(&mut s.s, "break"); - space(&mut s.s); + if_ok!(word(&mut s.s, "break")); + if_ok!(space(&mut s.s)); for ident in opt_ident.iter() { - word(&mut s.s, "'"); - print_name(s, *ident); - space(&mut s.s); + if_ok!(word(&mut s.s, "'")); + if_ok!(print_name(s, *ident)); + if_ok!(space(&mut s.s)); } } ast::ExprAgain(opt_ident) => { - word(&mut s.s, "continue"); - space(&mut s.s); + if_ok!(word(&mut s.s, "continue")); + if_ok!(space(&mut s.s)); for ident in opt_ident.iter() { - word(&mut s.s, "'"); - print_name(s, *ident); - space(&mut s.s) + if_ok!(word(&mut s.s, "'")); + if_ok!(print_name(s, *ident)); + if_ok!(space(&mut s.s)) } } ast::ExprRet(result) => { - word(&mut s.s, "return"); + if_ok!(word(&mut s.s, "return")); match result { - Some(expr) => { word(&mut s.s, " "); print_expr(s, expr); } + Some(expr) => { + if_ok!(word(&mut s.s, " ")); + if_ok!(print_expr(s, expr)); + } _ => () } } ast::ExprLogLevel => { - word(&mut s.s, "__log_level"); - popen(s); - pclose(s); + if_ok!(word(&mut s.s, "__log_level")); + if_ok!(popen(s)); + if_ok!(pclose(s)); } ast::ExprInlineAsm(ref a) => { if a.volatile { - word(&mut s.s, "__volatile__ asm!"); + if_ok!(word(&mut s.s, "__volatile__ asm!")); } else { - word(&mut s.s, "asm!"); + if_ok!(word(&mut s.s, "asm!")); } - popen(s); - print_string(s, a.asm.get(), a.asm_str_style); - word_space(s, ":"); + if_ok!(popen(s)); + if_ok!(print_string(s, a.asm.get(), a.asm_str_style)); + if_ok!(word_space(s, ":")); for &(ref co, o) in a.outputs.iter() { - print_string(s, co.get(), ast::CookedStr); - popen(s); - print_expr(s, o); - pclose(s); - word_space(s, ","); + if_ok!(print_string(s, co.get(), ast::CookedStr)); + if_ok!(popen(s)); + if_ok!(print_expr(s, o)); + if_ok!(pclose(s)); + if_ok!(word_space(s, ",")); } - word_space(s, ":"); + if_ok!(word_space(s, ":")); for &(ref co, o) in a.inputs.iter() { - print_string(s, co.get(), ast::CookedStr); - popen(s); - print_expr(s, o); - pclose(s); - word_space(s, ","); + if_ok!(print_string(s, co.get(), ast::CookedStr)); + if_ok!(popen(s)); + if_ok!(print_expr(s, o)); + if_ok!(pclose(s)); + if_ok!(word_space(s, ",")); } - word_space(s, ":"); - print_string(s, a.clobbers.get(), ast::CookedStr); - pclose(s); + if_ok!(word_space(s, ":")); + if_ok!(print_string(s, a.clobbers.get(), ast::CookedStr)); + if_ok!(pclose(s)); } - ast::ExprMac(ref m) => print_mac(s, m), + ast::ExprMac(ref m) => if_ok!(print_mac(s, m)), ast::ExprParen(e) => { - popen(s); - print_expr(s, e); - pclose(s); + if_ok!(popen(s)); + if_ok!(print_expr(s, e)); + if_ok!(pclose(s)); } } { let ann_node = NodeExpr(s, expr); - s.ann.post(ann_node); + if_ok!(s.ann.post(ann_node)); } - end(s); + end(s) } -pub fn print_local_decl(s: &mut State, loc: &ast::Local) { - print_pat(s, loc.pat); +pub fn print_local_decl(s: &mut State, loc: &ast::Local) -> io::IoResult<()> { + if_ok!(print_pat(s, loc.pat)); match loc.ty.node { ast::TyInfer => {} - _ => { word_space(s, ":"); print_type(s, loc.ty); } + _ => { + if_ok!(word_space(s, ":")); + if_ok!(print_type(s, loc.ty)); + } } + Ok(()) } -pub fn print_decl(s: &mut State, decl: &ast::Decl) { - maybe_print_comment(s, decl.span.lo); +pub fn print_decl(s: &mut State, decl: &ast::Decl) -> io::IoResult<()> { + if_ok!(maybe_print_comment(s, decl.span.lo)); match decl.node { ast::DeclLocal(ref loc) => { - space_if_not_bol(s); - ibox(s, indent_unit); - word_nbsp(s, "let"); - - fn print_local(s: &mut State, loc: &ast::Local) { - ibox(s, indent_unit); - print_local_decl(s, loc); - end(s); + if_ok!(space_if_not_bol(s)); + if_ok!(ibox(s, indent_unit)); + if_ok!(word_nbsp(s, "let")); + + fn print_local(s: &mut State, loc: &ast::Local) -> io::IoResult<()> { + if_ok!(ibox(s, indent_unit)); + if_ok!(print_local_decl(s, loc)); + if_ok!(end(s)); match loc.init { Some(init) => { - nbsp(s); - word_space(s, "="); - print_expr(s, init); + if_ok!(nbsp(s)); + if_ok!(word_space(s, "=")); + if_ok!(print_expr(s, init)); } _ => () } + Ok(()) } - print_local(s, *loc); - end(s); + if_ok!(print_local(s, *loc)); + end(s) } ast::DeclItem(item) => print_item(s, item) } } -pub fn print_ident(s: &mut State, ident: ast::Ident) { +pub fn print_ident(s: &mut State, ident: ast::Ident) -> io::IoResult<()> { let string = token::get_ident(ident.name); - word(&mut s.s, string.get()); + word(&mut s.s, string.get()) } -pub fn print_name(s: &mut State, name: ast::Name) { +pub fn print_name(s: &mut State, name: ast::Name) -> io::IoResult<()> { let string = token::get_ident(name); - word(&mut s.s, string.get()); + word(&mut s.s, string.get()) } -pub fn print_for_decl(s: &mut State, loc: &ast::Local, coll: &ast::Expr) { - print_local_decl(s, loc); - space(&mut s.s); - word_space(s, "in"); - print_expr(s, coll); +pub fn print_for_decl(s: &mut State, loc: &ast::Local, + coll: &ast::Expr) -> io::IoResult<()> { + if_ok!(print_local_decl(s, loc)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "in")); + print_expr(s, coll) } fn print_path_(s: &mut State, path: &ast::Path, colons_before_params: bool, - opt_bounds: &Option>) { - maybe_print_comment(s, path.span.lo); + opt_bounds: &Option>) + -> io::IoResult<()> +{ + if_ok!(maybe_print_comment(s, path.span.lo)); if path.global { - word(&mut s.s, "::"); + if_ok!(word(&mut s.s, "::")); } let mut first = true; @@ -1555,198 +1648,207 @@ fn print_path_(s: &mut State, if first { first = false } else { - word(&mut s.s, "::") + if_ok!(word(&mut s.s, "::")) } - print_ident(s, segment.identifier); + if_ok!(print_ident(s, segment.identifier)); // If this is the last segment, print the bounds. if i == path.segments.len() - 1 { match *opt_bounds { None => {} - Some(ref bounds) => print_bounds(s, bounds, true), + Some(ref bounds) => if_ok!(print_bounds(s, bounds, true)), } } if !segment.lifetimes.is_empty() || !segment.types.is_empty() { if colons_before_params { - word(&mut s.s, "::") + if_ok!(word(&mut s.s, "::")) } - word(&mut s.s, "<"); + if_ok!(word(&mut s.s, "<")); let mut comma = false; for lifetime in segment.lifetimes.iter() { if comma { - word_space(s, ",") + if_ok!(word_space(s, ",")) } - print_lifetime(s, lifetime); + if_ok!(print_lifetime(s, lifetime)); comma = true; } if !segment.types.is_empty() { if comma { - word_space(s, ",") + if_ok!(word_space(s, ",")) } - commasep(s, - Inconsistent, - segment.types.map_to_vec(|&t| t), - print_type_ref); + if_ok!(commasep(s, + Inconsistent, + segment.types.map_to_vec(|&t| t), + print_type_ref)); } - word(&mut s.s, ">") + if_ok!(word(&mut s.s, ">")) } } + Ok(()) } -pub fn print_path(s: &mut State, path: &ast::Path, colons_before_params: bool) { +pub fn print_path(s: &mut State, path: &ast::Path, + colons_before_params: bool) -> io::IoResult<()> { print_path_(s, path, colons_before_params, &None) } pub fn print_bounded_path(s: &mut State, path: &ast::Path, - bounds: &Option>) { + bounds: &Option>) + -> io::IoResult<()> +{ print_path_(s, path, false, bounds) } -pub fn print_pat(s: &mut State, pat: &ast::Pat) { - maybe_print_comment(s, pat.span.lo); +pub fn print_pat(s: &mut State, pat: &ast::Pat) -> io::IoResult<()> { + if_ok!(maybe_print_comment(s, pat.span.lo)); { let ann_node = NodePat(s, pat); - s.ann.pre(ann_node); + if_ok!(s.ann.pre(ann_node)); } /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.node { - ast::PatWild => word(&mut s.s, "_"), - ast::PatWildMulti => word(&mut s.s, ".."), + ast::PatWild => if_ok!(word(&mut s.s, "_")), + ast::PatWildMulti => if_ok!(word(&mut s.s, "..")), ast::PatIdent(binding_mode, ref path, sub) => { match binding_mode { ast::BindByRef(mutbl) => { - word_nbsp(s, "ref"); - print_mutability(s, mutbl); + if_ok!(word_nbsp(s, "ref")); + if_ok!(print_mutability(s, mutbl)); } ast::BindByValue(ast::MutImmutable) => {} ast::BindByValue(ast::MutMutable) => { - word_nbsp(s, "mut"); + if_ok!(word_nbsp(s, "mut")); } } - print_path(s, path, true); + if_ok!(print_path(s, path, true)); match sub { Some(p) => { - word(&mut s.s, "@"); - print_pat(s, p); + if_ok!(word(&mut s.s, "@")); + if_ok!(print_pat(s, p)); } None => () } } ast::PatEnum(ref path, ref args_) => { - print_path(s, path, true); + if_ok!(print_path(s, path, true)); match *args_ { - None => word(&mut s.s, "(..)"), + None => if_ok!(word(&mut s.s, "(..)")), Some(ref args) => { if !args.is_empty() { - popen(s); - commasep(s, Inconsistent, *args, - |s, &p| print_pat(s, p)); - pclose(s); + if_ok!(popen(s)); + if_ok!(commasep(s, Inconsistent, *args, + |s, &p| print_pat(s, p))); + if_ok!(pclose(s)); } else { } } } } ast::PatStruct(ref path, ref fields, etc) => { - print_path(s, path, true); - word(&mut s.s, "{"); - fn print_field(s: &mut State, f: &ast::FieldPat) { - cbox(s, indent_unit); - print_ident(s, f.ident); - word_space(s, ":"); - print_pat(s, f.pat); - end(s); + if_ok!(print_path(s, path, true)); + if_ok!(word(&mut s.s, "{")); + fn print_field(s: &mut State, f: &ast::FieldPat) -> io::IoResult<()> { + if_ok!(cbox(s, indent_unit)); + if_ok!(print_ident(s, f.ident)); + if_ok!(word_space(s, ":")); + if_ok!(print_pat(s, f.pat)); + if_ok!(end(s)); + Ok(()) } fn get_span(f: &ast::FieldPat) -> codemap::Span { return f.pat.span; } - commasep_cmnt(s, Consistent, *fields, - |s, f| print_field(s,f), - get_span); + if_ok!(commasep_cmnt(s, Consistent, *fields, + |s, f| print_field(s,f), + get_span)); if etc { - if fields.len() != 0u { word_space(s, ","); } - word(&mut s.s, ".."); + if fields.len() != 0u { if_ok!(word_space(s, ",")); } + if_ok!(word(&mut s.s, "..")); } - word(&mut s.s, "}"); + if_ok!(word(&mut s.s, "}")); } ast::PatTup(ref elts) => { - popen(s); - commasep(s, Inconsistent, *elts, |s, &p| print_pat(s, p)); + if_ok!(popen(s)); + if_ok!(commasep(s, Inconsistent, *elts, |s, &p| print_pat(s, p))); if elts.len() == 1 { - word(&mut s.s, ","); + if_ok!(word(&mut s.s, ",")); } - pclose(s); + if_ok!(pclose(s)); } ast::PatUniq(inner) => { - word(&mut s.s, "~"); - print_pat(s, inner); + if_ok!(word(&mut s.s, "~")); + if_ok!(print_pat(s, inner)); } ast::PatRegion(inner) => { - word(&mut s.s, "&"); - print_pat(s, inner); + if_ok!(word(&mut s.s, "&")); + if_ok!(print_pat(s, inner)); } - ast::PatLit(e) => print_expr(s, e), + ast::PatLit(e) => if_ok!(print_expr(s, e)), ast::PatRange(begin, end) => { - print_expr(s, begin); - space(&mut s.s); - word(&mut s.s, ".."); - print_expr(s, end); + if_ok!(print_expr(s, begin)); + if_ok!(space(&mut s.s)); + if_ok!(word(&mut s.s, "..")); + if_ok!(print_expr(s, end)); } ast::PatVec(ref before, slice, ref after) => { - word(&mut s.s, "["); - commasep(s, Inconsistent, *before, |s, &p| print_pat(s, p)); + if_ok!(word(&mut s.s, "[")); + if_ok!(commasep(s, Inconsistent, *before, |s, &p| print_pat(s, p))); for &p in slice.iter() { - if !before.is_empty() { word_space(s, ","); } + if !before.is_empty() { if_ok!(word_space(s, ",")); } match *p { ast::Pat { node: ast::PatWildMulti, .. } => { // this case is handled by print_pat } - _ => word(&mut s.s, ".."), + _ => if_ok!(word(&mut s.s, "..")), } - print_pat(s, p); - if !after.is_empty() { word_space(s, ","); } + if_ok!(print_pat(s, p)); + if !after.is_empty() { if_ok!(word_space(s, ",")); } } - commasep(s, Inconsistent, *after, |s, &p| print_pat(s, p)); - word(&mut s.s, "]"); + if_ok!(commasep(s, Inconsistent, *after, |s, &p| print_pat(s, p))); + if_ok!(word(&mut s.s, "]")); } } { let ann_node = NodePat(s, pat); - s.ann.post(ann_node); + if_ok!(s.ann.post(ann_node)); } + Ok(()) } -pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_, intr: @IdentInterner) -> ~str { - to_str(explicit_self, |a, &b| { print_explicit_self(a, b, ast::MutImmutable); () }, intr) +pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_, + intr: @IdentInterner) -> ~str { + to_str(explicit_self, |a, &b| { + print_explicit_self(a, b, ast::MutImmutable).map(|_| ()) + }, intr) } // Returns whether it printed anything fn print_explicit_self(s: &mut State, explicit_self: ast::ExplicitSelf_, - mutbl: ast::Mutability) -> bool { - print_mutability(s, mutbl); + mutbl: ast::Mutability) -> io::IoResult { + if_ok!(print_mutability(s, mutbl)); match explicit_self { - ast::SelfStatic => { return false; } + ast::SelfStatic => { return Ok(false); } ast::SelfValue => { - word(&mut s.s, "self"); + if_ok!(word(&mut s.s, "self")); } ast::SelfUniq => { - word(&mut s.s, "~self"); + if_ok!(word(&mut s.s, "~self")); } ast::SelfRegion(ref lt, m) => { - word(&mut s.s, "&"); - print_opt_lifetime(s, lt); - print_mutability(s, m); - word(&mut s.s, "self"); + if_ok!(word(&mut s.s, "&")); + if_ok!(print_opt_lifetime(s, lt)); + if_ok!(print_mutability(s, m)); + if_ok!(word(&mut s.s, "self")); } ast::SelfBox => { - word(&mut s.s, "@self"); + if_ok!(word(&mut s.s, "@self")); } } - return true; + return Ok(true); } pub fn print_fn(s: &mut State, @@ -1756,20 +1858,24 @@ pub fn print_fn(s: &mut State, name: ast::Ident, generics: &ast::Generics, opt_explicit_self: Option, - vis: ast::Visibility) { - head(s, ""); - print_fn_header_info(s, opt_explicit_self, purity, abis, ast::Many, None, vis); - nbsp(s); - print_ident(s, name); - print_generics(s, generics); - print_fn_args_and_ret(s, decl, opt_explicit_self); + vis: ast::Visibility) -> io::IoResult<()> { + if_ok!(head(s, "")); + if_ok!(print_fn_header_info(s, opt_explicit_self, purity, abis, + ast::Many, None, vis)); + if_ok!(nbsp(s)); + if_ok!(print_ident(s, name)); + if_ok!(print_generics(s, generics)); + if_ok!(print_fn_args_and_ret(s, decl, opt_explicit_self)); + Ok(()) } pub fn print_fn_args(s: &mut State, decl: &ast::FnDecl, - opt_explicit_self: Option) { + opt_explicit_self: Option) + -> io::IoResult<()> +{ // It is unfortunate to duplicate the commasep logic, but we want the // self type and the args all in the same box. - rbox(s, 0u, Inconsistent); + if_ok!(rbox(s, 0u, Inconsistent)); let mut first = true; for &explicit_self in opt_explicit_self.iter() { let m = match explicit_self { @@ -1779,7 +1885,7 @@ pub fn print_fn_args(s: &mut State, decl: &ast::FnDecl, _ => ast::MutImmutable } }; - first = !print_explicit_self(s, explicit_self, m); + first = !if_ok!(print_explicit_self(s, explicit_self, m)); } // HACK(eddyb) ignore the separately printed self argument. @@ -1790,117 +1896,126 @@ pub fn print_fn_args(s: &mut State, decl: &ast::FnDecl, }; for arg in args.iter() { - if first { first = false; } else { word_space(s, ","); } - print_arg(s, arg); + if first { first = false; } else { if_ok!(word_space(s, ",")); } + if_ok!(print_arg(s, arg)); } - end(s); + end(s) } pub fn print_fn_args_and_ret(s: &mut State, decl: &ast::FnDecl, - opt_explicit_self: Option) { - popen(s); - print_fn_args(s, decl, opt_explicit_self); + opt_explicit_self: Option) + -> io::IoResult<()> +{ + if_ok!(popen(s)); + if_ok!(print_fn_args(s, decl, opt_explicit_self)); if decl.variadic { - word(&mut s.s, ", ..."); + if_ok!(word(&mut s.s, ", ...")); } - pclose(s); + if_ok!(pclose(s)); - maybe_print_comment(s, decl.output.span.lo); + if_ok!(maybe_print_comment(s, decl.output.span.lo)); match decl.output.node { ast::TyNil => {} _ => { - space_if_not_bol(s); - word_space(s, "->"); - print_type(s, decl.output); + if_ok!(space_if_not_bol(s)); + if_ok!(word_space(s, "->")); + if_ok!(print_type(s, decl.output)); } } + Ok(()) } -pub fn print_fn_block_args(s: &mut State, decl: &ast::FnDecl) { - word(&mut s.s, "|"); - print_fn_args(s, decl, None); - word(&mut s.s, "|"); +pub fn print_fn_block_args(s: &mut State, + decl: &ast::FnDecl) -> io::IoResult<()> { + if_ok!(word(&mut s.s, "|")); + if_ok!(print_fn_args(s, decl, None)); + if_ok!(word(&mut s.s, "|")); match decl.output.node { ast::TyInfer => {} _ => { - space_if_not_bol(s); - word_space(s, "->"); - print_type(s, decl.output); + if_ok!(space_if_not_bol(s)); + if_ok!(word_space(s, "->")); + if_ok!(print_type(s, decl.output)); } } - maybe_print_comment(s, decl.output.span.lo); + maybe_print_comment(s, decl.output.span.lo) } -pub fn print_proc_args(s: &mut State, decl: &ast::FnDecl) { - word(&mut s.s, "proc"); - word(&mut s.s, "("); - print_fn_args(s, decl, None); - word(&mut s.s, ")"); +pub fn print_proc_args(s: &mut State, decl: &ast::FnDecl) -> io::IoResult<()> { + if_ok!(word(&mut s.s, "proc")); + if_ok!(word(&mut s.s, "(")); + if_ok!(print_fn_args(s, decl, None)); + if_ok!(word(&mut s.s, ")")); match decl.output.node { ast::TyInfer => {} _ => { - space_if_not_bol(s); - word_space(s, "->"); - print_type(s, decl.output); + if_ok!(space_if_not_bol(s)); + if_ok!(word_space(s, "->")); + if_ok!(print_type(s, decl.output)); } } - maybe_print_comment(s, decl.output.span.lo); + maybe_print_comment(s, decl.output.span.lo) } pub fn print_bounds(s: &mut State, bounds: &OptVec, - print_colon_anyway: bool) { + print_colon_anyway: bool) -> io::IoResult<()> { if !bounds.is_empty() { - word(&mut s.s, ":"); + if_ok!(word(&mut s.s, ":")); let mut first = true; for bound in bounds.iter() { - nbsp(s); + if_ok!(nbsp(s)); if first { first = false; } else { - word_space(s, "+"); + if_ok!(word_space(s, "+")); } - match *bound { + if_ok!(match *bound { TraitTyParamBound(ref tref) => print_trait_ref(s, tref), RegionTyParamBound => word(&mut s.s, "'static"), - } + }) } } else if print_colon_anyway { - word(&mut s.s, ":"); + if_ok!(word(&mut s.s, ":")); } + Ok(()) } -pub fn print_lifetime(s: &mut State, lifetime: &ast::Lifetime) { - word(&mut s.s, "'"); - print_ident(s, lifetime.ident); +pub fn print_lifetime(s: &mut State, + lifetime: &ast::Lifetime) -> io::IoResult<()> { + if_ok!(word(&mut s.s, "'")); + print_ident(s, lifetime.ident) } -pub fn print_generics(s: &mut State, generics: &ast::Generics) { +pub fn print_generics(s: &mut State, + generics: &ast::Generics) -> io::IoResult<()> { let total = generics.lifetimes.len() + generics.ty_params.len(); if total > 0 { - word(&mut s.s, "<"); - fn print_item(s: &mut State, generics: &ast::Generics, idx: uint) { + if_ok!(word(&mut s.s, "<")); + fn print_item(s: &mut State, generics: &ast::Generics, + idx: uint) -> io::IoResult<()> { if idx < generics.lifetimes.len() { let lifetime = generics.lifetimes.get(idx); - print_lifetime(s, lifetime); + print_lifetime(s, lifetime) } else { let idx = idx - generics.lifetimes.len(); let param = generics.ty_params.get(idx); - print_ident(s, param.ident); - print_bounds(s, ¶m.bounds, false); + if_ok!(print_ident(s, param.ident)); + if_ok!(print_bounds(s, ¶m.bounds, false)); match param.default { Some(default) => { - space(&mut s.s); - word_space(s, "="); - print_type(s, default); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "=")); + if_ok!(print_type(s, default)); } _ => {} } + Ok(()) } } @@ -1909,113 +2024,119 @@ pub fn print_generics(s: &mut State, generics: &ast::Generics) { ints.push(i); } - commasep(s, Inconsistent, ints, - |s, &i| print_item(s, generics, i)); - word(&mut s.s, ">"); + if_ok!(commasep(s, Inconsistent, ints, + |s, &i| print_item(s, generics, i))); + if_ok!(word(&mut s.s, ">")); } + Ok(()) } -pub fn print_meta_item(s: &mut State, item: &ast::MetaItem) { - ibox(s, indent_unit); +pub fn print_meta_item(s: &mut State, item: &ast::MetaItem) -> io::IoResult<()> { + if_ok!(ibox(s, indent_unit)); match item.node { - ast::MetaWord(ref name) => word(&mut s.s, name.get()), - ast::MetaNameValue(ref name, ref value) => { - word_space(s, name.get()); - word_space(s, "="); - print_literal(s, value); - } - ast::MetaList(ref name, ref items) => { - word(&mut s.s, name.get()); - popen(s); - commasep(s, - Consistent, - items.as_slice(), - |p, &i| print_meta_item(p, i)); - pclose(s); - } + ast::MetaWord(ref name) => { + if_ok!(word(&mut s.s, name.get())); + } + ast::MetaNameValue(ref name, ref value) => { + if_ok!(word_space(s, name.get())); + if_ok!(word_space(s, "=")); + if_ok!(print_literal(s, value)); + } + ast::MetaList(ref name, ref items) => { + if_ok!(word(&mut s.s, name.get())); + if_ok!(popen(s)); + if_ok!(commasep(s, + Consistent, + items.as_slice(), + |p, &i| print_meta_item(p, i))); + if_ok!(pclose(s)); + } } - end(s); + end(s) } -pub fn print_view_path(s: &mut State, vp: &ast::ViewPath) { +pub fn print_view_path(s: &mut State, vp: &ast::ViewPath) -> io::IoResult<()> { match vp.node { ast::ViewPathSimple(ident, ref path, _) => { // FIXME(#6993) can't compare identifiers directly here if path.segments.last().unwrap().identifier.name != ident.name { - print_ident(s, ident); - space(&mut s.s); - word_space(s, "="); + if_ok!(print_ident(s, ident)); + if_ok!(space(&mut s.s)); + if_ok!(word_space(s, "=")); } - print_path(s, path, false); + print_path(s, path, false) } ast::ViewPathGlob(ref path, _) => { - print_path(s, path, false); - word(&mut s.s, "::*"); + if_ok!(print_path(s, path, false)); + word(&mut s.s, "::*") } ast::ViewPathList(ref path, ref idents, _) => { if path.segments.is_empty() { - word(&mut s.s, "{"); + if_ok!(word(&mut s.s, "{")); } else { - print_path(s, path, false); - word(&mut s.s, "::{"); + if_ok!(print_path(s, path, false)); + if_ok!(word(&mut s.s, "::{")); } - commasep(s, Inconsistent, (*idents), |s, w| { - print_ident(s, w.node.name); - }); - word(&mut s.s, "}"); + if_ok!(commasep(s, Inconsistent, (*idents), |s, w| { + print_ident(s, w.node.name) + })); + word(&mut s.s, "}") } } } -pub fn print_view_paths(s: &mut State, vps: &[@ast::ViewPath]) { - commasep(s, Inconsistent, vps, |p, &vp| print_view_path(p, vp)); +pub fn print_view_paths(s: &mut State, + vps: &[@ast::ViewPath]) -> io::IoResult<()> { + commasep(s, Inconsistent, vps, |p, &vp| print_view_path(p, vp)) } -pub fn print_view_item(s: &mut State, item: &ast::ViewItem) { - hardbreak_if_not_bol(s); - maybe_print_comment(s, item.span.lo); - print_outer_attributes(s, item.attrs); - print_visibility(s, item.vis); +pub fn print_view_item(s: &mut State, item: &ast::ViewItem) -> io::IoResult<()> { + if_ok!(hardbreak_if_not_bol(s)); + if_ok!(maybe_print_comment(s, item.span.lo)); + if_ok!(print_outer_attributes(s, item.attrs)); + if_ok!(print_visibility(s, item.vis)); match item.node { ast::ViewItemExternMod(id, ref optional_path, _) => { - head(s, "extern mod"); - print_ident(s, id); + if_ok!(head(s, "extern mod")); + if_ok!(print_ident(s, id)); for &(ref p, style) in optional_path.iter() { - space(&mut s.s); - word(&mut s.s, "="); - space(&mut s.s); - print_string(s, p.get(), style); + if_ok!(space(&mut s.s)); + if_ok!(word(&mut s.s, "=")); + if_ok!(space(&mut s.s)); + if_ok!(print_string(s, p.get(), style)); } } ast::ViewItemUse(ref vps) => { - head(s, "use"); - print_view_paths(s, *vps); + if_ok!(head(s, "use")); + if_ok!(print_view_paths(s, *vps)); } } - word(&mut s.s, ";"); - end(s); // end inner head-block - end(s); // end outer head-block + if_ok!(word(&mut s.s, ";")); + if_ok!(end(s)); // end inner head-block + if_ok!(end(s)); // end outer head-block + Ok(()) } -pub fn print_mutability(s: &mut State, mutbl: ast::Mutability) { +pub fn print_mutability(s: &mut State, + mutbl: ast::Mutability) -> io::IoResult<()> { match mutbl { ast::MutMutable => word_nbsp(s, "mut"), - ast::MutImmutable => {/* nothing */ } + ast::MutImmutable => Ok(()), } } -pub fn print_mt(s: &mut State, mt: &ast::MutTy) { - print_mutability(s, mt.mutbl); - print_type(s, mt.ty); +pub fn print_mt(s: &mut State, mt: &ast::MutTy) -> io::IoResult<()> { + if_ok!(print_mutability(s, mt.mutbl)); + print_type(s, mt.ty) } -pub fn print_arg(s: &mut State, input: &ast::Arg) { - ibox(s, indent_unit); +pub fn print_arg(s: &mut State, input: &ast::Arg) -> io::IoResult<()> { + if_ok!(ibox(s, indent_unit)); match input.ty.node { - ast::TyInfer => print_pat(s, input.pat), + ast::TyInfer => if_ok!(print_pat(s, input.pat)), _ => { match input.pat.node { ast::PatIdent(_, ref path, _) if @@ -2025,15 +2146,15 @@ pub fn print_arg(s: &mut State, input: &ast::Arg) { // Do nothing. } _ => { - print_pat(s, input.pat); - word(&mut s.s, ":"); - space(&mut s.s); + if_ok!(print_pat(s, input.pat)); + if_ok!(word(&mut s.s, ":")); + if_ok!(space(&mut s.s)); } } - print_type(s, input.ty); + if_ok!(print_type(s, input.ty)); } } - end(s); + end(s) } pub fn print_ty_fn(s: &mut State, @@ -2046,116 +2167,132 @@ pub fn print_ty_fn(s: &mut State, id: Option, opt_bounds: &Option>, generics: Option<&ast::Generics>, - opt_explicit_self: Option) { - ibox(s, indent_unit); + opt_explicit_self: Option) + -> io::IoResult<()> +{ + if_ok!(ibox(s, indent_unit)); // Duplicates the logic in `print_fn_header_info()`. This is because that // function prints the sigil in the wrong place. That should be fixed. if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once { - word(&mut s.s, "proc"); + if_ok!(word(&mut s.s, "proc")); } else if opt_sigil == Some(ast::BorrowedSigil) { - print_extern_opt_abis(s, opt_abis); + if_ok!(print_extern_opt_abis(s, opt_abis)); for lifetime in opt_region.iter() { - print_lifetime(s, lifetime); + if_ok!(print_lifetime(s, lifetime)); } - print_purity(s, purity); - print_onceness(s, onceness); + if_ok!(print_purity(s, purity)); + if_ok!(print_onceness(s, onceness)); } else { - print_opt_abis_and_extern_if_nondefault(s, opt_abis); - print_opt_sigil(s, opt_sigil); - print_opt_lifetime(s, opt_region); - print_purity(s, purity); - print_onceness(s, onceness); - word(&mut s.s, "fn"); + if_ok!(print_opt_abis_and_extern_if_nondefault(s, opt_abis)); + if_ok!(print_opt_sigil(s, opt_sigil)); + if_ok!(print_opt_lifetime(s, opt_region)); + if_ok!(print_purity(s, purity)); + if_ok!(print_onceness(s, onceness)); + if_ok!(word(&mut s.s, "fn")); } - match id { Some(id) => { word(&mut s.s, " "); print_ident(s, id); } _ => () } + match id { + Some(id) => { + if_ok!(word(&mut s.s, " ")); + if_ok!(print_ident(s, id)); + } + _ => () + } if opt_sigil != Some(ast::BorrowedSigil) { opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true)); } - match generics { Some(g) => print_generics(s, g), _ => () } - zerobreak(&mut s.s); + match generics { Some(g) => if_ok!(print_generics(s, g)), _ => () } + if_ok!(zerobreak(&mut s.s)); if opt_sigil == Some(ast::BorrowedSigil) { - word(&mut s.s, "|"); + if_ok!(word(&mut s.s, "|")); } else { - popen(s); + if_ok!(popen(s)); } - print_fn_args(s, decl, opt_explicit_self); + if_ok!(print_fn_args(s, decl, opt_explicit_self)); if opt_sigil == Some(ast::BorrowedSigil) { - word(&mut s.s, "|"); + if_ok!(word(&mut s.s, "|")); opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true)); } else { if decl.variadic { - word(&mut s.s, ", ..."); + if_ok!(word(&mut s.s, ", ...")); } - pclose(s); + if_ok!(pclose(s)); } - maybe_print_comment(s, decl.output.span.lo); + if_ok!(maybe_print_comment(s, decl.output.span.lo)); match decl.output.node { ast::TyNil => {} _ => { - space_if_not_bol(s); - ibox(s, indent_unit); - word_space(s, "->"); - if decl.cf == ast::NoReturn { word_nbsp(s, "!"); } - else { print_type(s, decl.output); } - end(s); + if_ok!(space_if_not_bol(s)); + if_ok!(ibox(s, indent_unit)); + if_ok!(word_space(s, "->")); + if decl.cf == ast::NoReturn { + if_ok!(word_nbsp(s, "!")); + } else { + if_ok!(print_type(s, decl.output)); + } + if_ok!(end(s)); } } - end(s); + end(s) } pub fn maybe_print_trailing_comment(s: &mut State, span: codemap::Span, - next_pos: Option) { + next_pos: Option) + -> io::IoResult<()> +{ let cm; - match s.cm { Some(ccm) => cm = ccm, _ => return } + match s.cm { Some(ccm) => cm = ccm, _ => return Ok(()) } match next_comment(s) { - Some(ref cmnt) => { - if (*cmnt).style != comments::Trailing { return; } - let span_line = cm.lookup_char_pos(span.hi); - let comment_line = cm.lookup_char_pos((*cmnt).pos); - let mut next = (*cmnt).pos + BytePos(1); - match next_pos { None => (), Some(p) => next = p } - if span.hi < (*cmnt).pos && (*cmnt).pos < next && - span_line.line == comment_line.line { - print_comment(s, cmnt); - s.cur_cmnt_and_lit.cur_cmnt += 1u; + Some(ref cmnt) => { + if (*cmnt).style != comments::Trailing { return Ok(()) } + let span_line = cm.lookup_char_pos(span.hi); + let comment_line = cm.lookup_char_pos((*cmnt).pos); + let mut next = (*cmnt).pos + BytePos(1); + match next_pos { None => (), Some(p) => next = p } + if span.hi < (*cmnt).pos && (*cmnt).pos < next && + span_line.line == comment_line.line { + if_ok!(print_comment(s, cmnt)); + s.cur_cmnt_and_lit.cur_cmnt += 1u; + } } - } - _ => () + _ => () } + Ok(()) } -pub fn print_remaining_comments(s: &mut State) { +pub fn print_remaining_comments(s: &mut State) -> io::IoResult<()> { // If there aren't any remaining comments, then we need to manually // make sure there is a line break at the end. - if next_comment(s).is_none() { hardbreak(&mut s.s); } + if next_comment(s).is_none() { + if_ok!(hardbreak(&mut s.s)); + } loop { match next_comment(s) { - Some(ref cmnt) => { - print_comment(s, cmnt); - s.cur_cmnt_and_lit.cur_cmnt += 1u; - } - _ => break + Some(ref cmnt) => { + if_ok!(print_comment(s, cmnt)); + s.cur_cmnt_and_lit.cur_cmnt += 1u; + } + _ => break } } + Ok(()) } -pub fn print_literal(s: &mut State, lit: &ast::Lit) { - maybe_print_comment(s, lit.span.lo); +pub fn print_literal(s: &mut State, lit: &ast::Lit) -> io::IoResult<()> { + if_ok!(maybe_print_comment(s, lit.span.lo)); match next_lit(s, lit.span.lo) { Some(ref ltrl) => { - word(&mut s.s, (*ltrl).lit); - return; + return word(&mut s.s, (*ltrl).lit); } _ => () } @@ -2165,46 +2302,48 @@ pub fn print_literal(s: &mut State, lit: &ast::Lit) { let mut res = ~"'"; char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c)); res.push_char('\''); - word(&mut s.s, res); + word(&mut s.s, res) } ast::LitInt(i, t) => { if i < 0_i64 { word(&mut s.s, ~"-" + (-i as u64).to_str_radix(10u) - + ast_util::int_ty_to_str(t)); + + ast_util::int_ty_to_str(t)) } else { word(&mut s.s, (i as u64).to_str_radix(10u) - + ast_util::int_ty_to_str(t)); + + ast_util::int_ty_to_str(t)) } } ast::LitUint(u, t) => { word(&mut s.s, u.to_str_radix(10u) - + ast_util::uint_ty_to_str(t)); + + ast_util::uint_ty_to_str(t)) } ast::LitIntUnsuffixed(i) => { if i < 0_i64 { - word(&mut s.s, ~"-" + (-i as u64).to_str_radix(10u)); + word(&mut s.s, ~"-" + (-i as u64).to_str_radix(10u)) } else { - word(&mut s.s, (i as u64).to_str_radix(10u)); + word(&mut s.s, (i as u64).to_str_radix(10u)) } } + ast::LitFloat(ref f, t) => { - word(&mut s.s, f.get() + ast_util::float_ty_to_str(t)); + word(&mut s.s, f.get() + ast_util::float_ty_to_str(t)) } ast::LitFloatUnsuffixed(ref f) => word(&mut s.s, f.get()), ast::LitNil => word(&mut s.s, "()"), ast::LitBool(val) => { - if val { word(&mut s.s, "true"); } else { word(&mut s.s, "false"); } + if val { word(&mut s.s, "true") } else { word(&mut s.s, "false") } } ast::LitBinary(ref arr) => { - ibox(s, indent_unit); - word(&mut s.s, "["); - commasep_cmnt(s, Inconsistent, *arr.borrow(), |s, u| word(&mut s.s, format!("{}", *u)), - |_| lit.span); - word(&mut s.s, "]"); - end(s); + if_ok!(ibox(s, indent_unit)); + if_ok!(word(&mut s.s, "[")); + if_ok!(commasep_cmnt(s, Inconsistent, *arr.borrow(), + |s, u| word(&mut s.s, format!("{}", *u)), + |_| lit.span)); + if_ok!(word(&mut s.s, "]")); + end(s) } } } @@ -2228,49 +2367,55 @@ pub fn next_lit(s: &mut State, pos: BytePos) -> Option { } } -pub fn maybe_print_comment(s: &mut State, pos: BytePos) { +pub fn maybe_print_comment(s: &mut State, pos: BytePos) -> io::IoResult<()> { loop { match next_comment(s) { Some(ref cmnt) => { if (*cmnt).pos < pos { - print_comment(s, cmnt); + if_ok!(print_comment(s, cmnt)); s.cur_cmnt_and_lit.cur_cmnt += 1u; } else { break; } } _ => break } } + Ok(()) } -pub fn print_comment(s: &mut State, cmnt: &comments::Comment) { +pub fn print_comment(s: &mut State, + cmnt: &comments::Comment) -> io::IoResult<()> { match cmnt.style { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1u); - zerobreak(&mut s.s); - word(&mut s.s, cmnt.lines[0]); - zerobreak(&mut s.s); + if_ok!(zerobreak(&mut s.s)); + if_ok!(word(&mut s.s, cmnt.lines[0])); + if_ok!(zerobreak(&mut s.s)); } comments::Isolated => { - pprust::hardbreak_if_not_bol(s); + if_ok!(pprust::hardbreak_if_not_bol(s)); for line in cmnt.lines.iter() { // Don't print empty lines because they will end up as trailing // whitespace - if !line.is_empty() { word(&mut s.s, *line); } - hardbreak(&mut s.s); + if !line.is_empty() { + if_ok!(word(&mut s.s, *line)); + } + if_ok!(hardbreak(&mut s.s)); } } comments::Trailing => { - word(&mut s.s, " "); + if_ok!(word(&mut s.s, " ")); if cmnt.lines.len() == 1u { - word(&mut s.s, cmnt.lines[0]); - hardbreak(&mut s.s); + if_ok!(word(&mut s.s, cmnt.lines[0])); + if_ok!(hardbreak(&mut s.s)); } else { - ibox(s, 0u); + if_ok!(ibox(s, 0u)); for line in cmnt.lines.iter() { - if !line.is_empty() { word(&mut s.s, *line); } - hardbreak(&mut s.s); + if !line.is_empty() { + if_ok!(word(&mut s.s, *line)); + } + if_ok!(hardbreak(&mut s.s)); } - end(s); + if_ok!(end(s)); } } comments::BlankLine => { @@ -2279,19 +2424,23 @@ pub fn print_comment(s: &mut State, cmnt: &comments::Comment) { pp::String(s, _) => ";" == s, _ => false }; - if is_semi || is_begin(s) || is_end(s) { hardbreak(&mut s.s); } - hardbreak(&mut s.s); + if is_semi || is_begin(s) || is_end(s) { + if_ok!(hardbreak(&mut s.s)); + } + if_ok!(hardbreak(&mut s.s)); } } + Ok(()) } -pub fn print_string(s: &mut State, st: &str, style: ast::StrStyle) { +pub fn print_string(s: &mut State, st: &str, + style: ast::StrStyle) -> io::IoResult<()> { let st = match style { ast::CookedStr => format!("\"{}\"", st.escape_default()), ast::RawStr(n) => format!("r{delim}\"{string}\"{delim}", delim="#".repeat(n), string=st) }; - word(&mut s.s, st); + word(&mut s.s, st) } // FIXME(pcwalton): A nasty function to extract the string from an `io::Writer` @@ -2304,11 +2453,12 @@ unsafe fn get_mem_writer(writer: &mut ~io::Writer) -> ~str { result } -pub fn to_str(t: &T, f: |&mut State, &T|, intr: @IdentInterner) -> ~str { +pub fn to_str(t: &T, f: |&mut State, &T| -> io::IoResult<()>, + intr: @IdentInterner) -> ~str { let wr = ~MemWriter::new(); let mut s = rust_printer(wr as ~io::Writer, intr); - f(&mut s, t); - eof(&mut s.s); + f(&mut s, t).unwrap(); + eof(&mut s.s).unwrap(); unsafe { get_mem_writer(&mut s.s.out) } @@ -2327,44 +2477,52 @@ pub fn next_comment(s: &mut State) -> Option { } } -pub fn print_opt_purity(s: &mut State, opt_purity: Option) { +pub fn print_opt_purity(s: &mut State, + opt_purity: Option) -> io::IoResult<()> { match opt_purity { Some(ast::ImpureFn) => { } Some(purity) => { - word_nbsp(s, purity_to_str(purity)); + if_ok!(word_nbsp(s, purity_to_str(purity))); } None => {} } + Ok(()) } pub fn print_opt_abis_and_extern_if_nondefault(s: &mut State, - opt_abis: Option) { + opt_abis: Option) + -> io::IoResult<()> +{ match opt_abis { Some(abis) if !abis.is_rust() => { - word_nbsp(s, "extern"); - word_nbsp(s, abis.to_str()); + if_ok!(word_nbsp(s, "extern")); + if_ok!(word_nbsp(s, abis.to_str())); } Some(_) | None => {} }; + Ok(()) } -pub fn print_extern_opt_abis(s: &mut State, opt_abis: Option) { +pub fn print_extern_opt_abis(s: &mut State, + opt_abis: Option) -> io::IoResult<()> { match opt_abis { Some(abis) => { - word_nbsp(s, "extern"); - word_nbsp(s, abis.to_str()); + if_ok!(word_nbsp(s, "extern")); + if_ok!(word_nbsp(s, abis.to_str())); } None => {} - }; + } + Ok(()) } -pub fn print_opt_sigil(s: &mut State, opt_sigil: Option) { +pub fn print_opt_sigil(s: &mut State, + opt_sigil: Option) -> io::IoResult<()> { match opt_sigil { - Some(ast::BorrowedSigil) => { word(&mut s.s, "&"); } - Some(ast::OwnedSigil) => { word(&mut s.s, "~"); } - Some(ast::ManagedSigil) => { word(&mut s.s, "@"); } - None => {} - }; + Some(ast::BorrowedSigil) => word(&mut s.s, "&"), + Some(ast::OwnedSigil) => word(&mut s.s, "~"), + Some(ast::ManagedSigil) => word(&mut s.s, "@"), + None => Ok(()) + } } pub fn print_fn_header_info(s: &mut State, @@ -2373,23 +2531,24 @@ pub fn print_fn_header_info(s: &mut State, abis: AbiSet, onceness: ast::Onceness, opt_sigil: Option, - vis: ast::Visibility) { - word(&mut s.s, visibility_qualified(vis, "")); + vis: ast::Visibility) -> io::IoResult<()> { + if_ok!(word(&mut s.s, visibility_qualified(vis, ""))); if abis != AbiSet::Rust() { - word_nbsp(s, "extern"); - word_nbsp(s, abis.to_str()); + if_ok!(word_nbsp(s, "extern")); + if_ok!(word_nbsp(s, abis.to_str())); if opt_purity != Some(ast::ExternFn) { - print_opt_purity(s, opt_purity); + if_ok!(print_opt_purity(s, opt_purity)); } } else { - print_opt_purity(s, opt_purity); + if_ok!(print_opt_purity(s, opt_purity)); } - print_onceness(s, onceness); - word(&mut s.s, "fn"); - print_opt_sigil(s, opt_sigil); + if_ok!(print_onceness(s, onceness)); + if_ok!(word(&mut s.s, "fn")); + if_ok!(print_opt_sigil(s, opt_sigil)); + Ok(()) } pub fn purity_to_str(p: ast::Purity) -> &'static str { @@ -2407,17 +2566,17 @@ pub fn onceness_to_str(o: ast::Onceness) -> &'static str { } } -pub fn print_purity(s: &mut State, p: ast::Purity) { +pub fn print_purity(s: &mut State, p: ast::Purity) -> io::IoResult<()> { match p { - ast::ImpureFn => (), + ast::ImpureFn => Ok(()), _ => word_nbsp(s, purity_to_str(p)) } } -pub fn print_onceness(s: &mut State, o: ast::Onceness) { +pub fn print_onceness(s: &mut State, o: ast::Onceness) -> io::IoResult<()> { match o { - ast::Once => { word_nbsp(s, "once"); } - ast::Many => {} + ast::Once => word_nbsp(s, "once"), + ast::Many => Ok(()) } } diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 58c2bed7a45a7..aa22f47221bfa 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -101,30 +101,30 @@ pub fn matches_codepattern(a : &str, b : &str) -> bool { let mut idx_a = 0; let mut idx_b = 0; loop { - if (idx_a == a.len() && idx_b == b.len()) { + if idx_a == a.len() && idx_b == b.len() { return true; } - else if (idx_a == a.len()) {return false;} - else if (idx_b == b.len()) { + else if idx_a == a.len() {return false;} + else if idx_b == b.len() { // maybe the stuff left in a is all ws? - if (is_whitespace(a.char_at(idx_a))) { - return (scan_for_non_ws_or_end(a,idx_a) == a.len()); + if is_whitespace(a.char_at(idx_a)) { + return scan_for_non_ws_or_end(a,idx_a) == a.len(); } else { return false; } } // ws in both given and pattern: - else if (is_whitespace(a.char_at(idx_a)) - && is_whitespace(b.char_at(idx_b))) { + else if is_whitespace(a.char_at(idx_a)) + && is_whitespace(b.char_at(idx_b)) { idx_a = scan_for_non_ws_or_end(a,idx_a); idx_b = scan_for_non_ws_or_end(b,idx_b); } // ws in given only: - else if (is_whitespace(a.char_at(idx_a))) { + else if is_whitespace(a.char_at(idx_a)) { idx_a = scan_for_non_ws_or_end(a,idx_a); } // *don't* silently eat ws in expected only. - else if (a.char_at(idx_a) == b.char_at(idx_b)) { + else if a.char_at(idx_a) == b.char_at(idx_b) { idx_a += 1; idx_b += 1; } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 01ebf58628fa8..c4481a1a07f01 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -19,15 +19,21 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://static.rust-lang.org/doc/master")]; +#[feature(macro_rules)]; #[deny(non_camel_case_types)]; #[allow(missing_doc)]; use std::os; +use std::io; use terminfo::TermInfo; use terminfo::searcher::open; use terminfo::parser::compiled::{parse, msys_terminfo}; use terminfo::parm::{expand, Number, Variables}; +macro_rules! if_ok ( + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) +) + pub mod terminfo; // FIXME (#2807): Windows support. @@ -141,45 +147,48 @@ impl Terminal { /// If the color is a bright color, but the terminal only supports 8 colors, /// the corresponding normal color will be used instead. /// - /// Returns true if the color was set, false otherwise. - pub fn fg(&mut self, color: color::Color) -> bool { + /// Returns Ok(true) if the color was set, Ok(false) otherwise, and Err(e) + /// if there was an I/O error + pub fn fg(&mut self, color: color::Color) -> io::IoResult { let color = self.dim_if_necessary(color); if self.num_colors > color { let s = expand(*self.ti.strings.find_equiv(&("setaf")).unwrap(), [Number(color as int)], &mut Variables::new()); if s.is_ok() { - self.out.write(s.unwrap()); - return true + if_ok!(self.out.write(s.unwrap())); + return Ok(true) } else { warn!("{}", s.unwrap_err()); } } - false + Ok(false) } /// Sets the background color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, /// the corresponding normal color will be used instead. /// - /// Returns true if the color was set, false otherwise. - pub fn bg(&mut self, color: color::Color) -> bool { + /// Returns Ok(true) if the color was set, Ok(false) otherwise, and Err(e) + /// if there was an I/O error + pub fn bg(&mut self, color: color::Color) -> io::IoResult { let color = self.dim_if_necessary(color); if self.num_colors > color { let s = expand(*self.ti.strings.find_equiv(&("setab")).unwrap(), [Number(color as int)], &mut Variables::new()); if s.is_ok() { - self.out.write(s.unwrap()); - return true + if_ok!(self.out.write(s.unwrap())); + return Ok(true) } else { warn!("{}", s.unwrap_err()); } } - false + Ok(false) } /// Sets the given terminal attribute, if supported. - /// Returns true if the attribute was supported, false otherwise. - pub fn attr(&mut self, attr: attr::Attr) -> bool { + /// Returns Ok(true) if the attribute was supported, Ok(false) otherwise, + /// and Err(e) if there was an I/O error. + pub fn attr(&mut self, attr: attr::Attr) -> io::IoResult { match attr { attr::ForegroundColor(c) => self.fg(c), attr::BackgroundColor(c) => self.bg(c), @@ -189,13 +198,13 @@ impl Terminal { if parm.is_some() { let s = expand(*parm.unwrap(), [], &mut Variables::new()); if s.is_ok() { - self.out.write(s.unwrap()); - return true + if_ok!(self.out.write(s.unwrap())); + return Ok(true) } else { warn!("{}", s.unwrap_err()); } } - false + Ok(false) } } } @@ -214,7 +223,7 @@ impl Terminal { } /// Resets all terminal attributes and color to the default. - pub fn reset(&mut self) { + pub fn reset(&mut self) -> io::IoResult<()> { let mut cap = self.ti.strings.find_equiv(&("sgr0")); if cap.is_none() { // are there any terminals that have color/attrs and not sgr0? @@ -228,7 +237,7 @@ impl Terminal { expand(*op, [], &mut Variables::new()) }); if s.is_ok() { - self.out.write(s.unwrap()); + return self.out.write(s.unwrap()) } else if self.num_colors > 0 { warn!("{}", s.unwrap_err()); } else { @@ -236,6 +245,7 @@ impl Terminal { // but it's not worth testing all known attributes just for this. debug!("{}", s.unwrap_err()); } + Ok(()) } fn dim_if_necessary(&self, color: color::Color) -> color::Color { @@ -252,11 +262,11 @@ impl Terminal { } impl Writer for Terminal { - fn write(&mut self, buf: &[u8]) { - self.out.write(buf); + fn write(&mut self, buf: &[u8]) -> io::IoResult<()> { + self.out.write(buf) } - fn flush(&mut self) { - self.out.flush(); + fn flush(&mut self) -> io::IoResult<()> { + self.out.flush() } } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index b0104faf4b5e6..31f12bd45e692 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -162,6 +162,10 @@ pub static stringnames: &'static[&'static str] = &'static[ "cbt", "_", "cr", "cs /// Parse a compiled terminfo entry, using long capability names if `longnames` is true pub fn parse(file: &mut io::Reader, longnames: bool) -> Result<~TermInfo, ~str> { + macro_rules! if_ok( ($e:expr) => ( + match $e { Ok(e) => e, Err(e) => return Err(format!("{}", e)) } + ) ) + let bnames; let snames; let nnames; @@ -177,17 +181,17 @@ pub fn parse(file: &mut io::Reader, } // Check magic number - let magic = file.read_le_u16(); + let magic = if_ok!(file.read_le_u16()); if magic != 0x011A { return Err(format!("invalid magic number: expected {:x} but found {:x}", 0x011A, magic as uint)); } - let names_bytes = file.read_le_i16() as int; - let bools_bytes = file.read_le_i16() as int; - let numbers_count = file.read_le_i16() as int; - let string_offsets_count = file.read_le_i16() as int; - let string_table_bytes = file.read_le_i16() as int; + let names_bytes = if_ok!(file.read_le_i16()) as int; + let bools_bytes = if_ok!(file.read_le_i16()) as int; + let numbers_count = if_ok!(file.read_le_i16()) as int; + let string_offsets_count = if_ok!(file.read_le_i16()) as int; + let string_table_bytes = if_ok!(file.read_le_i16()) as int; assert!(names_bytes > 0); @@ -216,18 +220,21 @@ pub fn parse(file: &mut io::Reader, } // don't read NUL - let names_str = str::from_utf8_owned(file.read_bytes(names_bytes as uint - 1)).unwrap(); + let bytes = if_ok!(file.read_bytes(names_bytes as uint - 1)); + let names_str = match str::from_utf8_owned(bytes) { + Some(s) => s, None => return Err(~"input not utf-8"), + }; let term_names: ~[~str] = names_str.split('|').map(|s| s.to_owned()).collect(); - file.read_byte(); // consume NUL + if_ok!(file.read_byte()); // consume NUL debug!("term names: {:?}", term_names); let mut bools_map = HashMap::new(); if bools_bytes != 0 { for i in range(0, bools_bytes) { - let b = file.read_byte().unwrap(); + let b = if_ok!(file.read_byte()); if b < 0 { error!("EOF reading bools after {} entries", i); return Err(~"error: expected more bools but hit EOF"); @@ -242,13 +249,13 @@ pub fn parse(file: &mut io::Reader, if (bools_bytes + names_bytes) % 2 == 1 { debug!("adjusting for padding between bools and numbers"); - file.read_byte(); // compensate for padding + if_ok!(file.read_byte()); // compensate for padding } let mut numbers_map = HashMap::new(); if numbers_count != 0 { for i in range(0, numbers_count) { - let n = file.read_le_u16(); + let n = if_ok!(file.read_le_u16()); if n != 0xFFFF { debug!("{}\\#{}", nnames[i], n); numbers_map.insert(nnames[i].to_owned(), n); @@ -263,12 +270,12 @@ pub fn parse(file: &mut io::Reader, if string_offsets_count != 0 { let mut string_offsets = vec::with_capacity(10); for _ in range(0, string_offsets_count) { - string_offsets.push(file.read_le_u16()); + string_offsets.push(if_ok!(file.read_le_u16())); } debug!("offsets: {:?}", string_offsets); - let string_table = file.read_bytes(string_table_bytes as uint); + let string_table = if_ok!(file.read_bytes(string_table_bytes as uint)); if string_table.len() != string_table_bytes as uint { error!("EOF reading string table after {} bytes, wanted {}", string_table.len(), diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index 8cbb090269783..5b536d9aafa91 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -77,8 +77,8 @@ pub fn open(term: &str) -> Result { match get_dbpath_for_term(term) { Some(x) => { match File::open(x) { - Some(file) => Ok(file), - None => Err(~"error opening file"), + Ok(file) => Ok(file), + Err(e) => Err(format!("error opening file: {}", e)), } } None => Err(format!("could not find terminfo entry for {}", term)) @@ -106,7 +106,7 @@ fn test_get_dbpath_for_term() { #[test] #[ignore(reason = "see test_get_dbpath_for_term")] fn test_open() { - open("screen"); + open("screen").unwrap(); let t = open("nonexistent terminal that hopefully does not exist"); assert!(t.is_err()); } diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index a0e9f96b31db8..6f4a4c43b0395 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::io; use std::io::BufferedWriter; struct DummyWriter; impl Writer for DummyWriter { - fn write(&mut self, _: &[u8]) {} + fn write(&mut self, _: &[u8]) -> io::IoResult<()> { Ok(()) } } static ITER: int = 50; diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 43167458e8600..771e545ece88c 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -36,11 +36,12 @@ fn make_complements() -> [u8, ..256] { fn main() { let complements = make_complements(); - let mut data = if std::os::getenv("RUST_BENCH").is_some() { + let data = if std::os::getenv("RUST_BENCH").is_some() { File::open(&Path::new("shootout-k-nucleotide.data")).read_to_end() } else { stdin().read_to_end() }; + let mut data = data.unwrap(); for seq in data.mut_split(|c| *c == '>' as u8) { // skip header and last \n diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index 171424d8b3b69..17cd8db9d3919 100644 --- a/src/test/run-pass/capturing-logging.rs +++ b/src/test/run-pass/capturing-logging.rs @@ -43,5 +43,5 @@ fn main() { debug!("debug"); info!("info"); }); - assert_eq!(r.read_to_str(), ~"info\n"); + assert_eq!(r.read_to_str().unwrap(), ~"info\n"); } diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 3442e971f4fe5..f3ddc002333dd 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -27,8 +27,7 @@ fn test_destroy_once() { #[cfg(target_os="android")] static PROG: &'static str = "ls"; // android don't have echo binary - let mut p = run::Process::new(PROG, [], run::ProcessOptions::new()) - .expect(format!("failed to exec `{}`", PROG)); + let mut p = run::Process::new(PROG, [], run::ProcessOptions::new()).unwrap(); p.destroy(); // this shouldn't crash (and nor should the destructor) } @@ -39,12 +38,12 @@ fn test_destroy_twice() { #[cfg(target_os="android")] static PROG: &'static str = "ls"; // android don't have echo binary - let mut p = run::Process::new(PROG, [], run::ProcessOptions::new()) - .expect(format!("failed to exec `{}`", PROG)); + let mut p = match run::Process::new(PROG, [], run::ProcessOptions::new()) { + Ok(p) => p, + Err(e) => fail!("wut: {}", e), + }; p.destroy(); // this shouldnt crash... - io::io_error::cond.trap(|_| {}).inside(|| { - p.destroy(); // ...and nor should this (and nor should the destructor) - }) + p.destroy(); // ...and nor should this (and nor should the destructor) } fn test_destroy_actually_kills(force: bool) { @@ -61,14 +60,14 @@ fn test_destroy_actually_kills(force: bool) { #[cfg(unix,not(target_os="android"))] fn process_exists(pid: libc::pid_t) -> bool { let run::ProcessOutput {output, ..} = run::process_output("ps", [~"-p", pid.to_str()]) - .expect("failed to exec `ps`"); + .unwrap(); str::from_utf8_owned(output).unwrap().contains(pid.to_str()) } #[cfg(unix,target_os="android")] fn process_exists(pid: libc::pid_t) -> bool { let run::ProcessOutput {output, ..} = run::process_output("/system/bin/ps", [pid.to_str()]) - .expect("failed to exec `/system/bin/ps`"); + .unwrap(); str::from_utf8_owned(output).unwrap().contains(~"root") } @@ -93,7 +92,7 @@ fn test_destroy_actually_kills(force: bool) { // this process will stay alive indefinitely trying to read from stdin let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new()) - .expect(format!("failed to exec `{}`", BLOCK_COMMAND)); + .unwrap(); assert!(process_exists(p.get_id())); diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index cc59ce5d8b245..b66446b0cfe43 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -12,6 +12,7 @@ #[feature(macro_rules)]; #[deny(warnings)]; +#[allow(unused_must_use)]; use std::fmt; use std::io::MemWriter; @@ -22,10 +23,14 @@ struct A; struct B; impl fmt::Signed for A { - fn fmt(_: &A, f: &mut fmt::Formatter) { f.buf.write("aloha".as_bytes()); } + fn fmt(_: &A, f: &mut fmt::Formatter) -> fmt::Result { + f.buf.write("aloha".as_bytes()) + } } impl fmt::Signed for B { - fn fmt(_: &B, f: &mut fmt::Formatter) { f.buf.write("adios".as_bytes()); } + fn fmt(_: &B, f: &mut fmt::Formatter) -> fmt::Result { + f.buf.write("adios".as_bytes()) + } } macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a, $b.to_owned()) }) @@ -286,9 +291,9 @@ fn test_format_args() { let mut buf = MemWriter::new(); { let w = &mut buf as &mut io::Writer; - format_args!(|args| { fmt::write(w, args) }, "{}", 1); - format_args!(|args| { fmt::write(w, args) }, "test"); - format_args!(|args| { fmt::write(w, args) }, "{test}", test=3); + format_args!(|args| { fmt::write(w, args); }, "{}", 1); + format_args!(|args| { fmt::write(w, args); }, "test"); + format_args!(|args| { fmt::write(w, args); }, "{test}", test=3); } let s = str::from_utf8_owned(buf.unwrap()).unwrap(); t!(s, "1test3"); diff --git a/src/test/run-pass/issue-8398.rs b/src/test/run-pass/issue-8398.rs index f9169618c2a3b..0884db633264e 100644 --- a/src/test/run-pass/issue-8398.rs +++ b/src/test/run-pass/issue-8398.rs @@ -11,7 +11,7 @@ use std::io; fn foo(a: &mut io::Writer) { - a.write([]) + a.write([]).unwrap(); } pub fn main(){} diff --git a/src/test/run-pass/logging-only-prints-once.rs b/src/test/run-pass/logging-only-prints-once.rs index 4aef239f796f7..dccdc8ae3ba21 100644 --- a/src/test/run-pass/logging-only-prints-once.rs +++ b/src/test/run-pass/logging-only-prints-once.rs @@ -17,10 +17,11 @@ use std::fmt; struct Foo(Cell); impl fmt::Show for Foo { - fn fmt(f: &Foo, _fmt: &mut fmt::Formatter) { + fn fmt(f: &Foo, _fmt: &mut fmt::Formatter) -> fmt::Result { let Foo(ref f) = *f; assert!(f.get() == 0); f.set(1); + Ok(()) } } diff --git a/src/test/run-pass/signal-exit-status.rs b/src/test/run-pass/signal-exit-status.rs index dc74e9fb47051..0e8ca4d99428b 100644 --- a/src/test/run-pass/signal-exit-status.rs +++ b/src/test/run-pass/signal-exit-status.rs @@ -19,8 +19,7 @@ pub fn main() { // Raise a segfault. unsafe { *(0 as *mut int) = 0; } } else { - let status = run::process_status(args[0], [~"signal"]) - .expect("failed to exec `signal`"); + let status = run::process_status(args[0], [~"signal"]).unwrap(); // Windows does not have signal, so we get exit status 0xC0000028 (STATUS_BAD_STACK). match status { process::ExitSignal(_) if cfg!(unix) => {}, diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs index b186a68281062..7f04da0734d8f 100644 --- a/src/test/run-pass/stat.rs +++ b/src/test/run-pass/stat.rs @@ -21,8 +21,8 @@ pub fn main() { { match File::create(&path) { - None => unreachable!(), - Some(f) => { + Err(..) => unreachable!(), + Ok(f) => { let mut f = f; for _ in range(0u, 1000) { f.write([0]); @@ -32,5 +32,5 @@ pub fn main() { } assert!(path.exists()); - assert_eq!(path.stat().size, 1000); + assert_eq!(path.stat().unwrap().size, 1000); }