diff options
| author | bors <bors@rust-lang.org> | 2022-02-22 07:54:22 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-02-22 07:54:22 +0000 |
| commit | 58a721af9f818bdf57f86448557b45c5ae19a3ef (patch) | |
| tree | 086ddac67129cf7c2503daae81f5b0e03706ba81 /compiler/rustc_serialize/src/serialize.rs | |
| parent | b8967b0d52a2ba5f0c9da0da03e78ccba5534e4a (diff) | |
| parent | c6ad61a1bd2d82f4ac8f7e3c069caa1c2f52c1b4 (diff) | |
| download | rust-58a721af9f818bdf57f86448557b45c5ae19a3ef.tar.gz rust-58a721af9f818bdf57f86448557b45c5ae19a3ef.zip | |
Auto merge of #93839 - Mark-Simulacrum:delete-json-rust-deserialization, r=nnethercote
Simplify rustc_serialize by dropping support for decoding into JSON This PR currently bundles two (somewhat separate) tasks. First, it removes the JSON Decoder trait impl, which permitted going from JSON to Rust structs. For now, we keep supporting JSON deserialization, but only to `Json` (an equivalent of serde_json::Value). The primary hard to remove user there is for custom targets -- which need some form of JSON deserialization -- but they already have a custom ad-hoc pass for moving from Json to a Rust struct. A [comment](https://github.com/rust-lang/rust/blob/e7aca895980f25f6d2d3c48e10fd04656764d1e4/compiler/rustc_target/src/spec/mod.rs#L1653) there suggests that it would be impractical to move them to a Decodable-based impl, at least without backwards compatibility concerns. I suspect that if we were widely breaking compat there, it would make sense to use serde_json at this point which would produce better error messages; the types in rustc_target are relatively isolated so we would not particularly suffer from using serde_derive. The second part of the PR (all but the first commit) is to simplify the Decoder API by removing the non-primitive `read_*` functions. These primarily add indirection (through a closure), which doesn't directly cause a performance issue (the unique closure types essentially guarantee monomorphization), but does increase the amount of work rustc and LLVM need to do. This could be split out to a separate PR, but is included here in part to help motivate the first part. Future work might consist of: * Specializing enum discriminant encoding to avoid leb128 for small enums (since we know the variant count, we can directly use read/write u8 in almost all cases) * Adding new methods to support faster deserialization (e.g., access to the underlying byte stream) * Currently these are somewhat ad-hoc supported by specializations for e.g. `Vec<u8>`, but other types which could benefit don't today. * Removing the Decoder trait entirely in favor of a concrete type -- today, we only really have one impl of it modulo wrappers used for specialization-based dispatch. Highly recommend review with whitespace changes off, as the removal of closures frequently causes things to be de-indented.
Diffstat (limited to 'compiler/rustc_serialize/src/serialize.rs')
| -rw-r--r-- | compiler/rustc_serialize/src/serialize.rs | 185 |
1 files changed, 31 insertions, 154 deletions
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index a6172403fd6..a012be2857e 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -200,118 +200,6 @@ pub trait Decoder { fn read_char(&mut self) -> char; fn read_str(&mut self) -> Cow<'_, str>; fn read_raw_bytes_into(&mut self, s: &mut [u8]); - - // Compound types: - #[inline] - fn read_enum<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F) -> T - where - F: FnMut(&mut Self, usize) -> T, - { - let disr = self.read_usize(); - f(self, disr) - } - - #[inline] - fn read_enum_variant_arg<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_struct<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_struct_field<T, F>(&mut self, _f_name: &str, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_tuple<T, F>(&mut self, _len: usize, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_tuple_arg<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - // Specialized types: - fn read_option<T, F>(&mut self, mut f: F) -> T - where - F: FnMut(&mut Self, bool) -> T, - { - self.read_enum(move |this| { - this.read_enum_variant(&["None", "Some"], move |this, idx| match idx { - 0 => f(this, false), - 1 => f(this, true), - _ => panic!("read_option: expected 0 for None or 1 for Some"), - }) - }) - } - - fn read_seq<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self, usize) -> T, - { - let len = self.read_usize(); - f(self, len) - } - - #[inline] - fn read_seq_elt<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - fn read_map<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self, usize) -> T, - { - let len = self.read_usize(); - f(self, len) - } - - #[inline] - fn read_map_elt_key<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_map_elt_val<T, F>(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } } /// Trait for types that can be serialized @@ -493,22 +381,18 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> { impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> { default fn decode(d: &mut D) -> Vec<T> { - d.read_seq(|d, len| { - // SAFETY: we set the capacity in advance, only write elements, and - // only set the length at the end once the writing has succeeded. - let mut vec = Vec::with_capacity(len); - unsafe { - let ptr: *mut T = vec.as_mut_ptr(); - for i in 0..len { - std::ptr::write( - ptr.offset(i as isize), - d.read_seq_elt(|d| Decodable::decode(d)), - ); - } - vec.set_len(len); + let len = d.read_usize(); + // SAFETY: we set the capacity in advance, only write elements, and + // only set the length at the end once the writing has succeeded. + let mut vec = Vec::with_capacity(len); + unsafe { + let ptr: *mut T = vec.as_mut_ptr(); + for i in 0..len { + std::ptr::write(ptr.offset(i as isize), Decodable::decode(d)); } - vec - }) + vec.set_len(len); + } + vec } } @@ -521,14 +405,13 @@ impl<S: Encoder, T: Encodable<S>, const N: usize> Encodable<S> for [T; N] { impl<D: Decoder, const N: usize> Decodable<D> for [u8; N] { fn decode(d: &mut D) -> [u8; N] { - d.read_seq(|d, len| { - assert!(len == N); - let mut v = [0u8; N]; - for i in 0..len { - v[i] = d.read_seq_elt(|d| Decodable::decode(d)); - } - v - }) + let len = d.read_usize(); + assert!(len == N); + let mut v = [0u8; N]; + for i in 0..len { + v[i] = Decodable::decode(d); + } + v } } @@ -563,7 +446,11 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> { impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> { fn decode(d: &mut D) -> Option<T> { - d.read_option(|d, b| if b { Some(Decodable::decode(d)) } else { None }) + match d.read_usize() { + 0 => None, + 1 => Some(Decodable::decode(d)), + _ => panic!("Encountered invalid discriminant while decoding `Option`."), + } } } @@ -582,13 +469,11 @@ impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> { fn decode(d: &mut D) -> Result<T1, T2> { - d.read_enum(|d| { - d.read_enum_variant(&["Ok", "Err"], |d, disr| match disr { - 0 => Ok(d.read_enum_variant_arg(|d| T1::decode(d))), - 1 => Err(d.read_enum_variant_arg(|d| T2::decode(d))), - _ => panic!("Encountered invalid discriminant while decoding `Result`."), - }) - }) + match d.read_usize() { + 0 => Ok(T1::decode(d)), + 1 => Err(T2::decode(d)), + _ => panic!("Encountered invalid discriminant while decoding `Result`."), + } } } @@ -613,24 +498,16 @@ macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( impl<D: Decoder, $($name: Decodable<D>),+> Decodable<D> for ($($name,)+) { - #[allow(non_snake_case)] fn decode(d: &mut D) -> ($($name,)+) { - let len: usize = count!($($name)+); - d.read_tuple(len, |d| { - let ret = ($(d.read_tuple_arg(|d| -> $name { - Decodable::decode(d) - }),)+); - ret - }) + ($({ let element: $name = Decodable::decode(d); element },)+) } } impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) { #[allow(non_snake_case)] fn encode(&self, s: &mut S) -> Result<(), S::Error> { let ($(ref $name,)+) = *self; - let mut n = 0; - $(let $name = $name; n += 1;)+ - s.emit_tuple(n, |s| { + let len: usize = count!($($name)+); + s.emit_tuple(len, |s| { let mut i = 0; $(s.emit_tuple_arg({ i+=1; i-1 }, |s| $name.encode(s))?;)+ Ok(()) |
