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`.
This commit is contained in:
parent
582b9cbc45
commit
1acbe7573d
45 changed files with 611 additions and 682 deletions
|
@ -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> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue