1
Fork 0

Auto merge of #94732 - nnethercote:infallible-encoder, r=bjorn3

Make `Encodable` and `Encoder` infallible.

A follow-up to #93066.

r? `@ghost`
This commit is contained in:
bors 2022-06-08 10:24:12 +00:00
commit 1a97162cb2
48 changed files with 706 additions and 856 deletions

View file

@ -31,7 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_serialize::{self, Decoder, Encoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::source_map::{respan, Spanned}; use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
@ -2472,13 +2472,11 @@ rustc_index::newtype_index! {
} }
} }
impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId { impl<S: Encoder> Encodable<S> for AttrId {
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {}
Ok(())
}
} }
impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId { impl<D: Decoder> Decodable<D> for AttrId {
fn decode(_: &mut D) -> AttrId { fn decode(_: &mut D) -> AttrId {
crate::attr::mk_attr_id() crate::attr::mk_attr_id()
} }

View file

@ -121,8 +121,8 @@ impl<D: Decoder, T: 'static + Decodable<D>> Decodable<D> for P<T> {
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
(**self).encode(s) (**self).encode(s);
} }
} }
@ -191,8 +191,8 @@ impl<'a, T> IntoIterator for &'a P<[T]> {
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
Encodable::encode(&**self, s) Encodable::encode(&**self, s);
} }
} }

View file

@ -142,9 +142,9 @@ impl fmt::Debug for LazyTokenStream {
} }
impl<S: Encoder> Encodable<S> for LazyTokenStream { impl<S: Encoder> Encodable<S> for LazyTokenStream {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
// Used by AST json printing. // Used by AST json printing.
Encodable::encode(&self.create_token_stream(), s) Encodable::encode(&self.create_token_stream(), s);
} }
} }

View file

@ -29,7 +29,8 @@ use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_serialize::{opaque, Decodable, Decoder, Encoder}; use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
use rustc_session::cstore::{self, CrateSource}; use rustc_session::cstore::{self, CrateSource};
use rustc_session::utils::NativeLibKind; use rustc_session::utils::NativeLibKind;
@ -203,16 +204,14 @@ const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
impl CodegenResults { impl CodegenResults {
pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> { pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
let mut encoder = opaque::Encoder::new(vec![]); let mut encoder = MemEncoder::new();
encoder.emit_raw_bytes(RLINK_MAGIC).unwrap(); encoder.emit_raw_bytes(RLINK_MAGIC);
// `emit_raw_bytes` is used to make sure that the version representation does not depend on // `emit_raw_bytes` is used to make sure that the version representation does not depend on
// Encoder's inner representation of `u32`. // Encoder's inner representation of `u32`.
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()).unwrap(); encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
encoder.emit_str(RUSTC_VERSION.unwrap()).unwrap(); encoder.emit_str(RUSTC_VERSION.unwrap());
Encodable::encode(codegen_results, &mut encoder);
let mut encoder = rustc_serialize::opaque::Encoder::new(encoder.into_inner()); encoder.finish()
rustc_serialize::Encodable::encode(codegen_results, &mut encoder).unwrap();
encoder.into_inner()
} }
pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> { pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> {
@ -232,7 +231,7 @@ impl CodegenResults {
return Err(".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}".to_string()); return Err(".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}".to_string());
} }
let mut decoder = opaque::Decoder::new(&data[4..], 0); let mut decoder = MemDecoder::new(&data[4..], 0);
let rustc_version = decoder.read_str(); let rustc_version = decoder.read_str();
let current_version = RUSTC_VERSION.unwrap(); let current_version = RUSTC_VERSION.unwrap();
if rustc_version != current_version { if rustc_version != current_version {

View file

@ -1,5 +1,5 @@
use crate::stable_hasher; use crate::stable_hasher;
use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::convert::TryInto; use std::convert::TryInto;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -142,15 +142,14 @@ impl stable_hasher::StableHasherResult for Fingerprint {
impl_stable_hash_via_hash!(Fingerprint); impl_stable_hash_via_hash!(Fingerprint);
impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint { impl<E: Encoder> Encodable<E> for Fingerprint {
#[inline] #[inline]
fn encode(&self, s: &mut E) -> Result<(), E::Error> { fn encode(&self, s: &mut E) {
s.emit_raw_bytes(&self.to_le_bytes())?; s.emit_raw_bytes(&self.to_le_bytes());
Ok(())
} }
} }
impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint { impl<D: Decoder> Decodable<D> for Fingerprint {
#[inline] #[inline]
fn decode(d: &mut D) -> Self { fn decode(d: &mut D) -> Self {
Fingerprint::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) Fingerprint::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap())
@ -185,16 +184,16 @@ impl std::fmt::Display for PackedFingerprint {
} }
} }
impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint { impl<E: Encoder> Encodable<E> for PackedFingerprint {
#[inline] #[inline]
fn encode(&self, s: &mut E) -> Result<(), E::Error> { fn encode(&self, s: &mut E) {
// Copy to avoid taking reference to packed field. // Copy to avoid taking reference to packed field.
let copy = self.0; let copy = self.0;
copy.encode(s) copy.encode(s);
} }
} }
impl<D: rustc_serialize::Decoder> Decodable<D> for PackedFingerprint { impl<D: Decoder> Decodable<D> for PackedFingerprint {
#[inline] #[inline]
fn decode(d: &mut D) -> Self { fn decode(d: &mut D) -> Self {
Self(Fingerprint::decode(d)) Self(Fingerprint::decode(d))

View file

@ -49,8 +49,8 @@ impl fmt::Display for Svh {
} }
impl<S: Encoder> Encodable<S> for Svh { impl<S: Encoder> Encodable<S> for Svh {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_u64(self.as_u64().to_le()) s.emit_u64(self.as_u64().to_le());
} }
} }

View file

@ -30,22 +30,20 @@ const HEADER_FORMAT_VERSION: u16 = 0;
/// the Git commit hash. /// the Git commit hash.
const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult { pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) {
stream.emit_raw_bytes(FILE_MAGIC)?; stream.emit_raw_bytes(FILE_MAGIC);
stream.emit_raw_bytes(&[ stream
(HEADER_FORMAT_VERSION >> 0) as u8, .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
(HEADER_FORMAT_VERSION >> 8) as u8,
])?;
let rustc_version = rustc_version(nightly_build); let rustc_version = rustc_version(nightly_build);
assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize); assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
stream.emit_raw_bytes(&[rustc_version.len() as u8])?; stream.emit_raw_bytes(&[rustc_version.len() as u8]);
stream.emit_raw_bytes(rustc_version.as_bytes()) stream.emit_raw_bytes(rustc_version.as_bytes());
} }
pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F) pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
where where
F: FnOnce(&mut FileEncoder) -> FileEncodeResult, F: FnOnce(FileEncoder) -> FileEncodeResult,
{ {
debug!("save: storing data in {}", path_buf.display()); debug!("save: storing data in {}", path_buf.display());
@ -80,28 +78,21 @@ where
} }
}; };
if let Err(err) = write_file_header(&mut encoder, sess.is_nightly_build()) { write_file_header(&mut encoder, sess.is_nightly_build());
sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
return; match encode(encoder) {
Ok(position) => {
sess.prof.artifact_size(
&name.replace(' ', "_"),
path_buf.file_name().unwrap().to_string_lossy(),
position as u64,
);
debug!("save: data written to disk successfully");
}
Err(err) => {
sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
}
} }
if let Err(err) = encode(&mut encoder) {
sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
return;
}
if let Err(err) = encoder.flush() {
sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
return;
}
sess.prof.artifact_size(
&name.replace(' ', "_"),
path_buf.file_name().unwrap().to_string_lossy(),
encoder.position() as u64,
);
debug!("save: data written to disk successfully");
} }
/// Reads the contents of a file with a file header as defined in this module. /// Reads the contents of a file with a file header as defined in this module.

View file

@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap; use rustc_data_structures::memmap::Mmap;
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::OnDiskCache; use rustc_middle::ty::OnDiskCache;
use rustc_serialize::opaque::Decoder; use rustc_serialize::opaque::MemDecoder;
use rustc_serialize::Decodable; use rustc_serialize::Decodable;
use rustc_session::config::IncrementalStateAssertion; use rustc_session::config::IncrementalStateAssertion;
use rustc_session::Session; use rustc_session::Session;
@ -156,7 +156,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result { if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
// Decode the list of work_products // Decode the list of work_products
let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos); let mut work_product_decoder = MemDecoder::new(&work_products_data[..], start_pos);
let work_products: Vec<SerializedWorkProduct> = let work_products: Vec<SerializedWorkProduct> =
Decodable::decode(&mut work_product_decoder); Decodable::decode(&mut work_product_decoder);
@ -193,7 +193,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
LoadResult::Error { message } => LoadResult::Error { message }, LoadResult::Error { message } => LoadResult::Error { message },
LoadResult::Ok { data: (bytes, start_pos) } => { LoadResult::Ok { data: (bytes, start_pos) } => {
let mut decoder = Decoder::new(&bytes, start_pos); let mut decoder = MemDecoder::new(&bytes, start_pos);
let prev_commandline_args_hash = u64::decode(&mut decoder); let prev_commandline_args_hash = u64::decode(&mut decoder);
if prev_commandline_args_hash != expected_hash { if prev_commandline_args_hash != expected_hash {

View file

@ -3,7 +3,7 @@ use rustc_data_structures::sync::join;
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::Encodable;
use rustc_session::Session; use rustc_session::Session;
use std::fs; use std::fs;
@ -96,8 +96,9 @@ pub fn save_work_product_index(
debug!("save_work_product_index()"); debug!("save_work_product_index()");
dep_graph.assert_ignored(); dep_graph.assert_ignored();
let path = work_products_path(sess); let path = work_products_path(sess);
file_format::save_in(sess, path, "work product index", |e| { file_format::save_in(sess, path, "work product index", |mut e| {
encode_work_product_index(&new_work_products, e) encode_work_product_index(&new_work_products, &mut e);
e.finish()
}); });
// We also need to clean out old work-products, as not all of them are // We also need to clean out old work-products, as not all of them are
@ -123,7 +124,7 @@ pub fn save_work_product_index(
fn encode_work_product_index( fn encode_work_product_index(
work_products: &FxHashMap<WorkProductId, WorkProduct>, work_products: &FxHashMap<WorkProductId, WorkProduct>,
encoder: &mut FileEncoder, encoder: &mut FileEncoder,
) -> FileEncodeResult { ) {
let serialized_products: Vec<_> = work_products let serialized_products: Vec<_> = work_products
.iter() .iter()
.map(|(id, work_product)| SerializedWorkProduct { .map(|(id, work_product)| SerializedWorkProduct {
@ -135,7 +136,7 @@ fn encode_work_product_index(
serialized_products.encode(encoder) serialized_products.encode(encoder)
} }
fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult { fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder)) tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder))
} }
@ -170,24 +171,10 @@ pub fn build_dep_graph(
} }
}; };
if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) { file_format::write_file_header(&mut encoder, sess.is_nightly_build());
sess.err(&format!(
"failed to write dependency graph header to `{}`: {}",
path_buf.display(),
err
));
return None;
}
// First encode the commandline arguments hash // First encode the commandline arguments hash
if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) { sess.opts.dep_tracking_hash(false).encode(&mut encoder);
sess.err(&format!(
"failed to write dependency graph hash `{}`: {}",
path_buf.display(),
err
));
return None;
}
Some(DepGraph::new( Some(DepGraph::new(
&sess.prof, &sess.prof,

View file

@ -60,8 +60,8 @@ pub struct IndexVec<I: Idx, T> {
unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {} unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> { impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
Encodable::encode(&self.raw, s) Encodable::encode(&self.raw, s);
} }
} }

View file

@ -137,8 +137,8 @@ impl Parse for Newtype {
} }
} }
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name { impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
e.emit_u32(self.private) e.emit_u32(self.private);
} }
} }
} }

View file

@ -146,21 +146,17 @@ fn encodable_body(
.map(|binding| { .map(|binding| {
let bind_ident = &binding.binding; let bind_ident = &binding.binding;
let result = quote! { let result = quote! {
match ::rustc_serialize::Encodable::<#encoder_ty>::encode( ::rustc_serialize::Encodable::<#encoder_ty>::encode(
#bind_ident, #bind_ident,
__encoder, __encoder,
) { );
::std::result::Result::Ok(()) => (),
::std::result::Result::Err(__err)
=> return ::std::result::Result::Err(__err),
}
}; };
result result
}) })
.collect::<TokenStream>() .collect::<TokenStream>()
}); });
quote! { quote! {
::std::result::Result::Ok(match *self { #encode_inner }) match *self { #encode_inner }
} }
} }
_ => { _ => {
@ -172,14 +168,10 @@ fn encodable_body(
.map(|binding| { .map(|binding| {
let bind_ident = &binding.binding; let bind_ident = &binding.binding;
let result = quote! { let result = quote! {
match ::rustc_serialize::Encodable::<#encoder_ty>::encode( ::rustc_serialize::Encodable::<#encoder_ty>::encode(
#bind_ident, #bind_ident,
__encoder, __encoder,
) { );
::std::result::Result::Ok(()) => (),
::std::result::Result::Err(__err)
=> return ::std::result::Result::Err(__err),
}
}; };
result result
}) })
@ -190,7 +182,7 @@ fn encodable_body(
::rustc_serialize::Encoder::emit_enum_variant( ::rustc_serialize::Encoder::emit_enum_variant(
__encoder, __encoder,
#variant_idx, #variant_idx,
|__encoder| { ::std::result::Result::Ok({ #encode_fields }) } |__encoder| { #encode_fields }
) )
} }
} else { } else {
@ -223,7 +215,7 @@ fn encodable_body(
fn encode( fn encode(
&self, &self,
__encoder: &mut #encoder_ty, __encoder: &mut #encoder_ty,
) -> ::std::result::Result<(), <#encoder_ty as ::rustc_serialize::Encoder>::Error> { ) {
#lints #lints
#encode_body #encode_body
} }

View file

@ -26,7 +26,8 @@ use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::GeneratorDiagnosticData; use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_serialize::opaque::MemDecoder;
use rustc_serialize::{Decodable, Decoder};
use rustc_session::cstore::{ use rustc_session::cstore::{
CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib,
}; };
@ -154,7 +155,7 @@ struct ImportedSourceFile {
} }
pub(super) struct DecodeContext<'a, 'tcx> { pub(super) struct DecodeContext<'a, 'tcx> {
opaque: opaque::Decoder<'a>, opaque: MemDecoder<'a>,
cdata: Option<CrateMetadataRef<'a>>, cdata: Option<CrateMetadataRef<'a>>,
blob: &'a MetadataBlob, blob: &'a MetadataBlob,
sess: Option<&'tcx Session>, sess: Option<&'tcx Session>,
@ -186,7 +187,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
DecodeContext { DecodeContext {
opaque: opaque::Decoder::new(self.blob(), pos), opaque: MemDecoder::new(self.blob(), pos),
cdata: self.cdata(), cdata: self.cdata(),
blob: self.blob(), blob: self.blob(),
sess: self.sess().or(tcx.map(|tcx| tcx.sess)), sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
@ -418,7 +419,7 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> {
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> R,
{ {
let new_opaque = opaque::Decoder::new(self.opaque.data, pos); let new_opaque = MemDecoder::new(self.opaque.data, pos);
let old_opaque = mem::replace(&mut self.opaque, new_opaque); let old_opaque = mem::replace(&mut self.opaque, new_opaque);
let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
let r = f(self); let r = f(self);

View file

@ -4,7 +4,7 @@ use crate::rmeta::MetadataBlob;
use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::owning_ref::OwningRef;
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
use rustc_middle::parameterized_over_tcx; use rustc_middle::parameterized_over_tcx;
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::def_id::{DefIndex, DefPathHash}; use rustc_span::def_id::{DefIndex, DefPathHash};
pub(crate) enum DefPathHashMapRef<'tcx> { pub(crate) enum DefPathHashMapRef<'tcx> {
@ -29,12 +29,12 @@ impl DefPathHashMapRef<'_> {
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> {
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
match *self { match *self {
DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => { DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => {
let bytes = def_path_hash_map.raw_bytes(); let bytes = def_path_hash_map.raw_bytes();
e.emit_usize(bytes.len())?; e.emit_usize(bytes.len());
e.emit_raw_bytes(bytes) e.emit_raw_bytes(bytes);
} }
DefPathHashMapRef::OwnedFromMetadata(_) => { DefPathHashMapRef::OwnedFromMetadata(_) => {
panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization") panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization")

View file

@ -27,7 +27,8 @@ use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_serialize::opaque::MemEncoder;
use rustc_serialize::{Encodable, Encoder};
use rustc_session::config::CrateType; use rustc_session::config::CrateType;
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind}; use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
@ -43,7 +44,7 @@ use std::num::NonZeroUsize;
use tracing::{debug, trace}; use tracing::{debug, trace};
pub(super) struct EncodeContext<'a, 'tcx> { pub(super) struct EncodeContext<'a, 'tcx> {
opaque: opaque::Encoder, opaque: MemEncoder,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
feat: &'tcx rustc_feature::Features, feat: &'tcx rustc_feature::Features,
@ -86,15 +87,13 @@ macro_rules! empty_proc_macro {
macro_rules! encoder_methods { macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => { ($($name:ident($ty:ty);)*) => {
$(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { $(fn $name(&mut self, value: $ty) {
self.opaque.$name(value) self.opaque.$name(value)
})* })*
} }
} }
impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
type Error = <opaque::Encoder as Encoder>::Error;
encoder_methods! { encoder_methods! {
emit_usize(usize); emit_usize(usize);
emit_u128(u128); emit_u128(u128);
@ -120,57 +119,56 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
} }
impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> { impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
e.emit_lazy_distance(self.position) e.emit_lazy_distance(self.position);
} }
} }
impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> { impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
e.emit_usize(self.num_elems)?; e.emit_usize(self.num_elems);
if self.num_elems == 0 { if self.num_elems > 0 {
return Ok(()); e.emit_lazy_distance(self.position)
} }
e.emit_lazy_distance(self.position)
} }
} }
impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> { impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
e.emit_usize(self.encoded_size)?; e.emit_usize(self.encoded_size);
e.emit_lazy_distance(self.position) e.emit_lazy_distance(self.position);
} }
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
if *self != LOCAL_CRATE && s.is_proc_macro { if *self != LOCAL_CRATE && s.is_proc_macro {
panic!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self); panic!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
} }
s.emit_u32(self.as_u32()) s.emit_u32(self.as_u32());
} }
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
s.emit_u32(self.as_u32()) s.emit_u32(self.as_u32());
} }
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
s.emit_u32(self.as_u32()) s.emit_u32(self.as_u32());
} }
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s) rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s);
} }
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
if self.krate == LOCAL_CRATE { if self.krate == LOCAL_CRATE {
// We will only write details for local expansions. Non-local expansions will fetch // We will only write details for local expansions. Non-local expansions will fetch
// data from the corresponding crate's metadata. // data from the corresponding crate's metadata.
@ -178,13 +176,13 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
// metadata from proc-macro crates. // metadata from proc-macro crates.
s.hygiene_ctxt.schedule_expn_data_for_encoding(*self); s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
} }
self.krate.encode(s)?; self.krate.encode(s);
self.local_id.encode(s) self.local_id.encode(s);
} }
} }
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
let span = self.data(); let span = self.data();
// Don't serialize any `SyntaxContext`s from a proc-macro crate, // Don't serialize any `SyntaxContext`s from a proc-macro crate,
@ -219,9 +217,9 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
// `rustc_span::hygiene::raw_encode_expn_id` to handle // `rustc_span::hygiene::raw_encode_expn_id` to handle
// encoding `ExpnData` for proc-macro crates. // encoding `ExpnData` for proc-macro crates.
if s.is_proc_macro { if s.is_proc_macro {
SyntaxContext::root().encode(s)?; SyntaxContext::root().encode(s);
} else { } else {
span.ctxt.encode(s)?; span.ctxt.encode(s);
} }
if self.is_dummy() { if self.is_dummy() {
@ -289,22 +287,20 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
(TAG_VALID_SPAN_LOCAL, span.lo, span.hi) (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
}; };
tag.encode(s)?; tag.encode(s);
lo.encode(s)?; lo.encode(s);
// Encode length which is usually less than span.hi and profits more // Encode length which is usually less than span.hi and profits more
// from the variable-length integer encoding that we use. // from the variable-length integer encoding that we use.
let len = hi - lo; let len = hi - lo;
len.encode(s)?; len.encode(s);
if tag == TAG_VALID_SPAN_FOREIGN { if tag == TAG_VALID_SPAN_FOREIGN {
// This needs to be two lines to avoid holding the `s.source_file_cache` // This needs to be two lines to avoid holding the `s.source_file_cache`
// while calling `cnum.encode(s)` // while calling `cnum.encode(s)`
let cnum = s.source_file_cache.0.cnum; let cnum = s.source_file_cache.0.cnum;
cnum.encode(s)?; cnum.encode(s);
} }
Ok(())
} }
} }
@ -325,13 +321,10 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
&mut self.predicate_shorthands &mut self.predicate_shorthands
} }
fn encode_alloc_id( fn encode_alloc_id(&mut self, alloc_id: &rustc_middle::mir::interpret::AllocId) {
&mut self,
alloc_id: &rustc_middle::mir::interpret::AllocId,
) -> Result<(), Self::Error> {
let (index, _) = self.interpret_allocs.insert_full(*alloc_id); let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
index.encode(self) index.encode(self);
} }
} }
@ -360,10 +353,7 @@ macro_rules! record_array {
} }
impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn emit_lazy_distance( fn emit_lazy_distance(&mut self, position: NonZeroUsize) {
&mut self,
position: NonZeroUsize,
) -> Result<(), <Self as Encoder>::Error> {
let pos = position.get(); let pos = position.get();
let distance = match self.lazy_state { let distance = match self.lazy_state {
LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
@ -382,7 +372,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} }
}; };
self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap()); self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap());
self.emit_usize(distance) self.emit_usize(distance);
} }
fn lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T> fn lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T>
@ -393,7 +383,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
assert_eq!(self.lazy_state, LazyState::NoNode); assert_eq!(self.lazy_state, LazyState::NoNode);
self.lazy_state = LazyState::NodeStart(pos); self.lazy_state = LazyState::NodeStart(pos);
value.borrow().encode(self).unwrap(); value.borrow().encode(self);
self.lazy_state = LazyState::NoNode; self.lazy_state = LazyState::NoNode;
assert!(pos.get() <= self.position()); assert!(pos.get() <= self.position());
@ -412,7 +402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
assert_eq!(self.lazy_state, LazyState::NoNode); assert_eq!(self.lazy_state, LazyState::NoNode);
self.lazy_state = LazyState::NodeStart(pos); self.lazy_state = LazyState::NodeStart(pos);
let len = values.into_iter().map(|value| value.borrow().encode(self).unwrap()).count(); let len = values.into_iter().map(|value| value.borrow().encode(self)).count();
self.lazy_state = LazyState::NoNode; self.lazy_state = LazyState::NoNode;
assert!(pos.get() <= self.position()); assert!(pos.get() <= self.position());
@ -615,7 +605,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let id = self.interpret_allocs[idx]; let id = self.interpret_allocs[idx];
let pos = self.position() as u32; let pos = self.position() as u32;
interpret_alloc_index.push(pos); interpret_alloc_index.push(pos);
interpret::specialized_encode_alloc_id(self, tcx, id).unwrap(); interpret::specialized_encode_alloc_id(self, tcx, id);
} }
n = new_n; n = new_n;
} }
@ -1640,18 +1630,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let mut expn_data_table: TableBuilder<_, _> = Default::default(); let mut expn_data_table: TableBuilder<_, _> = Default::default();
let mut expn_hash_table: TableBuilder<_, _> = Default::default(); let mut expn_hash_table: TableBuilder<_, _> = Default::default();
let _: Result<(), !> = self.hygiene_ctxt.encode( self.hygiene_ctxt.encode(
&mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table), &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
|(this, syntax_contexts, _, _), index, ctxt_data| { |(this, syntax_contexts, _, _), index, ctxt_data| {
syntax_contexts.set(index, this.lazy(ctxt_data)); syntax_contexts.set(index, this.lazy(ctxt_data));
Ok(())
}, },
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| { |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
if let Some(index) = index.as_local() { if let Some(index) = index.as_local() {
expn_data_table.set(index.as_raw(), this.lazy(expn_data)); expn_data_table.set(index.as_raw(), this.lazy(expn_data));
expn_hash_table.set(index.as_raw(), this.lazy(hash)); expn_hash_table.set(index.as_raw(), this.lazy(hash));
} }
Ok(())
}, },
); );
@ -2194,11 +2182,11 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
} }
fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
let mut encoder = opaque::Encoder::new(vec![]); let mut encoder = MemEncoder::new();
encoder.emit_raw_bytes(METADATA_HEADER).unwrap(); encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything. // Will be filled with the root position after encoding everything.
encoder.emit_raw_bytes(&[0, 0, 0, 0]).unwrap(); encoder.emit_raw_bytes(&[0, 0, 0, 0]);
let source_map_files = tcx.sess.source_map().files(); let source_map_files = tcx.sess.source_map().files();
let source_file_cache = (source_map_files[0].clone(), 0); let source_file_cache = (source_map_files[0].clone(), 0);
@ -2223,13 +2211,13 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
}; };
// Encode the rustc version string in a predictable location. // Encode the rustc version string in a predictable location.
rustc_version().encode(&mut ecx).unwrap(); rustc_version().encode(&mut ecx);
// Encode all the entries and extra information in the crate, // Encode all the entries and extra information in the crate,
// culminating in the `CrateRoot` which points to all of it. // culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root(); let root = ecx.encode_crate_root();
let mut result = ecx.opaque.into_inner(); let mut result = ecx.opaque.finish();
// Encode the root position. // Encode the root position.
let header = METADATA_HEADER.len(); let header = METADATA_HEADER.len();

View file

@ -22,7 +22,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt}; use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
use rustc_serialize::opaque::Encoder; use rustc_serialize::opaque::MemEncoder;
use rustc_session::config::SymbolManglingVersion; use rustc_session::config::SymbolManglingVersion;
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
@ -323,7 +323,7 @@ macro_rules! define_tables {
} }
impl TableBuilders { impl TableBuilders {
fn encode(&self, buf: &mut Encoder) -> LazyTables { fn encode(&self, buf: &mut MemEncoder) -> LazyTables {
LazyTables { LazyTables {
$($name: self.$name.encode(buf)),+ $($name: self.$name.encode(buf)),+
} }

View file

@ -4,8 +4,8 @@ use rustc_data_structures::fingerprint::Fingerprint;
use rustc_hir::def::{CtorKind, CtorOf}; use rustc_hir::def::{CtorKind, CtorOf};
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_middle::ty::ParameterizedOverTcx; use rustc_middle::ty::ParameterizedOverTcx;
use rustc_serialize::opaque::Encoder; use rustc_serialize::opaque::MemEncoder;
use rustc_serialize::Encoder as _; use rustc_serialize::Encoder;
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use std::convert::TryInto; use std::convert::TryInto;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -281,13 +281,13 @@ where
Some(value).write_to_bytes(&mut self.blocks[i]); Some(value).write_to_bytes(&mut self.blocks[i]);
} }
pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> LazyTable<I, T> pub(crate) fn encode<const N: usize>(&self, buf: &mut MemEncoder) -> LazyTable<I, T>
where where
Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>, Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
{ {
let pos = buf.position(); let pos = buf.position();
for block in &self.blocks { for block in &self.blocks {
buf.emit_raw_bytes(block).unwrap(); buf.emit_raw_bytes(block);
} }
let num_bytes = self.blocks.len() * N; let num_bytes = self.blocks.len() * N;
LazyTable::from_position_and_encoded_size( LazyTable::from_position_and_encoded_size(

View file

@ -3,7 +3,7 @@ use rustc_data_structures::graph::{
}; };
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::OnceCell; use rustc_data_structures::sync::OnceCell;
use rustc_serialize as serialize; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
/// Helper type to cache the result of `graph::is_cyclic`. /// Helper type to cache the result of `graph::is_cyclic`.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -36,17 +36,17 @@ impl GraphIsCyclicCache {
} }
} }
impl<S: serialize::Encoder> serialize::Encodable<S> for GraphIsCyclicCache { impl<S: Encoder> Encodable<S> for GraphIsCyclicCache {
#[inline] #[inline]
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
serialize::Encodable::encode(&(), s) Encodable::encode(&(), s);
} }
} }
impl<D: serialize::Decoder> serialize::Decodable<D> for GraphIsCyclicCache { impl<D: Decoder> Decodable<D> for GraphIsCyclicCache {
#[inline] #[inline]
fn decode(d: &mut D) -> Self { fn decode(d: &mut D) -> Self {
let () = serialize::Decodable::decode(d); let () = Decodable::decode(d);
Self::new() Self::new()
} }
} }

View file

@ -207,27 +207,26 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>(
encoder: &mut E, encoder: &mut E,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
alloc_id: AllocId, alloc_id: AllocId,
) -> Result<(), E::Error> { ) {
match tcx.global_alloc(alloc_id) { match tcx.global_alloc(alloc_id) {
GlobalAlloc::Memory(alloc) => { GlobalAlloc::Memory(alloc) => {
trace!("encoding {:?} with {:#?}", alloc_id, alloc); trace!("encoding {:?} with {:#?}", alloc_id, alloc);
AllocDiscriminant::Alloc.encode(encoder)?; AllocDiscriminant::Alloc.encode(encoder);
alloc.encode(encoder)?; alloc.encode(encoder);
} }
GlobalAlloc::Function(fn_instance) => { GlobalAlloc::Function(fn_instance) => {
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance); trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
AllocDiscriminant::Fn.encode(encoder)?; AllocDiscriminant::Fn.encode(encoder);
fn_instance.encode(encoder)?; fn_instance.encode(encoder);
} }
GlobalAlloc::Static(did) => { GlobalAlloc::Static(did) => {
assert!(!tcx.is_thread_local_static(did)); assert!(!tcx.is_thread_local_static(did));
// References to statics doesn't need to know about their allocations, // References to statics doesn't need to know about their allocations,
// just about its `DefId`. // just about its `DefId`.
AllocDiscriminant::Static.encode(encoder)?; AllocDiscriminant::Static.encode(encoder);
did.encode(encoder)?; did.encode(encoder);
} }
} }
Ok(())
} }
// Used to avoid infinite recursion when decoding cyclic allocations. // Used to avoid infinite recursion when decoding cyclic allocations.

View file

@ -672,16 +672,16 @@ const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> { impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
#[inline] #[inline]
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
if E::CLEAR_CROSS_CRATE { if E::CLEAR_CROSS_CRATE {
return Ok(()); return;
} }
match *self { match *self {
ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e), ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
ClearCrossCrate::Set(ref val) => { ClearCrossCrate::Set(ref val) => {
TAG_CLEAR_CROSS_CRATE_SET.encode(e)?; TAG_CLEAR_CROSS_CRATE_SET.encode(e);
val.encode(e) val.encode(e);
} }
} }
} }

View file

@ -3,7 +3,7 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::OnceCell; use rustc_data_structures::sync::OnceCell;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_serialize as serialize; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::mir::{BasicBlock, BasicBlockData}; use crate::mir::{BasicBlock, BasicBlockData};
@ -54,14 +54,12 @@ impl PredecessorCache {
} }
} }
impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache { impl<S: Encoder> Encodable<S> for PredecessorCache {
#[inline] #[inline]
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {}
Ok(())
}
} }
impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache { impl<D: Decoder> Decodable<D> for PredecessorCache {
#[inline] #[inline]
fn decode(_: &mut D) -> Self { fn decode(_: &mut D) -> Self {
Self::new() Self::new()

View file

@ -5,7 +5,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::stable_map::FxHashMap;
use rustc_data_structures::sync::OnceCell; use rustc_data_structures::sync::OnceCell;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_serialize as serialize; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind}; use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
@ -54,14 +54,12 @@ impl SwitchSourceCache {
} }
} }
impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache { impl<S: Encoder> Encodable<S> for SwitchSourceCache {
#[inline] #[inline]
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {}
Ok(())
}
} }
impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache { impl<D: Decoder> Decodable<D> for SwitchSourceCache {
#[inline] #[inline]
fn decode(_: &mut D) -> Self { fn decode(_: &mut D) -> Self {
Self::new() Self::new()

View file

@ -1,7 +1,7 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::OnceCell; use rustc_data_structures::sync::OnceCell;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_serialize as serialize; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use super::*; use super::*;
@ -365,14 +365,12 @@ impl PostorderCache {
} }
} }
impl<S: serialize::Encoder> serialize::Encodable<S> for PostorderCache { impl<S: Encoder> Encodable<S> for PostorderCache {
#[inline] #[inline]
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {}
Ok(())
}
} }
impl<D: serialize::Decoder> serialize::Decodable<D> for PostorderCache { impl<D: Decoder> Decodable<D> for PostorderCache {
#[inline] #[inline]
fn decode(_: &mut D) -> Self { fn decode(_: &mut D) -> Self {
Self::new() Self::new()

View file

@ -69,11 +69,7 @@ pub trait RefDecodable<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> {
} }
/// Encode the given value or a previously cached shorthand. /// Encode the given value or a previously cached shorthand.
pub fn encode_with_shorthand<'tcx, E, T, M>( pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
encoder: &mut E,
value: &T,
cache: M,
) -> Result<(), E::Error>
where where
E: TyEncoder<I = TyCtxt<'tcx>>, E: TyEncoder<I = TyCtxt<'tcx>>,
M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>, M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
@ -83,13 +79,14 @@ where
{ {
let existing_shorthand = cache(encoder).get(value).copied(); let existing_shorthand = cache(encoder).get(value).copied();
if let Some(shorthand) = existing_shorthand { if let Some(shorthand) = existing_shorthand {
return encoder.emit_usize(shorthand); encoder.emit_usize(shorthand);
return;
} }
let variant = value.variant(); let variant = value.variant();
let start = encoder.position(); let start = encoder.position();
variant.encode(encoder)?; variant.encode(encoder);
let len = encoder.position() - start; let len = encoder.position() - start;
// The shorthand encoding uses the same usize as the // The shorthand encoding uses the same usize as the
@ -108,57 +105,55 @@ where
if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) { if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
cache(encoder).insert(*value, shorthand); cache(encoder).insert(*value, shorthand);
} }
Ok(())
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Ty<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Ty<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
encode_with_shorthand(e, self, TyEncoder::type_shorthands) encode_with_shorthand(e, self, TyEncoder::type_shorthands);
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E>
for ty::Binder<'tcx, ty::PredicateKind<'tcx>> for ty::Binder<'tcx, ty::PredicateKind<'tcx>>
{ {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.bound_vars().encode(e)?; self.bound_vars().encode(e);
encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands) encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands);
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.kind().encode(e) self.kind().encode(e);
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.kind().encode(e) self.kind().encode(e);
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Const<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Const<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.0.0.encode(e) self.0.0.encode(e);
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.inner().encode(e) self.inner().encode(e)
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AdtDef<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AdtDef<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.0.0.encode(e) self.0.0.encode(e)
} }
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
e.encode_alloc_id(self) e.encode_alloc_id(self)
} }
} }
@ -508,9 +503,9 @@ macro_rules! impl_binder_encode_decode {
($($t:ty),+ $(,)?) => { ($($t:ty),+ $(,)?) => {
$( $(
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Binder<'tcx, $t> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Binder<'tcx, $t> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.bound_vars().encode(e)?; self.bound_vars().encode(e);
self.as_ref().skip_binder().encode(e) self.as_ref().skip_binder().encode(e);
} }
} }
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Binder<'tcx, $t> { impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Binder<'tcx, $t> {

View file

@ -140,9 +140,9 @@ impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
} }
impl<S: Encoder> Encodable<S> for ScalarInt { impl<S: Encoder> Encodable<S> for ScalarInt {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_u128(self.data)?; s.emit_u128(self.data);
s.emit_u8(self.size) s.emit_u8(self.size);
} }
} }

View file

@ -87,7 +87,7 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>); fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult; fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult;
} }
#[allow(rustc::usage_of_ty_tykind)] #[allow(rustc::usage_of_ty_tykind)]
@ -1466,8 +1466,8 @@ impl<'tcx> TyCtxt<'tcx> {
) )
} }
pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult { pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
self.on_disk_cache.as_ref().map_or(Ok(()), |c| c.serialize(self, encoder)) self.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
} }
/// If `true`, we should use lazy normalization for constants, otherwise /// If `true`, we should use lazy normalization for constants, otherwise

View file

@ -117,8 +117,8 @@ impl<T: fmt::Debug> fmt::Debug for List<T> {
impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
#[inline] #[inline]
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
(**self).encode(s) (**self).encode(s);
} }
} }

View file

@ -216,7 +216,7 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
} }
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for GenericArg<'tcx> { impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for GenericArg<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.unpack().encode(e) self.unpack().encode(e)
} }
} }

View file

@ -2,6 +2,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)] #![feature(once_cell)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View file

@ -15,7 +15,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::dep_graph::DepContext; use rustc_query_system::dep_graph::DepContext;
use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects}; use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects};
use rustc_serialize::{ use rustc_serialize::{
opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}, opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
Decodable, Decoder, Encodable, Encoder, Decodable, Decoder, Encodable, Encoder,
}; };
use rustc_session::Session; use rustc_session::Session;
@ -25,6 +25,7 @@ use rustc_span::hygiene::{
use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::source_map::{SourceMap, StableSourceFileId};
use rustc_span::CachingSourceMapView; use rustc_span::CachingSourceMapView;
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span}; use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
use std::io;
use std::mem; use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
@ -158,7 +159,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
// Wrap in a scope so we can borrow `data`. // Wrap in a scope so we can borrow `data`.
let footer: Footer = { let footer: Footer = {
let mut decoder = opaque::Decoder::new(&data, start_pos); let mut decoder = MemDecoder::new(&data, start_pos);
// Decode the *position* of the footer, which can be found in the // Decode the *position* of the footer, which can be found in the
// last 8 bytes of the file. // last 8 bytes of the file.
@ -221,7 +222,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
*self.serialized_data.write() = None; *self.serialized_data.write() = None;
} }
fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult { fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult {
// Serializing the `DepGraph` should not modify it. // Serializing the `DepGraph` should not modify it.
tcx.dep_graph.with_ignore(|| { tcx.dep_graph.with_ignore(|| {
// Allocate `SourceFileIndex`es. // Allocate `SourceFileIndex`es.
@ -259,27 +260,25 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
// Encode query results. // Encode query results.
let mut query_result_index = EncodedDepNodeIndex::new(); let mut query_result_index = EncodedDepNodeIndex::new();
tcx.sess.time("encode_query_results", || -> FileEncodeResult { tcx.sess.time("encode_query_results", || {
let enc = &mut encoder; let enc = &mut encoder;
let qri = &mut query_result_index; let qri = &mut query_result_index;
QueryCtxt::from_tcx(tcx).encode_query_results(enc, qri) QueryCtxt::from_tcx(tcx).encode_query_results(enc, qri);
})?; });
// Encode side effects. // Encode side effects.
let side_effects_index: EncodedDepNodeIndex = self let side_effects_index: EncodedDepNodeIndex = self
.current_side_effects .current_side_effects
.borrow() .borrow()
.iter() .iter()
.map( .map(|(dep_node_index, side_effects)| {
|(dep_node_index, side_effects)| -> Result<_, <FileEncoder as Encoder>::Error> { let pos = AbsoluteBytePos::new(encoder.position());
let pos = AbsoluteBytePos::new(encoder.position()); let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); encoder.encode_tagged(dep_node_index, side_effects);
encoder.encode_tagged(dep_node_index, side_effects)?;
Ok((dep_node_index, pos)) (dep_node_index, pos)
}, })
) .collect();
.collect::<Result<_, _>>()?;
let interpret_alloc_index = { let interpret_alloc_index = {
let mut interpret_alloc_index = Vec::new(); let mut interpret_alloc_index = Vec::new();
@ -296,7 +295,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
let id = encoder.interpret_allocs[idx]; let id = encoder.interpret_allocs[idx];
let pos = encoder.position() as u32; let pos = encoder.position() as u32;
interpret_alloc_index.push(pos); interpret_alloc_index.push(pos);
interpret::specialized_encode_alloc_id(&mut encoder, tcx, id)?; interpret::specialized_encode_alloc_id(&mut encoder, tcx, id);
} }
n = new_n; n = new_n;
} }
@ -312,23 +311,21 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
hygiene_encode_context.encode( hygiene_encode_context.encode(
&mut encoder, &mut encoder,
|encoder, index, ctxt_data| -> FileEncodeResult { |encoder, index, ctxt_data| {
let pos = AbsoluteBytePos::new(encoder.position()); let pos = AbsoluteBytePos::new(encoder.position());
encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data)?; encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data);
syntax_contexts.insert(index, pos); syntax_contexts.insert(index, pos);
Ok(())
}, },
|encoder, expn_id, data, hash| -> FileEncodeResult { |encoder, expn_id, data, hash| {
if expn_id.krate == LOCAL_CRATE { if expn_id.krate == LOCAL_CRATE {
let pos = AbsoluteBytePos::new(encoder.position()); let pos = AbsoluteBytePos::new(encoder.position());
encoder.encode_tagged(TAG_EXPN_DATA, data)?; encoder.encode_tagged(TAG_EXPN_DATA, data);
expn_data.insert(hash, pos); expn_data.insert(hash, pos);
} else { } else {
foreign_expn_data.insert(hash, expn_id.local_id.as_u32()); foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
} }
Ok(())
}, },
)?; );
// `Encode the file footer. // `Encode the file footer.
let footer_pos = encoder.position() as u64; let footer_pos = encoder.position() as u64;
@ -343,16 +340,16 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
expn_data, expn_data,
foreign_expn_data, foreign_expn_data,
}, },
)?; );
// Encode the position of the footer as the last 8 bytes of the // Encode the position of the footer as the last 8 bytes of the
// file so we know where to look for it. // file so we know where to look for it.
IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?; IntEncodedWithFixedSize(footer_pos).encode(&mut encoder.encoder);
// DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
// of the footer must be the last thing in the data stream. // of the footer must be the last thing in the data stream.
Ok(()) encoder.finish()
}) })
} }
} }
@ -441,7 +438,7 @@ impl<'sess> OnDiskCache<'sess> {
let serialized_data = self.serialized_data.read(); let serialized_data = self.serialized_data.read();
let mut decoder = CacheDecoder { let mut decoder = CacheDecoder {
tcx, tcx,
opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()), opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
source_map: self.source_map, source_map: self.source_map,
file_index_to_file: &self.file_index_to_file, file_index_to_file: &self.file_index_to_file,
file_index_to_stable_id: &self.file_index_to_stable_id, file_index_to_stable_id: &self.file_index_to_stable_id,
@ -462,7 +459,7 @@ impl<'sess> OnDiskCache<'sess> {
/// will also handle things that contain `Ty` instances. /// will also handle things that contain `Ty` instances.
pub struct CacheDecoder<'a, 'tcx> { pub struct CacheDecoder<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
opaque: opaque::Decoder<'a>, opaque: MemDecoder<'a>,
source_map: &'a SourceMap, source_map: &'a SourceMap,
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>, file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>, file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
@ -514,7 +511,7 @@ trait DecoderWithPosition: Decoder {
fn position(&self) -> usize; fn position(&self) -> usize;
} }
impl<'a> DecoderWithPosition for opaque::Decoder<'a> { impl<'a> DecoderWithPosition for MemDecoder<'a> {
fn position(&self) -> usize { fn position(&self) -> usize {
self.position() self.position()
} }
@ -590,7 +587,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
{ {
debug_assert!(pos < self.opaque.data.len()); debug_assert!(pos < self.opaque.data.len());
let new_opaque = opaque::Decoder::new(self.opaque.data, pos); let new_opaque = MemDecoder::new(self.opaque.data, pos);
let old_opaque = mem::replace(&mut self.opaque, new_opaque); let old_opaque = mem::replace(&mut self.opaque, new_opaque);
let r = f(self); let r = f(self);
self.opaque = old_opaque; self.opaque = old_opaque;
@ -811,21 +808,10 @@ impl_ref_decoder! {<'tcx>
//- ENCODING ------------------------------------------------------------------- //- ENCODING -------------------------------------------------------------------
pub trait OpaqueEncoder: Encoder {
fn position(&self) -> usize;
}
impl OpaqueEncoder for FileEncoder {
#[inline]
fn position(&self) -> usize {
FileEncoder::position(self)
}
}
/// An encoder that can write to the incremental compilation cache. /// An encoder that can write to the incremental compilation cache.
pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { pub struct CacheEncoder<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
encoder: &'a mut E, encoder: FileEncoder,
type_shorthands: FxHashMap<Ty<'tcx>, usize>, type_shorthands: FxHashMap<Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>, predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
interpret_allocs: FxIndexSet<interpret::AllocId>, interpret_allocs: FxIndexSet<interpret::AllocId>,
@ -834,10 +820,7 @@ pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
hygiene_context: &'a HygieneEncodeContext, hygiene_context: &'a HygieneEncodeContext,
} }
impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E> impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
where
E: 'a + OpaqueEncoder,
{
fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex { fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
self.file_to_file_index[&(&*source_file as *const SourceFile)] self.file_to_file_index[&(&*source_file as *const SourceFile)]
} }
@ -847,48 +830,39 @@ where
/// encode the specified tag, then the given value, then the number of /// encode the specified tag, then the given value, then the number of
/// bytes taken up by tag and value. On decoding, we can then verify that /// bytes taken up by tag and value. On decoding, we can then verify that
/// we get the expected tag and read the expected number of bytes. /// we get the expected tag and read the expected number of bytes.
fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>( fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
&mut self,
tag: T,
value: &V,
) -> Result<(), E::Error> {
let start_pos = self.position(); let start_pos = self.position();
tag.encode(self)?; tag.encode(self);
value.encode(self)?; value.encode(self);
let end_pos = self.position(); let end_pos = self.position();
((end_pos - start_pos) as u64).encode(self) ((end_pos - start_pos) as u64).encode(self);
}
fn finish(self) -> Result<usize, io::Error> {
self.encoder.finish()
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for SyntaxContext {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: 'a + OpaqueEncoder, rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s);
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for ExpnId {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: 'a + OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
s.hygiene_context.schedule_expn_data_for_encoding(*self); s.hygiene_context.schedule_expn_data_for_encoding(*self);
self.expn_hash().encode(s) self.expn_hash().encode(s);
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Span {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: 'a + OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
let span_data = self.data_untracked(); let span_data = self.data_untracked();
span_data.ctxt.encode(s)?; span_data.ctxt.encode(s);
span_data.parent.encode(s)?; span_data.parent.encode(s);
if span_data.is_dummy() { if span_data.is_dummy() {
return TAG_PARTIAL_SPAN.encode(s); return TAG_PARTIAL_SPAN.encode(s);
@ -897,10 +871,10 @@ where
if let Some(parent) = span_data.parent { if let Some(parent) = span_data.parent {
let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked(); let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked();
if enclosing.contains(span_data) { if enclosing.contains(span_data) {
TAG_RELATIVE_SPAN.encode(s)?; TAG_RELATIVE_SPAN.encode(s);
(span_data.lo - enclosing.lo).to_u32().encode(s)?; (span_data.lo - enclosing.lo).to_u32().encode(s);
(span_data.hi - enclosing.lo).to_u32().encode(s)?; (span_data.hi - enclosing.lo).to_u32().encode(s);
return Ok(()); return;
} }
} }
@ -920,18 +894,15 @@ where
let source_file_index = s.source_file_index(file_lo); let source_file_index = s.source_file_index(file_lo);
TAG_FULL_SPAN.encode(s)?; TAG_FULL_SPAN.encode(s);
source_file_index.encode(s)?; source_file_index.encode(s);
line_lo.encode(s)?; line_lo.encode(s);
col_lo.encode(s)?; col_lo.encode(s);
len.encode(s) len.encode(s);
} }
} }
impl<'a, 'tcx, E> TyEncoder for CacheEncoder<'a, 'tcx, E> impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> {
where
E: 'a + OpaqueEncoder,
{
type I = TyCtxt<'tcx>; type I = TyCtxt<'tcx>;
const CLEAR_CROSS_CRATE: bool = false; const CLEAR_CROSS_CRATE: bool = false;
@ -944,36 +915,27 @@ where
fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> { fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
&mut self.predicate_shorthands &mut self.predicate_shorthands
} }
fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) {
let (index, _) = self.interpret_allocs.insert_full(*alloc_id); let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
index.encode(self) index.encode(self);
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for CrateNum impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for CrateNum {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: 'a + OpaqueEncoder, s.tcx.stable_crate_id(*self).encode(s);
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
s.tcx.stable_crate_id(*self).encode(s)
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefId {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: 'a + OpaqueEncoder, s.tcx.def_path_hash(*self).encode(s);
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
s.tcx.def_path_hash(*self).encode(s)
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefIndex {
where fn encode(&self, _: &mut CacheEncoder<'a, 'tcx>) {
E: 'a + OpaqueEncoder,
{
fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
bug!("encoding `DefIndex` without context"); bug!("encoding `DefIndex` without context");
} }
} }
@ -981,18 +943,13 @@ where
macro_rules! encoder_methods { macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => { ($($name:ident($ty:ty);)*) => {
#[inline] #[inline]
$(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { $(fn $name(&mut self, value: $ty) {
self.encoder.$name(value) self.encoder.$name(value)
})* })*
} }
} }
impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E> impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> {
where
E: 'a + OpaqueEncoder,
{
type Error = E::Error;
encoder_methods! { encoder_methods! {
emit_usize(usize); emit_usize(usize);
emit_u128(u128); emit_u128(u128);
@ -1021,21 +978,20 @@ where
// is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`. // is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder` // Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
// and the encoding traits currently work. // and the encoding traits currently work.
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] { impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for [u8] {
fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResult { fn encode(&self, e: &mut CacheEncoder<'a, 'tcx>) {
self.encode(e.encoder) self.encode(&mut e.encoder);
} }
} }
pub fn encode_query_results<'a, 'tcx, CTX, Q>( pub fn encode_query_results<'a, 'tcx, CTX, Q>(
tcx: CTX, tcx: CTX,
encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, encoder: &mut CacheEncoder<'a, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex, query_result_index: &mut EncodedDepNodeIndex,
) -> FileEncodeResult ) where
where
CTX: QueryContext + 'tcx, CTX: QueryContext + 'tcx,
Q: super::QueryDescription<CTX>, Q: super::QueryDescription<CTX>,
Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>, Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
{ {
let _timer = tcx let _timer = tcx
.dep_context() .dep_context()
@ -1044,11 +1000,7 @@ where
assert!(Q::query_state(tcx).all_inactive()); assert!(Q::query_state(tcx).all_inactive());
let cache = Q::query_cache(tcx); let cache = Q::query_cache(tcx);
let mut res = Ok(());
cache.iter(&mut |key, value, dep_node| { cache.iter(&mut |key, value, dep_node| {
if res.is_err() {
return;
}
if Q::cache_on_disk(*tcx.dep_context(), &key) { if Q::cache_on_disk(*tcx.dep_context(), &key) {
let dep_node = SerializedDepNodeIndex::new(dep_node.index()); let dep_node = SerializedDepNodeIndex::new(dep_node.index());
@ -1057,14 +1009,7 @@ where
// Encode the type check tables with the `SerializedDepNodeIndex` // Encode the type check tables with the `SerializedDepNodeIndex`
// as tag. // as tag.
match encoder.encode_tagged(dep_node, value) { encoder.encode_tagged(dep_node, value);
Ok(()) => {}
Err(e) => {
res = Err(e);
}
}
} }
}); });
res
} }

View file

@ -12,7 +12,6 @@ use rustc_query_system::query::{QueryContext, QueryJobId, QueryMap, QuerySideEff
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{Diagnostic, Handler}; use rustc_errors::{Diagnostic, Handler};
use rustc_serialize::opaque;
use std::any::Any; use std::any::Any;
use std::num::NonZeroU64; use std::num::NonZeroU64;
@ -140,9 +139,9 @@ impl<'tcx> QueryCtxt<'tcx> {
pub(super) fn encode_query_results( pub(super) fn encode_query_results(
self, self,
encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx, opaque::FileEncoder>, encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,
query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
) -> opaque::FileEncodeResult { ) {
macro_rules! encode_queries { macro_rules! encode_queries {
($($query:ident,)*) => { ($($query:ident,)*) => {
$( $(
@ -150,14 +149,12 @@ impl<'tcx> QueryCtxt<'tcx> {
self, self,
encoder, encoder,
query_result_index query_result_index
)?; );
)* )*
} }
} }
rustc_cached_queries!(encode_queries!); rustc_cached_queries!(encode_queries!);
Ok(())
} }
pub fn try_print_query_stack( pub fn try_print_query_stack(

View file

@ -842,7 +842,7 @@ impl<K: DepKind> DepGraph<K> {
if let Some(data) = &self.data { if let Some(data) = &self.data {
data.current.encoder.steal().finish(profiler) data.current.encoder.steal().finish(profiler)
} else { } else {
Ok(()) Ok(0)
} }
} }

View file

@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable}; use rustc_serialize::{Decodable, Decoder, Encodable};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::convert::TryInto; use std::convert::TryInto;
@ -96,11 +96,11 @@ impl<K: DepKind> SerializedDepGraph<K> {
} }
} }
impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>> impl<'a, K: DepKind + Decodable<MemDecoder<'a>>> Decodable<MemDecoder<'a>>
for SerializedDepGraph<K> for SerializedDepGraph<K>
{ {
#[instrument(level = "debug", skip(d))] #[instrument(level = "debug", skip(d))]
fn decode(d: &mut opaque::Decoder<'a>) -> SerializedDepGraph<K> { fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph<K> {
let start_position = d.position(); let start_position = d.position();
// The last 16 bytes are the node count and edge count. // The last 16 bytes are the node count and edge count.
@ -166,7 +166,6 @@ struct EncoderState<K: DepKind> {
encoder: FileEncoder, encoder: FileEncoder,
total_node_count: usize, total_node_count: usize,
total_edge_count: usize, total_edge_count: usize,
result: FileEncodeResult,
stats: Option<FxHashMap<K, Stat<K>>>, stats: Option<FxHashMap<K, Stat<K>>>,
} }
@ -176,7 +175,6 @@ impl<K: DepKind> EncoderState<K> {
encoder, encoder,
total_edge_count: 0, total_edge_count: 0,
total_node_count: 0, total_node_count: 0,
result: Ok(()),
stats: record_stats.then(FxHashMap::default), stats: record_stats.then(FxHashMap::default),
} }
} }
@ -208,29 +206,28 @@ impl<K: DepKind> EncoderState<K> {
} }
let encoder = &mut self.encoder; let encoder = &mut self.encoder;
if self.result.is_ok() { node.encode(encoder);
self.result = node.encode(encoder);
}
index index
} }
fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult { fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
let Self { mut encoder, total_node_count, total_edge_count, result, stats: _ } = self; let Self { mut encoder, total_node_count, total_edge_count, stats: _ } = self;
let () = result?;
let node_count = total_node_count.try_into().unwrap(); let node_count = total_node_count.try_into().unwrap();
let edge_count = total_edge_count.try_into().unwrap(); let edge_count = total_edge_count.try_into().unwrap();
debug!(?node_count, ?edge_count); debug!(?node_count, ?edge_count);
debug!("position: {:?}", encoder.position()); debug!("position: {:?}", encoder.position());
IntEncodedWithFixedSize(node_count).encode(&mut encoder)?; IntEncodedWithFixedSize(node_count).encode(&mut encoder);
IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?; IntEncodedWithFixedSize(edge_count).encode(&mut encoder);
debug!("position: {:?}", encoder.position()); debug!("position: {:?}", encoder.position());
// Drop the encoder so that nothing is written after the counts. // Drop the encoder so that nothing is written after the counts.
let result = encoder.flush(); let result = encoder.finish();
// FIXME(rylev): we hardcode the dep graph file name so we don't need a dependency on if let Ok(position) = result {
// rustc_incremental just for that. // FIXME(rylev): we hardcode the dep graph file name so we
profiler.artifact_size("dep_graph", "dep-graph.bin", encoder.position() as u64); // don't need a dependency on rustc_incremental just for that.
profiler.artifact_size("dep_graph", "dep-graph.bin", position as u64);
}
result result
} }
} }

View file

@ -10,9 +10,9 @@ use std::sync::Arc;
use smallvec::{Array, SmallVec}; use smallvec::{Array, SmallVec};
impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> { 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; 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> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for LinkedList<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_usize(self.len())?; s.emit_usize(self.len());
for e in self.iter() { 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> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for VecDeque<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_usize(self.len())?; s.emit_usize(self.len());
for e in self.iter() { for e in self.iter() {
e.encode(s)?; e.encode(s);
} }
Ok(())
} }
} }
@ -62,13 +60,12 @@ where
K: Encodable<S> + PartialEq + Ord, K: Encodable<S> + PartialEq + Ord,
V: Encodable<S>, V: Encodable<S>,
{ {
fn encode(&self, e: &mut S) -> Result<(), S::Error> { fn encode(&self, e: &mut S) {
e.emit_usize(self.len())?; e.emit_usize(self.len());
for (key, val) in self.iter() { for (key, val) in self.iter() {
key.encode(e)?; key.encode(e);
val.encode(e)?; val.encode(e);
} }
Ok(())
} }
} }
@ -93,12 +90,11 @@ impl<S: Encoder, T> Encodable<S> for BTreeSet<T>
where where
T: Encodable<S> + PartialEq + Ord, T: Encodable<S> + PartialEq + Ord,
{ {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_usize(self.len())?; s.emit_usize(self.len());
for e in self.iter() { for e in self.iter() {
e.encode(s)?; e.encode(s);
} }
Ok(())
} }
} }
@ -122,13 +118,12 @@ where
V: Encodable<E>, V: Encodable<E>,
S: BuildHasher, S: BuildHasher,
{ {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
e.emit_usize(self.len())?; e.emit_usize(self.len());
for (key, val) in self.iter() { for (key, val) in self.iter() {
key.encode(e)?; key.encode(e);
val.encode(e)?; val.encode(e);
} }
Ok(())
} }
} }
@ -156,12 +151,11 @@ where
T: Encodable<E> + Eq, T: Encodable<E> + Eq,
S: BuildHasher, S: BuildHasher,
{ {
fn encode(&self, s: &mut E) -> Result<(), E::Error> { fn encode(&self, s: &mut E) {
s.emit_usize(self.len())?; s.emit_usize(self.len());
for e in self.iter() { for e in self.iter() {
e.encode(s)?; e.encode(s);
} }
Ok(())
} }
} }
@ -187,13 +181,12 @@ where
V: Encodable<E>, V: Encodable<E>,
S: BuildHasher, S: BuildHasher,
{ {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
e.emit_usize(self.len())?; e.emit_usize(self.len());
for (key, val) in self.iter() { for (key, val) in self.iter() {
key.encode(e)?; key.encode(e);
val.encode(e)?; val.encode(e);
} }
Ok(())
} }
} }
@ -221,12 +214,11 @@ where
T: Encodable<E> + Hash + Eq, T: Encodable<E> + Hash + Eq,
S: BuildHasher, S: BuildHasher,
{ {
fn encode(&self, s: &mut E) -> Result<(), E::Error> { fn encode(&self, s: &mut E) {
s.emit_usize(self.len())?; s.emit_usize(self.len());
for e in self.iter() { 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]> { 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; 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]> { 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; let slice: &[T] = self;
slice.encode(s) slice.encode(s);
} }
} }

View file

@ -1,5 +1,5 @@
use crate::leb128::{self, max_leb128_len}; use crate::leb128::{self, max_leb128_len};
use crate::serialize::{self, Decoder as _, Encoder as _}; use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::File; use std::fs::File;
use std::io::{self, Write}; use std::io::{self, Write};
@ -11,25 +11,23 @@ use std::ptr;
// Encoder // Encoder
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub type EncodeResult = Result<(), !>; pub struct MemEncoder {
pub struct Encoder {
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl Encoder { impl MemEncoder {
pub fn new(data: Vec<u8>) -> Encoder { pub fn new() -> MemEncoder {
Encoder { data } MemEncoder { data: vec![] }
}
pub fn into_inner(self) -> Vec<u8> {
self.data
} }
#[inline] #[inline]
pub fn position(&self) -> usize { pub fn position(&self) -> usize {
self.data.len() self.data.len()
} }
pub fn finish(self) -> Vec<u8> {
self.data
}
} }
macro_rules! write_leb128 { macro_rules! write_leb128 {
@ -49,8 +47,6 @@ macro_rules! write_leb128 {
let encoded = leb128::$fun(buf, $value); let encoded = leb128::$fun(buf, $value);
$enc.data.set_len(old_len + encoded.len()); $enc.data.set_len(old_len + encoded.len());
} }
Ok(())
}}; }};
} }
@ -61,114 +57,108 @@ macro_rules! write_leb128 {
/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout /// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
const STR_SENTINEL: u8 = 0xC1; const STR_SENTINEL: u8 = 0xC1;
impl serialize::Encoder for Encoder { impl Encoder for MemEncoder {
type Error = !;
#[inline] #[inline]
fn emit_usize(&mut self, v: usize) -> EncodeResult { fn emit_usize(&mut self, v: usize) {
write_leb128!(self, v, usize, write_usize_leb128) write_leb128!(self, v, usize, write_usize_leb128)
} }
#[inline] #[inline]
fn emit_u128(&mut self, v: u128) -> EncodeResult { fn emit_u128(&mut self, v: u128) {
write_leb128!(self, v, u128, write_u128_leb128) write_leb128!(self, v, u128, write_u128_leb128);
} }
#[inline] #[inline]
fn emit_u64(&mut self, v: u64) -> EncodeResult { fn emit_u64(&mut self, v: u64) {
write_leb128!(self, v, u64, write_u64_leb128) write_leb128!(self, v, u64, write_u64_leb128);
} }
#[inline] #[inline]
fn emit_u32(&mut self, v: u32) -> EncodeResult { fn emit_u32(&mut self, v: u32) {
write_leb128!(self, v, u32, write_u32_leb128) write_leb128!(self, v, u32, write_u32_leb128);
} }
#[inline] #[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()); self.data.extend_from_slice(&v.to_le_bytes());
Ok(())
} }
#[inline] #[inline]
fn emit_u8(&mut self, v: u8) -> EncodeResult { fn emit_u8(&mut self, v: u8) {
self.data.push(v); self.data.push(v);
Ok(())
} }
#[inline] #[inline]
fn emit_isize(&mut self, v: isize) -> EncodeResult { fn emit_isize(&mut self, v: isize) {
write_leb128!(self, v, isize, write_isize_leb128) write_leb128!(self, v, isize, write_isize_leb128)
} }
#[inline] #[inline]
fn emit_i128(&mut self, v: i128) -> EncodeResult { fn emit_i128(&mut self, v: i128) {
write_leb128!(self, v, i128, write_i128_leb128) write_leb128!(self, v, i128, write_i128_leb128)
} }
#[inline] #[inline]
fn emit_i64(&mut self, v: i64) -> EncodeResult { fn emit_i64(&mut self, v: i64) {
write_leb128!(self, v, i64, write_i64_leb128) write_leb128!(self, v, i64, write_i64_leb128)
} }
#[inline] #[inline]
fn emit_i32(&mut self, v: i32) -> EncodeResult { fn emit_i32(&mut self, v: i32) {
write_leb128!(self, v, i32, write_i32_leb128) write_leb128!(self, v, i32, write_i32_leb128)
} }
#[inline] #[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()); self.data.extend_from_slice(&v.to_le_bytes());
Ok(())
} }
#[inline] #[inline]
fn emit_i8(&mut self, v: i8) -> EncodeResult { fn emit_i8(&mut self, v: i8) {
self.emit_u8(v as u8) self.emit_u8(v as u8);
} }
#[inline] #[inline]
fn emit_bool(&mut self, v: bool) -> EncodeResult { fn emit_bool(&mut self, v: bool) {
self.emit_u8(if v { 1 } else { 0 }) self.emit_u8(if v { 1 } else { 0 });
} }
#[inline] #[inline]
fn emit_f64(&mut self, v: f64) -> EncodeResult { fn emit_f64(&mut self, v: f64) {
let as_u64: u64 = v.to_bits(); let as_u64: u64 = v.to_bits();
self.emit_u64(as_u64) self.emit_u64(as_u64);
} }
#[inline] #[inline]
fn emit_f32(&mut self, v: f32) -> EncodeResult { fn emit_f32(&mut self, v: f32) {
let as_u32: u32 = v.to_bits(); let as_u32: u32 = v.to_bits();
self.emit_u32(as_u32) self.emit_u32(as_u32);
} }
#[inline] #[inline]
fn emit_char(&mut self, v: char) -> EncodeResult { fn emit_char(&mut self, v: char) {
self.emit_u32(v as u32) self.emit_u32(v as u32);
} }
#[inline] #[inline]
fn emit_str(&mut self, v: &str) -> EncodeResult { fn emit_str(&mut self, v: &str) {
self.emit_usize(v.len())?; self.emit_usize(v.len());
self.emit_raw_bytes(v.as_bytes())?; self.emit_raw_bytes(v.as_bytes());
self.emit_u8(STR_SENTINEL) self.emit_u8(STR_SENTINEL);
} }
#[inline] #[inline]
fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult { fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s); self.data.extend_from_slice(s);
Ok(())
} }
} }
pub type FileEncodeResult = Result<(), io::Error>; pub type FileEncodeResult = Result<usize, io::Error>;
// `FileEncoder` encodes data to file via fixed-size buffer. // `FileEncoder` encodes data to file via fixed-size buffer.
// //
// When encoding large amounts of data to a file, using `FileEncoder` may be // When encoding large amounts of data to a file, using `FileEncoder` may be
// preferred over using `Encoder` to encode to a `Vec`, and then writing the // preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
// `Vec` to file, as the latter uses as much memory as there is encoded data, // `Vec` to file, as the latter uses as much memory as there is encoded data,
// while the former uses the fixed amount of memory allocated to the buffer. // while the former uses the fixed amount of memory allocated to the buffer.
// `FileEncoder` also has the advantage of not needing to reallocate as data // `FileEncoder` also has the advantage of not needing to reallocate as data
@ -182,6 +172,9 @@ pub struct FileEncoder {
buffered: usize, buffered: usize,
flushed: usize, flushed: usize,
file: File, file: File,
// This is used to implement delayed error handling, as described in the
// comment on `trait Encoder`.
res: Result<(), io::Error>,
} }
impl FileEncoder { impl FileEncoder {
@ -202,7 +195,13 @@ impl FileEncoder {
let file = File::create(path)?; 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] #[inline]
@ -212,7 +211,7 @@ impl FileEncoder {
self.flushed + self.buffered 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 // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever
// offers a raw buffer access API, we can use it, and remove this. // offers a raw buffer access API, we can use it, and remove this.
@ -267,6 +266,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( let mut guard = BufGuard::new(
unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) }, unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) },
&mut self.buffered, &mut self.buffered,
@ -276,18 +281,20 @@ impl FileEncoder {
while !guard.done() { while !guard.done() {
match self.file.write(guard.remaining()) { match self.file.write(guard.remaining()) {
Ok(0) => { Ok(0) => {
return Err(io::Error::new( self.res = Err(io::Error::new(
io::ErrorKind::WriteZero, io::ErrorKind::WriteZero,
"failed to write the buffered data", "failed to write the buffered data",
)); ));
return;
} }
Ok(n) => guard.consume(n), Ok(n) => guard.consume(n),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e), Err(e) => {
self.res = Err(e);
return;
}
} }
} }
Ok(())
} }
#[inline] #[inline]
@ -296,14 +303,14 @@ impl FileEncoder {
} }
#[inline] #[inline]
fn write_one(&mut self, value: u8) -> FileEncodeResult { fn write_one(&mut self, value: u8) {
// We ensure this during `FileEncoder` construction. // We ensure this during `FileEncoder` construction.
debug_assert!(self.capacity() >= 1); debug_assert!(self.capacity() >= 1);
let mut buffered = self.buffered; let mut buffered = self.buffered;
if std::intrinsics::unlikely(buffered >= self.capacity()) { if std::intrinsics::unlikely(buffered >= self.capacity()) {
self.flush()?; self.flush();
buffered = 0; buffered = 0;
} }
@ -314,12 +321,10 @@ impl FileEncoder {
} }
self.buffered = buffered + 1; self.buffered = buffered + 1;
Ok(())
} }
#[inline] #[inline]
fn write_all(&mut self, buf: &[u8]) -> FileEncodeResult { fn write_all(&mut self, buf: &[u8]) {
let capacity = self.capacity(); let capacity = self.capacity();
let buf_len = buf.len(); let buf_len = buf.len();
@ -327,7 +332,7 @@ impl FileEncoder {
let mut buffered = self.buffered; let mut buffered = self.buffered;
if std::intrinsics::unlikely(buf_len > capacity - buffered) { if std::intrinsics::unlikely(buf_len > capacity - buffered) {
self.flush()?; self.flush();
buffered = 0; buffered = 0;
} }
@ -340,16 +345,20 @@ impl FileEncoder {
} }
self.buffered = buffered + buf_len; self.buffered = buffered + buf_len;
Ok(())
} else { } 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 { if self.buffered > 0 {
self.flush()?; self.flush();
} }
// This is basically a copy of `Write::write_all` but also updates our // This is basically a copy of `Write::write_all` but also updates our
@ -359,26 +368,37 @@ impl FileEncoder {
while !buf.is_empty() { while !buf.is_empty() {
match self.file.write(buf) { match self.file.write(buf) {
Ok(0) => { Ok(0) => {
return Err(io::Error::new( self.res = Err(io::Error::new(
io::ErrorKind::WriteZero, io::ErrorKind::WriteZero,
"failed to write whole buffer", "failed to write whole buffer",
)); ));
return;
} }
Ok(n) => { Ok(n) => {
buf = &buf[n..]; buf = &buf[n..];
self.flushed += n; self.flushed += n;
} }
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e), Err(e) => {
self.res = Err(e);
return;
}
} }
} }
}
Ok(()) pub fn finish(mut self) -> Result<usize, io::Error> {
self.flush();
let res = std::mem::replace(&mut self.res, Ok(()));
res.map(|()| self.position())
} }
} }
impl Drop for FileEncoder { impl Drop for FileEncoder {
fn drop(&mut self) { 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(); let _result = self.flush();
} }
} }
@ -394,7 +414,7 @@ macro_rules! file_encoder_write_leb128 {
// This can't overflow. See assertion in `FileEncoder::with_capacity`. // This can't overflow. See assertion in `FileEncoder::with_capacity`.
if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) { if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) {
$enc.flush()?; $enc.flush();
buffered = 0; buffered = 0;
} }
@ -406,106 +426,102 @@ macro_rules! file_encoder_write_leb128 {
let encoded = leb128::$fun(buf, $value); let encoded = leb128::$fun(buf, $value);
$enc.buffered = buffered + encoded.len(); $enc.buffered = buffered + encoded.len();
Ok(())
}}; }};
} }
impl serialize::Encoder for FileEncoder { impl Encoder for FileEncoder {
type Error = io::Error;
#[inline] #[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) file_encoder_write_leb128!(self, v, usize, write_usize_leb128)
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, u128, write_u128_leb128)
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, u64, write_u64_leb128)
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, u32, write_u32_leb128)
} }
#[inline] #[inline]
fn emit_u16(&mut self, v: u16) -> FileEncodeResult { fn emit_u16(&mut self, v: u16) {
self.write_all(&v.to_le_bytes()) self.write_all(&v.to_le_bytes());
} }
#[inline] #[inline]
fn emit_u8(&mut self, v: u8) -> FileEncodeResult { fn emit_u8(&mut self, v: u8) {
self.write_one(v) self.write_one(v);
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, isize, write_isize_leb128)
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, i128, write_i128_leb128)
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, i64, write_i64_leb128)
} }
#[inline] #[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) file_encoder_write_leb128!(self, v, i32, write_i32_leb128)
} }
#[inline] #[inline]
fn emit_i16(&mut self, v: i16) -> FileEncodeResult { fn emit_i16(&mut self, v: i16) {
self.write_all(&v.to_le_bytes()) self.write_all(&v.to_le_bytes());
} }
#[inline] #[inline]
fn emit_i8(&mut self, v: i8) -> FileEncodeResult { fn emit_i8(&mut self, v: i8) {
self.emit_u8(v as u8) self.emit_u8(v as u8);
} }
#[inline] #[inline]
fn emit_bool(&mut self, v: bool) -> FileEncodeResult { fn emit_bool(&mut self, v: bool) {
self.emit_u8(if v { 1 } else { 0 }) self.emit_u8(if v { 1 } else { 0 });
} }
#[inline] #[inline]
fn emit_f64(&mut self, v: f64) -> FileEncodeResult { fn emit_f64(&mut self, v: f64) {
let as_u64: u64 = v.to_bits(); let as_u64: u64 = v.to_bits();
self.emit_u64(as_u64) self.emit_u64(as_u64);
} }
#[inline] #[inline]
fn emit_f32(&mut self, v: f32) -> FileEncodeResult { fn emit_f32(&mut self, v: f32) {
let as_u32: u32 = v.to_bits(); let as_u32: u32 = v.to_bits();
self.emit_u32(as_u32) self.emit_u32(as_u32);
} }
#[inline] #[inline]
fn emit_char(&mut self, v: char) -> FileEncodeResult { fn emit_char(&mut self, v: char) {
self.emit_u32(v as u32) self.emit_u32(v as u32);
} }
#[inline] #[inline]
fn emit_str(&mut self, v: &str) -> FileEncodeResult { fn emit_str(&mut self, v: &str) {
self.emit_usize(v.len())?; self.emit_usize(v.len());
self.emit_raw_bytes(v.as_bytes())?; self.emit_raw_bytes(v.as_bytes());
self.emit_u8(STR_SENTINEL) self.emit_u8(STR_SENTINEL);
} }
#[inline] #[inline]
fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult { fn emit_raw_bytes(&mut self, s: &[u8]) {
self.write_all(s) self.write_all(s);
} }
} }
@ -513,15 +529,15 @@ impl serialize::Encoder for FileEncoder {
// Decoder // Decoder
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub struct Decoder<'a> { pub struct MemDecoder<'a> {
pub data: &'a [u8], pub data: &'a [u8],
position: usize, position: usize,
} }
impl<'a> Decoder<'a> { impl<'a> MemDecoder<'a> {
#[inline] #[inline]
pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { pub fn new(data: &'a [u8], position: usize) -> MemDecoder<'a> {
Decoder { data, position } MemDecoder { data, position }
} }
#[inline] #[inline]
@ -544,7 +560,7 @@ macro_rules! read_leb128 {
($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }}; ($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }};
} }
impl<'a> serialize::Decoder for Decoder<'a> { impl<'a> Decoder for MemDecoder<'a> {
#[inline] #[inline]
fn read_u128(&mut self) -> u128 { fn read_u128(&mut self) -> u128 {
read_leb128!(self, read_u128_leb128) read_leb128!(self, read_u128_leb128)
@ -666,25 +682,25 @@ impl<'a> serialize::Decoder for Decoder<'a> {
// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc., // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
// since the default implementations call `encode` on their slices internally. // since the default implementations call `encode` on their slices internally.
impl serialize::Encodable<Encoder> for [u8] { impl Encodable<MemEncoder> for [u8] {
fn encode(&self, e: &mut Encoder) -> EncodeResult { fn encode(&self, e: &mut MemEncoder) {
serialize::Encoder::emit_usize(e, self.len())?; Encoder::emit_usize(e, self.len());
e.emit_raw_bytes(self) e.emit_raw_bytes(self);
} }
} }
impl serialize::Encodable<FileEncoder> for [u8] { impl Encodable<FileEncoder> for [u8] {
fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { fn encode(&self, e: &mut FileEncoder) {
serialize::Encoder::emit_usize(e, self.len())?; Encoder::emit_usize(e, self.len());
e.emit_raw_bytes(self) e.emit_raw_bytes(self);
} }
} }
// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc., // Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
// since the default implementations call `decode` to produce a `Vec<u8>` internally. // since the default implementations call `decode` to produce a `Vec<u8>` internally.
impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> { impl<'a> Decodable<MemDecoder<'a>> for Vec<u8> {
fn decode(d: &mut Decoder<'a>) -> Self { fn decode(d: &mut MemDecoder<'a>) -> Self {
let len = serialize::Decoder::read_usize(d); let len = Decoder::read_usize(d);
d.read_raw_bytes(len).to_owned() d.read_raw_bytes(len).to_owned()
} }
} }
@ -696,31 +712,29 @@ impl IntEncodedWithFixedSize {
pub const ENCODED_SIZE: usize = 8; pub const ENCODED_SIZE: usize = 8;
} }
impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize { impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
#[inline] #[inline]
fn encode(&self, e: &mut Encoder) -> EncodeResult { fn encode(&self, e: &mut MemEncoder) {
let _start_pos = e.position(); 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(); let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
} }
} }
impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize { impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
#[inline] #[inline]
fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult { fn encode(&self, e: &mut FileEncoder) {
let _start_pos = e.position(); 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(); let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
} }
} }
impl<'a> serialize::Decodable<Decoder<'a>> for IntEncodedWithFixedSize { impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize {
#[inline] #[inline]
fn decode(decoder: &mut Decoder<'a>) -> IntEncodedWithFixedSize { fn decode(decoder: &mut MemDecoder<'a>) -> IntEncodedWithFixedSize {
let _start_pos = decoder.position(); let _start_pos = decoder.position();
let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE); let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
let value = u64::from_le_bytes(bytes.try_into().unwrap()); let value = u64::from_le_bytes(bytes.try_into().unwrap());

View file

@ -11,36 +11,44 @@ use std::path;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; 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 they should provide
/// a `finish` method that finishes up encoding. If the encoder is fallible,
/// `finish` should return a `Result` that indicates success or failure.
pub trait Encoder { pub trait Encoder {
type Error;
// Primitive types: // Primitive types:
fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>; fn emit_usize(&mut self, v: usize);
fn emit_u128(&mut self, v: u128) -> Result<(), Self::Error>; fn emit_u128(&mut self, v: u128);
fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; fn emit_u64(&mut self, v: u64);
fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; fn emit_u32(&mut self, v: u32);
fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; fn emit_u16(&mut self, v: u16);
fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; fn emit_u8(&mut self, v: u8);
fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>; fn emit_isize(&mut self, v: isize);
fn emit_i128(&mut self, v: i128) -> Result<(), Self::Error>; fn emit_i128(&mut self, v: i128);
fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; fn emit_i64(&mut self, v: i64);
fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; fn emit_i32(&mut self, v: i32);
fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; fn emit_i16(&mut self, v: i16);
fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>; fn emit_i8(&mut self, v: i8);
fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>; fn emit_bool(&mut self, v: bool);
fn emit_f64(&mut self, v: f64) -> Result<(), Self::Error>; fn emit_f64(&mut self, v: f64);
fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; fn emit_f32(&mut self, v: f32);
fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; fn emit_char(&mut self, v: char);
fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; fn emit_str(&mut self, v: &str);
fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>; fn emit_raw_bytes(&mut self, s: &[u8]);
// Convenience for the derive macro: // 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 where
F: FnOnce(&mut Self) -> Result<(), Self::Error>, F: FnOnce(&mut Self),
{ {
self.emit_usize(v_id)?; self.emit_usize(v_id);
f(self) f(self);
} }
// We put the field index in a const generic to allow the emit_usize to be // We put the field index in a const generic to allow the emit_usize to be
@ -50,7 +58,7 @@ pub trait Encoder {
// optimization that would otherwise be necessary here, likely due to the // optimization that would otherwise be necessary here, likely due to the
// multiple levels of inlining and const-prop that are needed. // multiple levels of inlining and const-prop that are needed.
#[inline] #[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) self.emit_usize(ID)
} }
} }
@ -95,7 +103,7 @@ pub trait Decoder {
/// * `TyEncodable` should be used for types that are only serialized in crate /// * `TyEncodable` should be used for types that are only serialized in crate
/// metadata or the incremental cache. This is most types in `rustc_middle`. /// metadata or the incremental cache. This is most types in `rustc_middle`.
pub trait Encodable<S: Encoder> { 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 /// Trait for types that can be deserialized
@ -117,8 +125,8 @@ macro_rules! direct_serialize_impls {
($($ty:ident $emit_method:ident $read_method:ident),*) => { ($($ty:ident $emit_method:ident $read_method:ident),*) => {
$( $(
impl<S: Encoder> Encodable<S> for $ty { impl<S: Encoder> Encodable<S> for $ty {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.$emit_method(*self) s.$emit_method(*self);
} }
} }
@ -138,12 +146,14 @@ direct_serialize_impls! {
u32 emit_u32 read_u32, u32 emit_u32 read_u32,
u64 emit_u64 read_u64, u64 emit_u64 read_u64,
u128 emit_u128 read_u128, u128 emit_u128 read_u128,
isize emit_isize read_isize, isize emit_isize read_isize,
i8 emit_i8 read_i8, i8 emit_i8 read_i8,
i16 emit_i16 read_i16, i16 emit_i16 read_i16,
i32 emit_i32 read_i32, i32 emit_i32 read_i32,
i64 emit_i64 read_i64, i64 emit_i64 read_i64,
i128 emit_i128 read_i128, i128 emit_i128 read_i128,
f32 emit_f32 read_f32, f32 emit_f32 read_f32,
f64 emit_f64 read_f64, f64 emit_f64 read_f64,
bool emit_bool read_bool, bool emit_bool read_bool,
@ -154,14 +164,14 @@ impl<S: Encoder, T: ?Sized> Encodable<S> for &T
where where
T: Encodable<S>, T: Encodable<S>,
{ {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
(**self).encode(s) (**self).encode(s)
} }
} }
impl<S: Encoder> Encodable<S> for ! { impl<S: Encoder> Encodable<S> for ! {
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {
unreachable!() unreachable!();
} }
} }
@ -172,8 +182,8 @@ impl<D: Decoder> Decodable<D> for ! {
} }
impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 { impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_u32(self.get()) s.emit_u32(self.get());
} }
} }
@ -184,14 +194,14 @@ impl<D: Decoder> Decodable<D> for ::std::num::NonZeroU32 {
} }
impl<S: Encoder> Encodable<S> for str { impl<S: Encoder> Encodable<S> for str {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_str(self) s.emit_str(self);
} }
} }
impl<S: Encoder> Encodable<S> for String { impl<S: Encoder> Encodable<S> for String {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_str(&self[..]) s.emit_str(&self[..]);
} }
} }
@ -202,9 +212,7 @@ impl<D: Decoder> Decodable<D> for String {
} }
impl<S: Encoder> Encodable<S> for () { impl<S: Encoder> Encodable<S> for () {
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {}
Ok(())
}
} }
impl<D: Decoder> Decodable<D> for () { impl<D: Decoder> Decodable<D> for () {
@ -212,9 +220,7 @@ impl<D: Decoder> Decodable<D> for () {
} }
impl<S: Encoder, T> Encodable<S> for PhantomData<T> { impl<S: Encoder, T> Encodable<S> for PhantomData<T> {
fn encode(&self, _s: &mut S) -> Result<(), S::Error> { fn encode(&self, _s: &mut S) {}
Ok(())
}
} }
impl<D: Decoder, T> Decodable<D> for PhantomData<T> { impl<D: Decoder, T> Decodable<D> for PhantomData<T> {
@ -231,8 +237,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<[T]> {
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for Rc<T> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for Rc<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
(**self).encode(s) (**self).encode(s);
} }
} }
@ -243,19 +249,18 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] { impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
default fn encode(&self, s: &mut S) -> Result<(), S::Error> { default fn encode(&self, s: &mut S) {
s.emit_usize(self.len())?; s.emit_usize(self.len());
for e in self.iter() { for e in self.iter() {
e.encode(s)? e.encode(s);
} }
Ok(())
} }
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> { 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; let slice: &[T] = self;
slice.encode(s) slice.encode(s);
} }
} }
@ -277,9 +282,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] { 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; let slice: &[T] = self;
slice.encode(s) slice.encode(s);
} }
} }
@ -299,9 +304,9 @@ impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]>
where where
[T]: ToOwned<Owned = Vec<T>>, [T]: ToOwned<Owned = Vec<T>>,
{ {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
let slice: &[T] = self; let slice: &[T] = self;
slice.encode(s) slice.encode(s);
} }
} }
@ -316,7 +321,7 @@ where
} }
impl<'a, S: Encoder> Encodable<S> for Cow<'a, str> { 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; let val: &str = self;
val.encode(s) val.encode(s)
} }
@ -330,9 +335,9 @@ impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> {
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> { 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 { 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)), Some(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
} }
} }
@ -349,7 +354,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> { 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 { match *self {
Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)), Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)),
Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)), Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
@ -381,10 +386,9 @@ macro_rules! tuple {
} }
impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) { impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) {
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
let ($(ref $name,)+) = *self; let ($(ref $name,)+) = *self;
$($name.encode(s)?;)+ $($name.encode(s);)+
Ok(())
} }
} }
peel! { $($name,)+ } peel! { $($name,)+ }
@ -394,14 +398,14 @@ macro_rules! tuple {
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
impl<S: Encoder> Encodable<S> for path::Path { impl<S: Encoder> Encodable<S> for path::Path {
fn encode(&self, e: &mut S) -> Result<(), S::Error> { fn encode(&self, e: &mut S) {
self.to_str().unwrap().encode(e) self.to_str().unwrap().encode(e);
} }
} }
impl<S: Encoder> Encodable<S> for path::PathBuf { impl<S: Encoder> Encodable<S> for path::PathBuf {
fn encode(&self, e: &mut S) -> Result<(), S::Error> { fn encode(&self, e: &mut S) {
path::Path::encode(self, e) path::Path::encode(self, e);
} }
} }
@ -413,8 +417,8 @@ impl<D: Decoder> Decodable<D> for path::PathBuf {
} }
impl<S: Encoder, T: Encodable<S> + Copy> Encodable<S> for Cell<T> { impl<S: Encoder, T: Encodable<S> + Copy> Encodable<S> for Cell<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
self.get().encode(s) self.get().encode(s);
} }
} }
@ -430,8 +434,8 @@ impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> {
// from `encode` when `try_borrow` returns `None`. // from `encode` when `try_borrow` returns `None`.
impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
self.borrow().encode(s) self.borrow().encode(s);
} }
} }
@ -442,8 +446,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for RefCell<T> {
} }
impl<S: Encoder, T: Encodable<S>> Encodable<S> for Arc<T> { impl<S: Encoder, T: Encodable<S>> Encodable<S> for Arc<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
(**self).encode(s) (**self).encode(s);
} }
} }
@ -454,8 +458,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<T> {
} }
impl<S: Encoder, T: ?Sized + Encodable<S>> Encodable<S> for Box<T> { impl<S: Encoder, T: ?Sized + Encodable<S>> Encodable<S> for Box<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
(**self).encode(s) (**self).encode(s);
} }
} }
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<T> { impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<T> {

View file

@ -1,7 +1,7 @@
#![allow(rustc::internal)] #![allow(rustc::internal)]
use rustc_macros::{Decodable, Encodable}; use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{Decoder, Encoder}; use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::{Decodable, Encodable};
use std::fmt::Debug; use std::fmt::Debug;
@ -28,17 +28,18 @@ struct Struct {
q: Option<u32>, q: Option<u32>,
} }
fn check_round_trip<T: Encodable<Encoder> + for<'a> Decodable<Decoder<'a>> + PartialEq + Debug>( fn check_round_trip<
T: Encodable<MemEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
>(
values: Vec<T>, values: Vec<T>,
) { ) {
let mut encoder = Encoder::new(Vec::new()); let mut encoder = MemEncoder::new();
for value in &values { for value in &values {
Encodable::encode(value, &mut encoder).unwrap(); Encodable::encode(value, &mut encoder);
} }
let data = encoder.into_inner(); let data = encoder.finish();
let mut decoder = Decoder::new(&data[..], 0); let mut decoder = MemDecoder::new(&data[..], 0);
for value in values { for value in values {
let decoded = Decodable::decode(&mut decoder); let decoded = Decodable::decode(&mut decoder);

View file

@ -41,8 +41,8 @@ impl fmt::Display for CrateNum {
/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx. /// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
/// Therefore, make sure to include the context when encode a `CrateNum`. /// Therefore, make sure to include the context when encode a `CrateNum`.
impl<E: Encoder> Encodable<E> for CrateNum { impl<E: Encoder> Encodable<E> for CrateNum {
default fn encode(&self, s: &mut E) -> Result<(), E::Error> { default fn encode(&self, s: &mut E) {
s.emit_u32(self.as_u32()) s.emit_u32(self.as_u32());
} }
} }
@ -203,7 +203,7 @@ rustc_index::newtype_index! {
} }
impl<E: Encoder> Encodable<E> for DefIndex { impl<E: Encoder> Encodable<E> for DefIndex {
default fn encode(&self, _: &mut E) -> Result<(), E::Error> { default fn encode(&self, _: &mut E) {
panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>()); panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
} }
} }
@ -306,9 +306,9 @@ impl DefId {
} }
impl<E: Encoder> Encodable<E> for DefId { impl<E: Encoder> Encodable<E> for DefId {
default fn encode(&self, s: &mut E) -> Result<(), E::Error> { default fn encode(&self, s: &mut E) {
self.krate.encode(s)?; self.krate.encode(s);
self.index.encode(s) self.index.encode(s);
} }
} }
@ -382,8 +382,8 @@ impl fmt::Debug for LocalDefId {
} }
impl<E: Encoder> Encodable<E> for LocalDefId { impl<E: Encoder> Encodable<E> for LocalDefId {
fn encode(&self, s: &mut E) -> Result<(), E::Error> { fn encode(&self, s: &mut E) {
self.to_def_id().encode(s) self.to_def_id().encode(s);
} }
} }

View file

@ -1189,12 +1189,12 @@ impl HygieneEncodeContext {
} }
} }
pub fn encode<T, R>( pub fn encode<T>(
&self, &self,
encoder: &mut T, encoder: &mut T,
mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>, mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData),
mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash) -> Result<(), R>, mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash),
) -> Result<(), R> { ) {
// When we serialize a `SyntaxContextData`, we may end up serializing // When we serialize a `SyntaxContextData`, we may end up serializing
// a `SyntaxContext` that we haven't seen before // a `SyntaxContext` that we haven't seen before
while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() { while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() {
@ -1213,22 +1213,19 @@ impl HygieneEncodeContext {
// order // order
for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| { for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| {
if self.serialized_ctxts.lock().insert(ctxt) { if self.serialized_ctxts.lock().insert(ctxt) {
encode_ctxt(encoder, index, data)?; encode_ctxt(encoder, index, data);
} }
Ok(()) });
})?;
let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) }; let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| { for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| {
if self.serialized_expns.lock().insert(expn) { if self.serialized_expns.lock().insert(expn) {
encode_expn(encoder, expn, data, hash)?; encode_expn(encoder, expn, data, hash);
} }
Ok(()) });
})?;
} }
debug!("encode_hygiene: Done serializing SyntaxContextData"); debug!("encode_hygiene: Done serializing SyntaxContextData");
Ok(())
} }
} }
@ -1378,40 +1375,38 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
new_ctxt new_ctxt
} }
fn for_all_ctxts_in<E, F: FnMut(u32, SyntaxContext, &SyntaxContextData) -> Result<(), E>>( fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextData)>(
ctxts: impl Iterator<Item = SyntaxContext>, ctxts: impl Iterator<Item = SyntaxContext>,
mut f: F, mut f: F,
) -> Result<(), E> { ) {
let all_data: Vec<_> = HygieneData::with(|data| { let all_data: Vec<_> = HygieneData::with(|data| {
ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect()
}); });
for (ctxt, data) in all_data.into_iter() { for (ctxt, data) in all_data.into_iter() {
f(ctxt.0, ctxt, &data)?; f(ctxt.0, ctxt, &data);
} }
Ok(())
} }
fn for_all_expns_in<E>( fn for_all_expns_in(
expns: impl Iterator<Item = ExpnId>, expns: impl Iterator<Item = ExpnId>,
mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>, mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash),
) -> Result<(), E> { ) {
let all_data: Vec<_> = HygieneData::with(|data| { let all_data: Vec<_> = HygieneData::with(|data| {
expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect() expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect()
}); });
for (expn, data, hash) in all_data.into_iter() { for (expn, data, hash) in all_data.into_iter() {
f(expn, &data, hash)?; f(expn, &data, hash);
} }
Ok(())
} }
impl<E: Encoder> Encodable<E> for LocalExpnId { impl<E: Encoder> Encodable<E> for LocalExpnId {
fn encode(&self, e: &mut E) -> Result<(), E::Error> { fn encode(&self, e: &mut E) {
self.to_expn_id().encode(e) self.to_expn_id().encode(e);
} }
} }
impl<E: Encoder> Encodable<E> for ExpnId { impl<E: Encoder> Encodable<E> for ExpnId {
default fn encode(&self, _: &mut E) -> Result<(), E::Error> { default fn encode(&self, _: &mut E) {
panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>()); panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
} }
} }
@ -1432,15 +1427,15 @@ pub fn raw_encode_syntax_context<E: Encoder>(
ctxt: SyntaxContext, ctxt: SyntaxContext,
context: &HygieneEncodeContext, context: &HygieneEncodeContext,
e: &mut E, e: &mut E,
) -> Result<(), E::Error> { ) {
if !context.serialized_ctxts.lock().contains(&ctxt) { if !context.serialized_ctxts.lock().contains(&ctxt) {
context.latest_ctxts.lock().insert(ctxt); context.latest_ctxts.lock().insert(ctxt);
} }
ctxt.0.encode(e) ctxt.0.encode(e);
} }
impl<E: Encoder> Encodable<E> for SyntaxContext { impl<E: Encoder> Encodable<E> for SyntaxContext {
default fn encode(&self, _: &mut E) -> Result<(), E::Error> { default fn encode(&self, _: &mut E) {
panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>()); panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
} }
} }

View file

@ -194,12 +194,10 @@ impl Hash for RealFileName {
// This is functionally identical to #[derive(Encodable)], with the exception of // This is functionally identical to #[derive(Encodable)], with the exception of
// an added assert statement // an added assert statement
impl<S: Encoder> Encodable<S> for RealFileName { impl<S: Encoder> Encodable<S> for RealFileName {
fn encode(&self, encoder: &mut S) -> Result<(), S::Error> { fn encode(&self, encoder: &mut S) {
match *self { match *self {
RealFileName::LocalPath(ref local_path) => encoder.emit_enum_variant(0, |encoder| { RealFileName::LocalPath(ref local_path) => encoder.emit_enum_variant(0, |encoder| {
Ok({ local_path.encode(encoder);
local_path.encode(encoder)?;
})
}), }),
RealFileName::Remapped { ref local_path, ref virtual_name } => encoder RealFileName::Remapped { ref local_path, ref virtual_name } => encoder
@ -207,9 +205,8 @@ impl<S: Encoder> Encodable<S> for RealFileName {
// For privacy and build reproducibility, we must not embed host-dependant path in artifacts // For privacy and build reproducibility, we must not embed host-dependant path in artifacts
// if they have been remapped by --remap-path-prefix // if they have been remapped by --remap-path-prefix
assert!(local_path.is_none()); assert!(local_path.is_none());
local_path.encode(encoder)?; local_path.encode(encoder);
virtual_name.encode(encoder)?; virtual_name.encode(encoder);
Ok(())
}), }),
} }
} }
@ -946,10 +943,10 @@ impl Default for Span {
} }
impl<E: Encoder> Encodable<E> for Span { impl<E: Encoder> Encodable<E> for Span {
default fn encode(&self, s: &mut E) -> Result<(), E::Error> { default fn encode(&self, s: &mut E) {
let span = self.data(); let span = self.data();
span.lo.encode(s)?; span.lo.encode(s);
span.hi.encode(s) span.hi.encode(s);
} }
} }
impl<D: Decoder> Decodable<D> for Span { impl<D: Decoder> Decodable<D> for Span {
@ -1297,17 +1294,17 @@ pub struct SourceFile {
} }
impl<S: Encoder> Encodable<S> for SourceFile { impl<S: Encoder> Encodable<S> for SourceFile {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
self.name.encode(s)?; self.name.encode(s);
self.src_hash.encode(s)?; self.src_hash.encode(s);
self.start_pos.encode(s)?; self.start_pos.encode(s);
self.end_pos.encode(s)?; self.end_pos.encode(s);
// We are always in `Lines` form by the time we reach here. // We are always in `Lines` form by the time we reach here.
assert!(self.lines.borrow().is_lines()); assert!(self.lines.borrow().is_lines());
self.lines(|lines| { self.lines(|lines| {
// Store the length. // Store the length.
s.emit_u32(lines.len() as u32)?; s.emit_u32(lines.len() as u32);
// Compute and store the difference list. // Compute and store the difference list.
if lines.len() != 0 { if lines.len() != 0 {
@ -1329,10 +1326,10 @@ impl<S: Encoder> Encodable<S> for SourceFile {
}; };
// Encode the number of bytes used per diff. // Encode the number of bytes used per diff.
s.emit_u8(bytes_per_diff as u8)?; s.emit_u8(bytes_per_diff as u8);
// Encode the first element. // Encode the first element.
lines[0].encode(s)?; lines[0].encode(s);
// Encode the difference list. // Encode the difference list.
let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst); let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst);
@ -1359,16 +1356,15 @@ impl<S: Encoder> Encodable<S> for SourceFile {
} }
_ => unreachable!(), _ => unreachable!(),
} }
s.emit_raw_bytes(&raw_diffs)?; s.emit_raw_bytes(&raw_diffs);
} }
Ok(()) });
})?;
self.multibyte_chars.encode(s)?; self.multibyte_chars.encode(s);
self.non_narrow_chars.encode(s)?; self.non_narrow_chars.encode(s);
self.name_hash.encode(s)?; self.name_hash.encode(s);
self.normalized_pos.encode(s)?; self.normalized_pos.encode(s);
self.cnum.encode(s) self.cnum.encode(s);
} }
} }
@ -1915,13 +1911,13 @@ impl_pos! {
pub struct CharPos(pub usize); pub struct CharPos(pub usize);
} }
impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos { impl<S: Encoder> Encodable<S> for BytePos {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_u32(self.0) s.emit_u32(self.0);
} }
} }
impl<D: rustc_serialize::Decoder> Decodable<D> for BytePos { impl<D: Decoder> Decodable<D> for BytePos {
fn decode(d: &mut D) -> BytePos { fn decode(d: &mut D) -> BytePos {
BytePos(d.read_u32()) BytePos(d.read_u32())
} }

View file

@ -1802,8 +1802,8 @@ impl fmt::Display for Symbol {
} }
impl<S: Encoder> Encodable<S> for Symbol { impl<S: Encoder> Encodable<S> for Symbol {
fn encode(&self, s: &mut S) -> Result<(), S::Error> { fn encode(&self, s: &mut S) {
s.emit_str(self.as_str()) s.emit_str(self.as_str());
} }
} }

View file

@ -31,10 +31,7 @@ pub trait TyEncoder: Encoder {
fn predicate_shorthands( fn predicate_shorthands(
&mut self, &mut self,
) -> &mut FxHashMap<<Self::I as Interner>::PredicateKind, usize>; ) -> &mut FxHashMap<<Self::I as Interner>::PredicateKind, usize>;
fn encode_alloc_id( fn encode_alloc_id(&mut self, alloc_id: &<Self::I as Interner>::AllocId);
&mut self,
alloc_id: &<Self::I as Interner>::AllocId,
) -> Result<(), Self::Error>;
} }
pub trait TyDecoder: Decoder { pub trait TyDecoder: Decoder {

View file

@ -14,7 +14,7 @@ use crate::UintTy;
use self::TyKind::*; use self::TyKind::*;
use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::stable_hasher::HashStable;
use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::{Decodable, Decoder, Encodable};
/// Defines the kinds of types used by the type system. /// Defines the kinds of types used by the type system.
/// ///
@ -715,115 +715,92 @@ where
I::PredicateKind: Encodable<E>, I::PredicateKind: Encodable<E>,
I::AllocId: Encodable<E>, I::AllocId: Encodable<E>,
{ {
fn encode(&self, e: &mut E) -> Result<(), <E as rustc_serialize::Encoder>::Error> { fn encode(&self, e: &mut E) {
let disc = discriminant(self); let disc = discriminant(self);
match self { match self {
Bool => e.emit_enum_variant(disc, |_| Ok(())), Bool => e.emit_enum_variant(disc, |_| {}),
Char => e.emit_enum_variant(disc, |_| Ok(())), Char => e.emit_enum_variant(disc, |_| {}),
Int(i) => e.emit_enum_variant(disc, |e| { Int(i) => e.emit_enum_variant(disc, |e| {
i.encode(e)?; i.encode(e);
Ok(())
}), }),
Uint(u) => e.emit_enum_variant(disc, |e| { Uint(u) => e.emit_enum_variant(disc, |e| {
u.encode(e)?; u.encode(e);
Ok(())
}), }),
Float(f) => e.emit_enum_variant(disc, |e| { Float(f) => e.emit_enum_variant(disc, |e| {
f.encode(e)?; f.encode(e);
Ok(())
}), }),
Adt(adt, substs) => e.emit_enum_variant(disc, |e| { Adt(adt, substs) => e.emit_enum_variant(disc, |e| {
adt.encode(e)?; adt.encode(e);
substs.encode(e)?; substs.encode(e);
Ok(())
}), }),
Foreign(def_id) => e.emit_enum_variant(disc, |e| { Foreign(def_id) => e.emit_enum_variant(disc, |e| {
def_id.encode(e)?; def_id.encode(e);
Ok(())
}), }),
Str => e.emit_enum_variant(disc, |_| Ok(())), Str => e.emit_enum_variant(disc, |_| {}),
Array(t, c) => e.emit_enum_variant(disc, |e| { Array(t, c) => e.emit_enum_variant(disc, |e| {
t.encode(e)?; t.encode(e);
c.encode(e)?; c.encode(e);
Ok(())
}), }),
Slice(t) => e.emit_enum_variant(disc, |e| { Slice(t) => e.emit_enum_variant(disc, |e| {
t.encode(e)?; t.encode(e);
Ok(())
}), }),
RawPtr(tam) => e.emit_enum_variant(disc, |e| { RawPtr(tam) => e.emit_enum_variant(disc, |e| {
tam.encode(e)?; tam.encode(e);
Ok(())
}), }),
Ref(r, t, m) => e.emit_enum_variant(disc, |e| { Ref(r, t, m) => e.emit_enum_variant(disc, |e| {
r.encode(e)?; r.encode(e);
t.encode(e)?; t.encode(e);
m.encode(e)?; m.encode(e);
Ok(())
}), }),
FnDef(def_id, substs) => e.emit_enum_variant(disc, |e| { FnDef(def_id, substs) => e.emit_enum_variant(disc, |e| {
def_id.encode(e)?; def_id.encode(e);
substs.encode(e)?; substs.encode(e);
Ok(())
}), }),
FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| { FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
polyfnsig.encode(e)?; polyfnsig.encode(e);
Ok(())
}), }),
Dynamic(l, r) => e.emit_enum_variant(disc, |e| { Dynamic(l, r) => e.emit_enum_variant(disc, |e| {
l.encode(e)?; l.encode(e);
r.encode(e)?; r.encode(e);
Ok(())
}), }),
Closure(def_id, substs) => e.emit_enum_variant(disc, |e| { Closure(def_id, substs) => e.emit_enum_variant(disc, |e| {
def_id.encode(e)?; def_id.encode(e);
substs.encode(e)?; substs.encode(e);
Ok(())
}), }),
Generator(def_id, substs, m) => e.emit_enum_variant(disc, |e| { Generator(def_id, substs, m) => e.emit_enum_variant(disc, |e| {
def_id.encode(e)?; def_id.encode(e);
substs.encode(e)?; substs.encode(e);
m.encode(e)?; m.encode(e);
Ok(())
}), }),
GeneratorWitness(b) => e.emit_enum_variant(disc, |e| { GeneratorWitness(b) => e.emit_enum_variant(disc, |e| {
b.encode(e)?; b.encode(e);
Ok(())
}), }),
Never => e.emit_enum_variant(disc, |_| Ok(())), Never => e.emit_enum_variant(disc, |_| {}),
Tuple(substs) => e.emit_enum_variant(disc, |e| { Tuple(substs) => e.emit_enum_variant(disc, |e| {
substs.encode(e)?; substs.encode(e);
Ok(())
}), }),
Projection(p) => e.emit_enum_variant(disc, |e| { Projection(p) => e.emit_enum_variant(disc, |e| {
p.encode(e)?; p.encode(e);
Ok(())
}), }),
Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| { Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| {
def_id.encode(e)?; def_id.encode(e);
substs.encode(e)?; substs.encode(e);
Ok(())
}), }),
Param(p) => e.emit_enum_variant(disc, |e| { Param(p) => e.emit_enum_variant(disc, |e| {
p.encode(e)?; p.encode(e);
Ok(())
}), }),
Bound(d, b) => e.emit_enum_variant(disc, |e| { Bound(d, b) => e.emit_enum_variant(disc, |e| {
d.encode(e)?; d.encode(e);
b.encode(e)?; b.encode(e);
Ok(())
}), }),
Placeholder(p) => e.emit_enum_variant(disc, |e| { Placeholder(p) => e.emit_enum_variant(disc, |e| {
p.encode(e)?; p.encode(e);
Ok(())
}), }),
Infer(i) => e.emit_enum_variant(disc, |e| { Infer(i) => e.emit_enum_variant(disc, |e| {
i.encode(e)?; i.encode(e);
Ok(())
}), }),
Error(d) => e.emit_enum_variant(disc, |e| { Error(d) => e.emit_enum_variant(disc, |e| {
d.encode(e)?; d.encode(e);
Ok(())
}), }),
} }
} }
@ -856,56 +833,34 @@ where
I::AllocId: Decodable<D>, I::AllocId: Decodable<D>,
{ {
fn decode(d: &mut D) -> Self { fn decode(d: &mut D) -> Self {
match rustc_serialize::Decoder::read_usize(d) { match Decoder::read_usize(d) {
0 => Bool, 0 => Bool,
1 => Char, 1 => Char,
2 => Int(rustc_serialize::Decodable::decode(d)), 2 => Int(Decodable::decode(d)),
3 => Uint(rustc_serialize::Decodable::decode(d)), 3 => Uint(Decodable::decode(d)),
4 => Float(rustc_serialize::Decodable::decode(d)), 4 => Float(Decodable::decode(d)),
5 => Adt(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)), 5 => Adt(Decodable::decode(d), Decodable::decode(d)),
6 => Foreign(rustc_serialize::Decodable::decode(d)), 6 => Foreign(Decodable::decode(d)),
7 => Str, 7 => Str,
8 => { 8 => Array(Decodable::decode(d), Decodable::decode(d)),
Array(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) 9 => Slice(Decodable::decode(d)),
} 10 => RawPtr(Decodable::decode(d)),
9 => Slice(rustc_serialize::Decodable::decode(d)), 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
10 => RawPtr(rustc_serialize::Decodable::decode(d)), 12 => FnDef(Decodable::decode(d), Decodable::decode(d)),
11 => Ref( 13 => FnPtr(Decodable::decode(d)),
rustc_serialize::Decodable::decode(d), 14 => Dynamic(Decodable::decode(d), Decodable::decode(d)),
rustc_serialize::Decodable::decode(d), 15 => Closure(Decodable::decode(d), Decodable::decode(d)),
rustc_serialize::Decodable::decode(d), 16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
), 17 => GeneratorWitness(Decodable::decode(d)),
12 => {
FnDef(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d))
}
13 => FnPtr(rustc_serialize::Decodable::decode(d)),
14 => Dynamic(
rustc_serialize::Decodable::decode(d),
rustc_serialize::Decodable::decode(d),
),
15 => Closure(
rustc_serialize::Decodable::decode(d),
rustc_serialize::Decodable::decode(d),
),
16 => Generator(
rustc_serialize::Decodable::decode(d),
rustc_serialize::Decodable::decode(d),
rustc_serialize::Decodable::decode(d),
),
17 => GeneratorWitness(rustc_serialize::Decodable::decode(d)),
18 => Never, 18 => Never,
19 => Tuple(rustc_serialize::Decodable::decode(d)), 19 => Tuple(Decodable::decode(d)),
20 => Projection(rustc_serialize::Decodable::decode(d)), 20 => Projection(Decodable::decode(d)),
21 => { 21 => Opaque(Decodable::decode(d), Decodable::decode(d)),
Opaque(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) 22 => Param(Decodable::decode(d)),
} 23 => Bound(Decodable::decode(d), Decodable::decode(d)),
22 => Param(rustc_serialize::Decodable::decode(d)), 24 => Placeholder(Decodable::decode(d)),
23 => { 25 => Infer(Decodable::decode(d)),
Bound(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) 26 => Error(Decodable::decode(d)),
}
24 => Placeholder(rustc_serialize::Decodable::decode(d)),
25 => Infer(rustc_serialize::Decodable::decode(d)),
26 => Error(rustc_serialize::Decodable::decode(d)),
_ => panic!( _ => panic!(
"{}", "{}",
format!( format!(

View file

@ -17,7 +17,7 @@ use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_serialize::{ use rustc_serialize::{
opaque::{Decoder, FileEncoder}, opaque::{FileEncoder, MemDecoder},
Decodable, Encodable, Decodable, Encodable,
}; };
use rustc_session::getopts; use rustc_session::getopts;
@ -314,8 +314,8 @@ pub(crate) fn run(
// Save output to provided path // Save output to provided path
let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?; let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?;
calls.encode(&mut encoder).map_err(|e| e.to_string())?; calls.encode(&mut encoder);
encoder.flush().map_err(|e| e.to_string())?; encoder.finish().map_err(|e| e.to_string())?;
Ok(()) Ok(())
}; };
@ -336,7 +336,7 @@ pub(crate) fn load_call_locations(
let mut all_calls: AllCallLocations = FxHashMap::default(); let mut all_calls: AllCallLocations = FxHashMap::default();
for path in with_examples { for path in with_examples {
let bytes = fs::read(&path).map_err(|e| format!("{} (for path {})", e, path))?; let bytes = fs::read(&path).map_err(|e| format!("{} (for path {})", e, path))?;
let mut decoder = Decoder::new(&bytes, 0); let mut decoder = MemDecoder::new(&bytes, 0);
let calls = AllCallLocations::decode(&mut decoder); let calls = AllCallLocations::decode(&mut decoder);
for (function, fn_calls) in calls.into_iter() { for (function, fn_calls) in calls.into_iter() {

View file

@ -7,8 +7,8 @@ extern crate rustc_macros;
extern crate rustc_serialize; extern crate rustc_serialize;
use rustc_macros::{Decodable, Encodable}; use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque; use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::{Decodable, Encodable, Encoder};
#[derive(Encodable, Decodable)] #[derive(Encodable, Decodable)]
struct A { struct A {
@ -17,9 +17,13 @@ struct A {
fn main() { fn main() {
let obj = A { foo: Box::new([true, false]) }; let obj = A { foo: Box::new([true, false]) };
let mut encoder = opaque::Encoder::new(vec![]);
obj.encode(&mut encoder).unwrap(); let mut encoder = MemEncoder::new();
let mut decoder = opaque::Decoder::new(&encoder.data, 0); obj.encode(&mut encoder);
let data = encoder.finish();
let mut decoder = MemDecoder::new(&data, 0);
let obj2 = A::decode(&mut decoder); let obj2 = A::decode(&mut decoder);
assert_eq!(obj.foo, obj2.foo); assert_eq!(obj.foo, obj2.foo);
} }

View file

@ -9,8 +9,8 @@ extern crate rustc_macros;
extern crate rustc_serialize; extern crate rustc_serialize;
use rustc_macros::{Decodable, Encodable}; use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque; use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::{Decodable, Encodable, Encoder};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
#[derive(Encodable, Decodable)] #[derive(Encodable, Decodable)]
@ -26,10 +26,14 @@ struct B {
fn main() { fn main() {
let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) }; let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
let mut encoder = opaque::Encoder::new(vec![]);
obj.encode(&mut encoder).unwrap(); let mut encoder = MemEncoder::new();
let mut decoder = opaque::Decoder::new(&encoder.data, 0); obj.encode(&mut encoder);
let data = encoder.finish();
let mut decoder = MemDecoder::new(&data, 0);
let obj2 = B::decode(&mut decoder); let obj2 = B::decode(&mut decoder);
assert_eq!(obj.foo.get(), obj2.foo.get()); assert_eq!(obj.foo.get(), obj2.foo.get());
assert_eq!(obj.bar.borrow().baz, obj2.bar.borrow().baz); assert_eq!(obj.bar.borrow().baz, obj2.bar.borrow().baz);
} }

View file

@ -75,6 +75,7 @@ enum WireProtocol {
fn encode_json<T: for<'a> Encodable<JsonEncoder<'a>>>(val: &T, wr: &mut Cursor<Vec<u8>>) { fn encode_json<T: for<'a> Encodable<JsonEncoder<'a>>>(val: &T, wr: &mut Cursor<Vec<u8>>) {
write!(wr, "{}", as_json(val)); write!(wr, "{}", as_json(val));
} }
fn encode_opaque<T: Encodable<OpaqueEncoder>>(val: &T, wr: Vec<u8>) { fn encode_opaque<T: Encodable<OpaqueEncoder>>(val: &T, wr: Vec<u8>) {
let mut encoder = OpaqueEncoder(wr); let mut encoder = OpaqueEncoder(wr);
val.encode(&mut encoder); val.encode(&mut encoder);

View file

@ -8,17 +8,21 @@ extern crate rustc_macros;
extern crate rustc_serialize; extern crate rustc_serialize;
use rustc_macros::{Decodable, Encodable}; use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque; use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::{Decodable, Encodable}; use rustc_serialize::{Decodable, Encodable, Encoder};
#[derive(Encodable, Decodable, PartialEq, Debug)] #[derive(Encodable, Decodable, PartialEq, Debug)]
struct UnitLikeStruct; struct UnitLikeStruct;
pub fn main() { pub fn main() {
let obj = UnitLikeStruct; let obj = UnitLikeStruct;
let mut encoder = opaque::Encoder::new(vec![]);
obj.encode(&mut encoder).unwrap(); let mut encoder = MemEncoder::new();
let mut decoder = opaque::Decoder::new(&encoder.data, 0); obj.encode(&mut encoder);
let data = encoder.finish();
let mut decoder = MemDecoder::new(&data, 0);
let obj2 = UnitLikeStruct::decode(&mut decoder); let obj2 = UnitLikeStruct::decode(&mut decoder);
assert_eq!(obj, obj2); assert_eq!(obj, obj2);
} }