diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2022-06-07 13:30:45 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2022-06-08 07:01:26 +1000 |
| commit | 1acbe7573dc32f917f51a784a36b7afc690900e3 (patch) | |
| tree | 1b4e8d414de3d349bd3ae038c28e9dc77e54c345 /compiler/rustc_serialize/src | |
| parent | 582b9cbc45334a73467d6ccaf0a8b9de559c2011 (diff) | |
| download | rust-1acbe7573dc32f917f51a784a36b7afc690900e3.tar.gz rust-1acbe7573dc32f917f51a784a36b7afc690900e3.zip | |
Use delayed error handling for `Encodable` and `Encoder` infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
Diffstat (limited to 'compiler/rustc_serialize/src')
| -rw-r--r-- | compiler/rustc_serialize/src/collection_impls.rs | 74 | ||||
| -rw-r--r-- | compiler/rustc_serialize/src/opaque.rs | 240 | ||||
| -rw-r--r-- | compiler/rustc_serialize/src/serialize.rs | 156 |
3 files changed, 246 insertions, 224 deletions
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs index c4541bbcac9..5e53f0b104d 100644 --- a/compiler/rustc_serialize/src/collection_impls.rs +++ b/compiler/rustc_serialize/src/collection_impls.rs @@ -10,9 +10,9 @@ use std::sync::Arc; use smallvec::{Array, SmallVec}; impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { let slice: &[A::Item] = self; - slice.encode(s) + slice.encode(s); } } @@ -24,12 +24,11 @@ impl<D: Decoder, A: Array<Item: Decodable<D>>> Decodable<D> for SmallVec<A> { } impl<S: Encoder, T: Encodable<S>> Encodable<S> for LinkedList<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_usize(self.len())?; + fn encode(&self, s: &mut S) { + s.emit_usize(self.len()); for e in self.iter() { - e.encode(s)?; + e.encode(s); } - Ok(()) } } @@ -41,12 +40,11 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for LinkedList<T> { } impl<S: Encoder, T: Encodable<S>> Encodable<S> for VecDeque<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_usize(self.len())?; + fn encode(&self, s: &mut S) { + s.emit_usize(self.len()); for e in self.iter() { - e.encode(s)?; + e.encode(s); } - Ok(()) } } @@ -62,13 +60,12 @@ where K: Encodable<S> + PartialEq + Ord, V: Encodable<S>, { - fn encode(&self, e: &mut S) -> Result<(), S::Error> { - e.emit_usize(self.len())?; + fn encode(&self, e: &mut S) { + e.emit_usize(self.len()); for (key, val) in self.iter() { - key.encode(e)?; - val.encode(e)?; + key.encode(e); + val.encode(e); } - Ok(()) } } @@ -93,12 +90,11 @@ impl<S: Encoder, T> Encodable<S> for BTreeSet<T> where T: Encodable<S> + PartialEq + Ord, { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_usize(self.len())?; + fn encode(&self, s: &mut S) { + s.emit_usize(self.len()); for e in self.iter() { - e.encode(s)?; + e.encode(s); } - Ok(()) } } @@ -122,13 +118,12 @@ where V: Encodable<E>, S: BuildHasher, { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - e.emit_usize(self.len())?; + fn encode(&self, e: &mut E) { + e.emit_usize(self.len()); for (key, val) in self.iter() { - key.encode(e)?; - val.encode(e)?; + key.encode(e); + val.encode(e); } - Ok(()) } } @@ -156,12 +151,11 @@ where T: Encodable<E> + Eq, S: BuildHasher, { - fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_usize(self.len())?; + fn encode(&self, s: &mut E) { + s.emit_usize(self.len()); for e in self.iter() { - e.encode(s)?; + e.encode(s); } - Ok(()) } } @@ -187,13 +181,12 @@ where V: Encodable<E>, S: BuildHasher, { - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - e.emit_usize(self.len())?; + fn encode(&self, e: &mut E) { + e.emit_usize(self.len()); for (key, val) in self.iter() { - key.encode(e)?; - val.encode(e)?; + key.encode(e); + val.encode(e); } - Ok(()) } } @@ -221,12 +214,11 @@ where T: Encodable<E> + Hash + Eq, S: BuildHasher, { - fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_usize(self.len())?; + fn encode(&self, s: &mut E) { + s.emit_usize(self.len()); for e in self.iter() { - e.encode(s)?; + e.encode(s); } - Ok(()) } } @@ -247,9 +239,9 @@ where } impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> { - fn encode(&self, s: &mut E) -> Result<(), E::Error> { + fn encode(&self, s: &mut E) { let slice: &[T] = self; - slice.encode(s) + slice.encode(s); } } @@ -261,9 +253,9 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> { } impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> { - fn encode(&self, s: &mut E) -> Result<(), E::Error> { + fn encode(&self, s: &mut E) { let slice: &[T] = self; - slice.encode(s) + slice.encode(s); } } diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 40b79ba89ef..b2dbf937eb7 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -11,8 +11,6 @@ use std::ptr; // Encoder // ----------------------------------------------------------------------------- -pub type EncodeResult = Result<(), !>; - pub struct Encoder { pub data: Vec<u8>, } @@ -22,10 +20,6 @@ impl Encoder { Encoder { data: vec![] } } - pub fn into_inner(self) -> Vec<u8> { - self.data - } - #[inline] pub fn position(&self) -> usize { self.data.len() @@ -49,8 +43,6 @@ macro_rules! write_leb128 { let encoded = leb128::$fun(buf, $value); $enc.data.set_len(old_len + encoded.len()); } - - Ok(()) }}; } @@ -62,108 +54,109 @@ macro_rules! write_leb128 { const STR_SENTINEL: u8 = 0xC1; impl serialize::Encoder for Encoder { - type Error = !; + type Ok = Vec<u8>; + type Err = !; #[inline] - fn emit_usize(&mut self, v: usize) -> EncodeResult { + fn emit_usize(&mut self, v: usize) { write_leb128!(self, v, usize, write_usize_leb128) } #[inline] - fn emit_u128(&mut self, v: u128) -> EncodeResult { - write_leb128!(self, v, u128, write_u128_leb128) + fn emit_u128(&mut self, v: u128) { + write_leb128!(self, v, u128, write_u128_leb128); } #[inline] - fn emit_u64(&mut self, v: u64) -> EncodeResult { - write_leb128!(self, v, u64, write_u64_leb128) + fn emit_u64(&mut self, v: u64) { + write_leb128!(self, v, u64, write_u64_leb128); } #[inline] - fn emit_u32(&mut self, v: u32) -> EncodeResult { - write_leb128!(self, v, u32, write_u32_leb128) + fn emit_u32(&mut self, v: u32) { + write_leb128!(self, v, u32, write_u32_leb128); } #[inline] - fn emit_u16(&mut self, v: u16) -> EncodeResult { + fn emit_u16(&mut self, v: u16) { self.data.extend_from_slice(&v.to_le_bytes()); - Ok(()) } #[inline] - fn emit_u8(&mut self, v: u8) -> EncodeResult { + fn emit_u8(&mut self, v: u8) { self.data.push(v); - Ok(()) } #[inline] - fn emit_isize(&mut self, v: isize) -> EncodeResult { + fn emit_isize(&mut self, v: isize) { write_leb128!(self, v, isize, write_isize_leb128) } #[inline] - fn emit_i128(&mut self, v: i128) -> EncodeResult { + fn emit_i128(&mut self, v: i128) { write_leb128!(self, v, i128, write_i128_leb128) } #[inline] - fn emit_i64(&mut self, v: i64) -> EncodeResult { + fn emit_i64(&mut self, v: i64) { write_leb128!(self, v, i64, write_i64_leb128) } #[inline] - fn emit_i32(&mut self, v: i32) -> EncodeResult { + fn emit_i32(&mut self, v: i32) { write_leb128!(self, v, i32, write_i32_leb128) } #[inline] - fn emit_i16(&mut self, v: i16) -> EncodeResult { + fn emit_i16(&mut self, v: i16) { self.data.extend_from_slice(&v.to_le_bytes()); - Ok(()) } #[inline] - fn emit_i8(&mut self, v: i8) -> EncodeResult { - self.emit_u8(v as u8) + fn emit_i8(&mut self, v: i8) { + self.emit_u8(v as u8); } #[inline] - fn emit_bool(&mut self, v: bool) -> EncodeResult { - self.emit_u8(if v { 1 } else { 0 }) + fn emit_bool(&mut self, v: bool) { + self.emit_u8(if v { 1 } else { 0 }); } #[inline] - fn emit_f64(&mut self, v: f64) -> EncodeResult { + fn emit_f64(&mut self, v: f64) { let as_u64: u64 = v.to_bits(); - self.emit_u64(as_u64) + self.emit_u64(as_u64); } #[inline] - fn emit_f32(&mut self, v: f32) -> EncodeResult { + fn emit_f32(&mut self, v: f32) { let as_u32: u32 = v.to_bits(); - self.emit_u32(as_u32) + self.emit_u32(as_u32); } #[inline] - fn emit_char(&mut self, v: char) -> EncodeResult { - self.emit_u32(v as u32) + fn emit_char(&mut self, v: char) { + self.emit_u32(v as u32); } #[inline] - fn emit_str(&mut self, v: &str) -> EncodeResult { - self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes())?; - self.emit_u8(STR_SENTINEL) + fn emit_str(&mut self, v: &str) { + self.emit_usize(v.len()); + self.emit_raw_bytes(v.as_bytes()); + self.emit_u8(STR_SENTINEL); } #[inline] - fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult { + fn emit_raw_bytes(&mut self, s: &[u8]) { self.data.extend_from_slice(s); - Ok(()) + } + + fn finish(self) -> Result<Self::Ok, Self::Err> { + Ok(self.data) } } -pub type FileEncodeResult = Result<(), io::Error>; +pub type FileEncodeResult = Result<usize, io::Error>; // `FileEncoder` encodes data to file via fixed-size buffer. // @@ -182,6 +175,9 @@ pub struct FileEncoder { buffered: usize, flushed: usize, file: File, + // This is used to implement delayed error handling, as described in the + // comment on `trait Encoder`. + res: Result<(), io::Error>, } impl FileEncoder { @@ -202,7 +198,13 @@ impl FileEncoder { let file = File::create(path)?; - Ok(FileEncoder { buf: Box::new_uninit_slice(capacity), buffered: 0, flushed: 0, file }) + Ok(FileEncoder { + buf: Box::new_uninit_slice(capacity), + buffered: 0, + flushed: 0, + file, + res: Ok(()), + }) } #[inline] @@ -212,7 +214,7 @@ impl FileEncoder { self.flushed + self.buffered } - pub fn flush(&mut self) -> FileEncodeResult { + pub fn flush(&mut self) { // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever // offers a raw buffer access API, we can use it, and remove this. @@ -267,6 +269,12 @@ impl FileEncoder { } } + // If we've already had an error, do nothing. It'll get reported after + // `finish` is called. + if self.res.is_err() { + return; + } + let mut guard = BufGuard::new( unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) }, &mut self.buffered, @@ -276,18 +284,20 @@ impl FileEncoder { while !guard.done() { match self.file.write(guard.remaining()) { Ok(0) => { - return Err(io::Error::new( + self.res = Err(io::Error::new( io::ErrorKind::WriteZero, "failed to write the buffered data", )); + return; } Ok(n) => guard.consume(n), Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(e) => return Err(e), + Err(e) => { + self.res = Err(e); + return; + } } } - - Ok(()) } #[inline] @@ -296,14 +306,14 @@ impl FileEncoder { } #[inline] - fn write_one(&mut self, value: u8) -> FileEncodeResult { + fn write_one(&mut self, value: u8) { // We ensure this during `FileEncoder` construction. debug_assert!(self.capacity() >= 1); let mut buffered = self.buffered; if std::intrinsics::unlikely(buffered >= self.capacity()) { - self.flush()?; + self.flush(); buffered = 0; } @@ -314,12 +324,10 @@ impl FileEncoder { } self.buffered = buffered + 1; - - Ok(()) } #[inline] - fn write_all(&mut self, buf: &[u8]) -> FileEncodeResult { + fn write_all(&mut self, buf: &[u8]) { let capacity = self.capacity(); let buf_len = buf.len(); @@ -327,7 +335,7 @@ impl FileEncoder { let mut buffered = self.buffered; if std::intrinsics::unlikely(buf_len > capacity - buffered) { - self.flush()?; + self.flush(); buffered = 0; } @@ -340,16 +348,20 @@ impl FileEncoder { } self.buffered = buffered + buf_len; - - Ok(()) } else { - self.write_all_unbuffered(buf) + self.write_all_unbuffered(buf); } } - fn write_all_unbuffered(&mut self, mut buf: &[u8]) -> FileEncodeResult { + fn write_all_unbuffered(&mut self, mut buf: &[u8]) { + // If we've already had an error, do nothing. It'll get reported after + // `finish` is called. + if self.res.is_err() { + return; + } + if self.buffered > 0 { - self.flush()?; + self.flush(); } // This is basically a copy of `Write::write_all` but also updates our @@ -359,26 +371,30 @@ impl FileEncoder { while !buf.is_empty() { match self.file.write(buf) { Ok(0) => { - return Err(io::Error::new( + self.res = Err(io::Error::new( io::ErrorKind::WriteZero, "failed to write whole buffer", )); + return; } Ok(n) => { buf = &buf[n..]; self.flushed += n; } Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(e) => return Err(e), + Err(e) => { + self.res = Err(e); + return; + } } } - - Ok(()) } } impl Drop for FileEncoder { fn drop(&mut self) { + // Likely to be a no-op, because `finish` should have been called and + // it also flushes. But do it just in case. let _result = self.flush(); } } @@ -394,7 +410,7 @@ macro_rules! file_encoder_write_leb128 { // This can't overflow. See assertion in `FileEncoder::with_capacity`. if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) { - $enc.flush()?; + $enc.flush(); buffered = 0; } @@ -406,106 +422,112 @@ macro_rules! file_encoder_write_leb128 { let encoded = leb128::$fun(buf, $value); $enc.buffered = buffered + encoded.len(); - - Ok(()) }}; } impl serialize::Encoder for FileEncoder { - type Error = io::Error; + type Ok = usize; + type Err = io::Error; #[inline] - fn emit_usize(&mut self, v: usize) -> FileEncodeResult { + fn emit_usize(&mut self, v: usize) { file_encoder_write_leb128!(self, v, usize, write_usize_leb128) } #[inline] - fn emit_u128(&mut self, v: u128) -> FileEncodeResult { + fn emit_u128(&mut self, v: u128) { file_encoder_write_leb128!(self, v, u128, write_u128_leb128) } #[inline] - fn emit_u64(&mut self, v: u64) -> FileEncodeResult { + fn emit_u64(&mut self, v: u64) { file_encoder_write_leb128!(self, v, u64, write_u64_leb128) } #[inline] - fn emit_u32(&mut self, v: u32) -> FileEncodeResult { + fn emit_u32(&mut self, v: u32) { file_encoder_write_leb128!(self, v, u32, write_u32_leb128) } #[inline] - fn emit_u16(&mut self, v: u16) -> FileEncodeResult { - self.write_all(&v.to_le_bytes()) + fn emit_u16(&mut self, v: u16) { + self.write_all(&v.to_le_bytes()); } #[inline] - fn emit_u8(&mut self, v: u8) -> FileEncodeResult { - self.write_one(v) + fn emit_u8(&mut self, v: u8) { + self.write_one(v); } #[inline] - fn emit_isize(&mut self, v: isize) -> FileEncodeResult { + fn emit_isize(&mut self, v: isize) { file_encoder_write_leb128!(self, v, isize, write_isize_leb128) } #[inline] - fn emit_i128(&mut self, v: i128) -> FileEncodeResult { + fn emit_i128(&mut self, v: i128) { file_encoder_write_leb128!(self, v, i128, write_i128_leb128) } #[inline] - fn emit_i64(&mut self, v: i64) -> FileEncodeResult { + fn emit_i64(&mut self, v: i64) { file_encoder_write_leb128!(self, v, i64, write_i64_leb128) } #[inline] - fn emit_i32(&mut self, v: i32) -> FileEncodeResult { + fn emit_i32(&mut self, v: i32) { file_encoder_write_leb128!(self, v, i32, write_i32_leb128) } #[inline] - fn emit_i16(&mut self, v: i16) -> FileEncodeResult { - self.write_all(&v.to_le_bytes()) + fn emit_i16(&mut self, v: i16) { + self.write_all(&v.to_le_bytes()); } #[inline] - fn emit_i8(&mut self, v: i8) -> FileEncodeResult { - self.emit_u8(v as u8) + fn emit_i8(&mut self, v: i8) { + self.emit_u8(v as u8); } #[inline] - fn emit_bool(&mut self, v: bool) -> FileEncodeResult { - self.emit_u8(if v { 1 } else { 0 }) + fn emit_bool(&mut self, v: bool) { + self.emit_u8(if v { 1 } else { 0 }); } #[inline] - fn emit_f64(&mut self, v: f64) -> FileEncodeResult { + fn emit_f64(&mut self, v: f64) { let as_u64: u64 = v.to_bits(); - self.emit_u64(as_u64) + self.emit_u64(as_u64); } #[inline] - fn emit_f32(&mut self, v: f32) -> FileEncodeResult { + fn emit_f32(&mut self, v: f32) { let as_u32: u32 = v.to_bits(); - self.emit_u32(as_u32) + self.emit_u32(as_u32); } #[inline] - fn emit_char(&mut self, v: char) -> FileEncodeResult { - self.emit_u32(v as u32) + fn emit_char(&mut self, v: char) { + self.emit_u32(v as u32); } #[inline] - fn emit_str(&mut self, v: &str) -> FileEncodeResult { - self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes())?; - self.emit_u8(STR_SENTINEL) + fn emit_str(&mut self, v: &str) { + self.emit_usize(v.len()); + self.emit_raw_bytes(v.as_bytes()); + self.emit_u8(STR_SENTINEL); } #[inline] - fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { - self.write_all(s) + fn emit_raw_bytes(&mut self, s: &[u8]) { + self.write_all(s); + } + + fn finish(mut self) -> Result<usize, io::Error> { + self.flush(); + + let res = std::mem::replace(&mut self.res, Ok(())); + res.map(|()| self.position()) } } @@ -667,16 +689,16 @@ impl<'a> serialize::Decoder for Decoder<'a> { // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc., // since the default implementations call `encode` on their slices internally. impl serialize::Encodable<Encoder> for [u8] { - fn encode(&self, e: &mut Encoder) -> EncodeResult { - serialize::Encoder::emit_usize(e, self.len())?; - e.emit_raw_bytes(self) + fn encode(&self, e: &mut Encoder) { + serialize::Encoder::emit_usize(e, self.len()); + e.emit_raw_bytes(self); } } impl serialize::Encodable<FileEncoder> for [u8] { - fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { - serialize::Encoder::emit_usize(e, self.len())?; - e.emit_raw_bytes(self) + fn encode(&self, e: &mut FileEncoder) { + serialize::Encoder::emit_usize(e, self.len()); + e.emit_raw_bytes(self); } } @@ -698,23 +720,21 @@ impl IntEncodedWithFixedSize { impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize { #[inline] - fn encode(&self, e: &mut Encoder) -> EncodeResult { + fn encode(&self, e: &mut Encoder) { let _start_pos = e.position(); - e.emit_raw_bytes(&self.0.to_le_bytes())?; + e.emit_raw_bytes(&self.0.to_le_bytes()); let _end_pos = e.position(); debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(()) } } impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize { #[inline] - fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { + fn encode(&self, e: &mut FileEncoder) { let _start_pos = e.position(); - e.emit_raw_bytes(&self.0.to_le_bytes())?; + e.emit_raw_bytes(&self.0.to_le_bytes()); let _end_pos = e.position(); debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); - Ok(()) } } diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 817a0c9dcb1..98bb18581f5 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -11,36 +11,47 @@ use std::path; use std::rc::Rc; use std::sync::Arc; +/// A note about error handling. +/// +/// Encoders may be fallible, but in practice failure is rare and there are so +/// many nested calls that typical Rust error handling (via `Result` and `?`) +/// is pervasive and has non-trivial cost. Instead, impls of this trait must +/// implement a delayed error handling strategy. If a failure occurs, they +/// should record this internally, and all subsequent encoding operations can +/// be processed or ignored, whichever is appropriate. Then when `finish()` is +/// called, an error result should be returned to indicate the failure. If no +/// failures occurred, then `finish()` should return a success result. pub trait Encoder { - type Error; + type Ok; + type Err; // Primitive types: - fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>; - fn emit_u128(&mut self, v: u128) -> Result<(), Self::Error>; - fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; - fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; - fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; - fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; - fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>; - fn emit_i128(&mut self, v: i128) -> Result<(), Self::Error>; - fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; - fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; - fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; - fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>; - fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>; - fn emit_f64(&mut self, v: f64) -> Result<(), Self::Error>; - fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; - fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; - fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; - fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>; + fn emit_usize(&mut self, v: usize); + fn emit_u128(&mut self, v: u128); + fn emit_u64(&mut self, v: u64); + fn emit_u32(&mut self, v: u32); + fn emit_u16(&mut self, v: u16); + fn emit_u8(&mut self, v: u8); + fn emit_isize(&mut self, v: isize); + fn emit_i128(&mut self, v: i128); + fn emit_i64(&mut self, v: i64); + fn emit_i32(&mut self, v: i32); + fn emit_i16(&mut self, v: i16); + fn emit_i8(&mut self, v: i8); + fn emit_bool(&mut self, v: bool); + fn emit_f64(&mut self, v: f64); + fn emit_f32(&mut self, v: f32); + fn emit_char(&mut self, v: char); + fn emit_str(&mut self, v: &str); + fn emit_raw_bytes(&mut self, s: &[u8]); // Convenience for the derive macro: - fn emit_enum_variant<F>(&mut self, v_id: usize, f: F) -> Result<(), Self::Error> + fn emit_enum_variant<F>(&mut self, v_id: usize, f: F) where - F: FnOnce(&mut Self) -> Result<(), Self::Error>, + F: FnOnce(&mut Self), { - self.emit_usize(v_id)?; - f(self) + self.emit_usize(v_id); + f(self); } // We put the field index in a const generic to allow the emit_usize to be @@ -50,9 +61,12 @@ pub trait Encoder { // optimization that would otherwise be necessary here, likely due to the // multiple levels of inlining and const-prop that are needed. #[inline] - fn emit_fieldless_enum_variant<const ID: usize>(&mut self) -> Result<(), Self::Error> { + fn emit_fieldless_enum_variant<const ID: usize>(&mut self) { self.emit_usize(ID) } + + // Consume the encoder, getting the result. + fn finish(self) -> Result<Self::Ok, Self::Err>; } // Note: all the methods in this trait are infallible, which may be surprising. @@ -95,7 +109,7 @@ pub trait Decoder { /// * `TyEncodable` should be used for types that are only serialized in crate /// metadata or the incremental cache. This is most types in `rustc_middle`. pub trait Encodable<S: Encoder> { - fn encode(&self, s: &mut S) -> Result<(), S::Error>; + fn encode(&self, s: &mut S); } /// Trait for types that can be deserialized @@ -117,8 +131,8 @@ macro_rules! direct_serialize_impls { ($($ty:ident $emit_method:ident $read_method:ident),*) => { $( impl<S: Encoder> Encodable<S> for $ty { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.$emit_method(*self) + fn encode(&self, s: &mut S) { + s.$emit_method(*self); } } @@ -138,12 +152,14 @@ direct_serialize_impls! { u32 emit_u32 read_u32, u64 emit_u64 read_u64, u128 emit_u128 read_u128, + isize emit_isize read_isize, i8 emit_i8 read_i8, i16 emit_i16 read_i16, i32 emit_i32 read_i32, i64 emit_i64 read_i64, i128 emit_i128 read_i128, + f32 emit_f32 read_f32, f64 emit_f64 read_f64, bool emit_bool read_bool, @@ -154,14 +170,14 @@ impl<S: Encoder, T: ?Sized> Encodable<S> for &T where T: Encodable<S>, { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { (**self).encode(s) } } impl<S: Encoder> Encodable<S> for ! { - fn encode(&self, _s: &mut S) -> Result<(), S::Error> { - unreachable!() + fn encode(&self, _s: &mut S) { + unreachable!(); } } @@ -172,8 +188,8 @@ impl<D: Decoder> Decodable<D> for ! { } impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_u32(self.get()) + fn encode(&self, s: &mut S) { + s.emit_u32(self.get()); } } @@ -184,14 +200,14 @@ impl<D: Decoder> Decodable<D> for ::std::num::NonZeroU32 { } impl<S: Encoder> Encodable<S> for str { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(self) + fn encode(&self, s: &mut S) { + s.emit_str(self); } } impl<S: Encoder> Encodable<S> for String { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self[..]) + fn encode(&self, s: &mut S) { + s.emit_str(&self[..]); } } @@ -202,9 +218,7 @@ impl<D: Decoder> Decodable<D> for String { } impl<S: Encoder> Encodable<S> for () { - fn encode(&self, _s: &mut S) -> Result<(), S::Error> { - Ok(()) - } + fn encode(&self, _s: &mut S) {} } impl<D: Decoder> Decodable<D> for () { @@ -212,9 +226,7 @@ impl<D: Decoder> Decodable<D> for () { } impl<S: Encoder, T> Encodable<S> for PhantomData<T> { - fn encode(&self, _s: &mut S) -> Result<(), S::Error> { - Ok(()) - } + fn encode(&self, _s: &mut S) {} } impl<D: Decoder, T> Decodable<D> for PhantomData<T> { @@ -231,8 +243,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<[T]> { } impl<S: Encoder, T: Encodable<S>> Encodable<S> for Rc<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (**self).encode(s) + fn encode(&self, s: &mut S) { + (**self).encode(s); } } @@ -243,19 +255,18 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> { } impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] { - default fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_usize(self.len())?; + default fn encode(&self, s: &mut S) { + s.emit_usize(self.len()); for e in self.iter() { - e.encode(s)? + e.encode(s); } - Ok(()) } } impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { let slice: &[T] = self; - slice.encode(s) + slice.encode(s); } } @@ -277,9 +288,9 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> { } impl<S: Encoder, T: Encodable<S>, const N: usize> Encodable<S> for [T; N] { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { let slice: &[T] = self; - slice.encode(s) + slice.encode(s); } } @@ -299,9 +310,9 @@ impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]> where [T]: ToOwned<Owned = Vec<T>>, { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { let slice: &[T] = self; - slice.encode(s) + slice.encode(s); } } @@ -316,7 +327,7 @@ where } impl<'a, S: Encoder> Encodable<S> for Cow<'a, str> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { let val: &str = self; val.encode(s) } @@ -330,9 +341,9 @@ impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> { } impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { match *self { - None => s.emit_enum_variant(0, |_| Ok(())), + None => s.emit_enum_variant(0, |_| {}), Some(ref v) => s.emit_enum_variant(1, |s| v.encode(s)), } } @@ -349,7 +360,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> { } impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { match *self { Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)), Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)), @@ -381,10 +392,9 @@ macro_rules! tuple { } impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) { #[allow(non_snake_case)] - fn encode(&self, s: &mut S) -> Result<(), S::Error> { + fn encode(&self, s: &mut S) { let ($(ref $name,)+) = *self; - $($name.encode(s)?;)+ - Ok(()) + $($name.encode(s);)+ } } peel! { $($name,)+ } @@ -394,14 +404,14 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } impl<S: Encoder> Encodable<S> for path::Path { - fn encode(&self, e: &mut S) -> Result<(), S::Error> { - self.to_str().unwrap().encode(e) + fn encode(&self, e: &mut S) { + self.to_str().unwrap().encode(e); } } impl<S: Encoder> Encodable<S> for path::PathBuf { - fn encode(&self, e: &mut S) -> Result<(), S::Error> { - path::Path::encode(self, e) + fn encode(&self, e: &mut S) { + path::Path::encode(self, e); } } @@ -413,8 +423,8 @@ impl<D: Decoder> Decodable<D> for path::PathBuf { } impl<S: Encoder, T: Encodable<S> + Copy> Encodable<S> for Cell<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.get().encode(s) + fn encode(&self, s: &mut S) { + self.get().encode(s); } } @@ -430,8 +440,8 @@ impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> { // from `encode` when `try_borrow` returns `None`. impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.borrow().encode(s) + fn encode(&self, s: &mut S) { + self.borrow().encode(s); } } @@ -442,8 +452,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for RefCell<T> { } impl<S: Encoder, T: Encodable<S>> Encodable<S> for Arc<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (**self).encode(s) + fn encode(&self, s: &mut S) { + (**self).encode(s); } } @@ -454,8 +464,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<T> { } impl<S: Encoder, T: ?Sized + Encodable<S>> Encodable<S> for Box<T> { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (**self).encode(s) + fn encode(&self, s: &mut S) { + (**self).encode(s); } } impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<T> { |
