Skip to content

Commit 1acbe75

Browse files
committed
Use delayed error handling for Encodable and Encoder infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and `opaque::FileEncoder`. The former encodes into memory and is infallible, the latter writes to file and is fallible. Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a bit verbose and has non-trivial cost, which is annoying given how rare failures are (especially in the infallible `opaque::Encoder` case). This commit changes how `Encoder` fallibility is handled. All the `emit_*` methods are now infallible. `opaque::Encoder` requires no great changes for this. `opaque::FileEncoder` now implements a delayed error handling strategy. If a failure occurs, it records this via the `res` field, and all subsequent encoding operations are skipped if `res` indicates an error has occurred. Once encoding is complete, the new `finish` method is called, which returns a `Result`. In other words, there is now a single `Result`-producing method instead of many of them. This has very little effect on how any file errors are reported if `opaque::FileEncoder` has any failures. Much of this commit is boring mechanical changes, removing `Result` return values and `?` or `unwrap` from expressions. The more interesting parts are as follows. - serialize.rs: The `Encoder` trait gains an `Ok` associated type. The `into_inner` method is changed into `finish`, which returns `Result<Vec<u8>, !>`. - opaque.rs: The `FileEncoder` adopts the delayed error handling strategy. Its `Ok` type is a `usize`, returning the number of bytes written, replacing previous uses of `FileEncoder::position`. - Various methods that take an encoder now consume it, rather than being passed a mutable reference, e.g. `serialize_query_result_cache`.
1 parent 582b9cb commit 1acbe75

File tree

45 files changed

+610
-681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+610
-681
lines changed

compiler/rustc_ast/src/ast.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -2473,9 +2473,7 @@ rustc_index::newtype_index! {
24732473
}
24742474

24752475
impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId {
2476-
fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
2477-
Ok(())
2478-
}
2476+
fn encode(&self, _s: &mut S) {}
24792477
}
24802478

24812479
impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {

compiler/rustc_ast/src/ptr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ impl<D: Decoder, T: 'static + Decodable<D>> Decodable<D> for P<T> {
121121
}
122122

123123
impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
124-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
125-
(**self).encode(s)
124+
fn encode(&self, s: &mut S) {
125+
(**self).encode(s);
126126
}
127127
}
128128

@@ -191,8 +191,8 @@ impl<'a, T> IntoIterator for &'a P<[T]> {
191191
}
192192

193193
impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> {
194-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
195-
Encodable::encode(&**self, s)
194+
fn encode(&self, s: &mut S) {
195+
Encodable::encode(&**self, s);
196196
}
197197
}
198198

compiler/rustc_ast/src/tokenstream.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ impl fmt::Debug for LazyTokenStream {
142142
}
143143

144144
impl<S: Encoder> Encodable<S> for LazyTokenStream {
145-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
145+
fn encode(&self, s: &mut S) {
146146
// Used by AST json printing.
147-
Encodable::encode(&self.create_token_stream(), s)
147+
Encodable::encode(&self.create_token_stream(), s);
148148
}
149149
}
150150

compiler/rustc_codegen_ssa/src/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_middle::dep_graph::WorkProduct;
2929
use rustc_middle::middle::dependency_format::Dependencies;
3030
use rustc_middle::middle::exported_symbols::SymbolExportKind;
3131
use rustc_middle::ty::query::{ExternProviders, Providers};
32-
use rustc_serialize::{opaque, Decodable, Decoder, Encoder};
32+
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
3333
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
3434
use rustc_session::cstore::{self, CrateSource};
3535
use rustc_session::utils::NativeLibKind;
@@ -204,13 +204,13 @@ const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
204204
impl CodegenResults {
205205
pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
206206
let mut encoder = opaque::Encoder::new();
207-
encoder.emit_raw_bytes(RLINK_MAGIC).unwrap();
207+
encoder.emit_raw_bytes(RLINK_MAGIC);
208208
// `emit_raw_bytes` is used to make sure that the version representation does not depend on
209209
// Encoder's inner representation of `u32`.
210-
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()).unwrap();
211-
encoder.emit_str(RUSTC_VERSION.unwrap()).unwrap();
212-
rustc_serialize::Encodable::encode(codegen_results, &mut encoder).unwrap();
213-
encoder.into_inner()
210+
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
211+
encoder.emit_str(RUSTC_VERSION.unwrap());
212+
Encodable::encode(codegen_results, &mut encoder);
213+
encoder.finish().unwrap()
214214
}
215215

216216
pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> {

compiler/rustc_data_structures/src/fingerprint.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,8 @@ impl_stable_hash_via_hash!(Fingerprint);
144144

145145
impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
146146
#[inline]
147-
fn encode(&self, s: &mut E) -> Result<(), E::Error> {
148-
s.emit_raw_bytes(&self.to_le_bytes())?;
149-
Ok(())
147+
fn encode(&self, s: &mut E) {
148+
s.emit_raw_bytes(&self.to_le_bytes());
150149
}
151150
}
152151

@@ -187,10 +186,10 @@ impl std::fmt::Display for PackedFingerprint {
187186

188187
impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint {
189188
#[inline]
190-
fn encode(&self, s: &mut E) -> Result<(), E::Error> {
189+
fn encode(&self, s: &mut E) {
191190
// Copy to avoid taking reference to packed field.
192191
let copy = self.0;
193-
copy.encode(s)
192+
copy.encode(s);
194193
}
195194
}
196195

compiler/rustc_data_structures/src/svh.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ impl fmt::Display for Svh {
4949
}
5050

5151
impl<S: Encoder> Encodable<S> for Svh {
52-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
53-
s.emit_u64(self.as_u64().to_le())
52+
fn encode(&self, s: &mut S) {
53+
s.emit_u64(self.as_u64().to_le());
5454
}
5555
}
5656

compiler/rustc_incremental/src/persist/file_format.rs

+20-29
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,20 @@ const HEADER_FORMAT_VERSION: u16 = 0;
3030
/// the Git commit hash.
3131
const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
3232

33-
pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
34-
stream.emit_raw_bytes(FILE_MAGIC)?;
35-
stream.emit_raw_bytes(&[
36-
(HEADER_FORMAT_VERSION >> 0) as u8,
37-
(HEADER_FORMAT_VERSION >> 8) as u8,
38-
])?;
33+
pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) {
34+
stream.emit_raw_bytes(FILE_MAGIC);
35+
stream
36+
.emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
3937

4038
let rustc_version = rustc_version(nightly_build);
4139
assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
42-
stream.emit_raw_bytes(&[rustc_version.len() as u8])?;
43-
stream.emit_raw_bytes(rustc_version.as_bytes())
40+
stream.emit_raw_bytes(&[rustc_version.len() as u8]);
41+
stream.emit_raw_bytes(rustc_version.as_bytes());
4442
}
4543

4644
pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
4745
where
48-
F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
46+
F: FnOnce(FileEncoder) -> FileEncodeResult,
4947
{
5048
debug!("save: storing data in {}", path_buf.display());
5149

@@ -80,28 +78,21 @@ where
8078
}
8179
};
8280

83-
if let Err(err) = write_file_header(&mut encoder, sess.is_nightly_build()) {
84-
sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
85-
return;
86-
}
87-
88-
if let Err(err) = encode(&mut encoder) {
89-
sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
90-
return;
91-
}
81+
write_file_header(&mut encoder, sess.is_nightly_build());
9282

93-
if let Err(err) = encoder.flush() {
94-
sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
95-
return;
83+
match encode(encoder) {
84+
Ok(position) => {
85+
sess.prof.artifact_size(
86+
&name.replace(' ', "_"),
87+
path_buf.file_name().unwrap().to_string_lossy(),
88+
position as u64,
89+
);
90+
debug!("save: data written to disk successfully");
91+
}
92+
Err(err) => {
93+
sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
94+
}
9695
}
97-
98-
sess.prof.artifact_size(
99-
&name.replace(' ', "_"),
100-
path_buf.file_name().unwrap().to_string_lossy(),
101-
encoder.position() as u64,
102-
);
103-
104-
debug!("save: data written to disk successfully");
10596
}
10697

10798
/// Reads the contents of a file with a file header as defined in this module.

compiler/rustc_incremental/src/persist/save.rs

+8-21
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_data_structures::sync::join;
33
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
44
use rustc_middle::ty::TyCtxt;
55
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
6-
use rustc_serialize::Encodable as RustcEncodable;
6+
use rustc_serialize::{Encodable as RustcEncodable, Encoder};
77
use rustc_session::Session;
88
use std::fs;
99

@@ -96,8 +96,9 @@ pub fn save_work_product_index(
9696
debug!("save_work_product_index()");
9797
dep_graph.assert_ignored();
9898
let path = work_products_path(sess);
99-
file_format::save_in(sess, path, "work product index", |e| {
100-
encode_work_product_index(&new_work_products, e)
99+
file_format::save_in(sess, path, "work product index", |mut e| {
100+
encode_work_product_index(&new_work_products, &mut e);
101+
e.finish()
101102
});
102103

103104
// 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(
123124
fn encode_work_product_index(
124125
work_products: &FxHashMap<WorkProductId, WorkProduct>,
125126
encoder: &mut FileEncoder,
126-
) -> FileEncodeResult {
127+
) {
127128
let serialized_products: Vec<_> = work_products
128129
.iter()
129130
.map(|(id, work_product)| SerializedWorkProduct {
@@ -135,7 +136,7 @@ fn encode_work_product_index(
135136
serialized_products.encode(encoder)
136137
}
137138

138-
fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult {
139+
fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
139140
tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder))
140141
}
141142

@@ -170,24 +171,10 @@ pub fn build_dep_graph(
170171
}
171172
};
172173

173-
if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) {
174-
sess.err(&format!(
175-
"failed to write dependency graph header to `{}`: {}",
176-
path_buf.display(),
177-
err
178-
));
179-
return None;
180-
}
174+
file_format::write_file_header(&mut encoder, sess.is_nightly_build());
181175

182176
// First encode the commandline arguments hash
183-
if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) {
184-
sess.err(&format!(
185-
"failed to write dependency graph hash `{}`: {}",
186-
path_buf.display(),
187-
err
188-
));
189-
return None;
190-
}
177+
sess.opts.dep_tracking_hash(false).encode(&mut encoder);
191178

192179
Some(DepGraph::new(
193180
&sess.prof,

compiler/rustc_index/src/vec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ pub struct IndexVec<I: Idx, T> {
6060
unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
6161

6262
impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
63-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
64-
Encodable::encode(&self.raw, s)
63+
fn encode(&self, s: &mut S) {
64+
Encodable::encode(&self.raw, s);
6565
}
6666
}
6767

compiler/rustc_macros/src/newtype.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ impl Parse for Newtype {
137137
}
138138
}
139139
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
140-
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
141-
e.emit_u32(self.private)
140+
fn encode(&self, e: &mut E) {
141+
e.emit_u32(self.private);
142142
}
143143
}
144144
}

compiler/rustc_macros/src/serialize.rs

+7-15
Original file line numberDiff line numberDiff line change
@@ -146,21 +146,17 @@ fn encodable_body(
146146
.map(|binding| {
147147
let bind_ident = &binding.binding;
148148
let result = quote! {
149-
match ::rustc_serialize::Encodable::<#encoder_ty>::encode(
149+
::rustc_serialize::Encodable::<#encoder_ty>::encode(
150150
#bind_ident,
151151
__encoder,
152-
) {
153-
::std::result::Result::Ok(()) => (),
154-
::std::result::Result::Err(__err)
155-
=> return ::std::result::Result::Err(__err),
156-
}
152+
);
157153
};
158154
result
159155
})
160156
.collect::<TokenStream>()
161157
});
162158
quote! {
163-
::std::result::Result::Ok(match *self { #encode_inner })
159+
match *self { #encode_inner }
164160
}
165161
}
166162
_ => {
@@ -172,14 +168,10 @@ fn encodable_body(
172168
.map(|binding| {
173169
let bind_ident = &binding.binding;
174170
let result = quote! {
175-
match ::rustc_serialize::Encodable::<#encoder_ty>::encode(
171+
::rustc_serialize::Encodable::<#encoder_ty>::encode(
176172
#bind_ident,
177173
__encoder,
178-
) {
179-
::std::result::Result::Ok(()) => (),
180-
::std::result::Result::Err(__err)
181-
=> return ::std::result::Result::Err(__err),
182-
}
174+
);
183175
};
184176
result
185177
})
@@ -190,7 +182,7 @@ fn encodable_body(
190182
::rustc_serialize::Encoder::emit_enum_variant(
191183
__encoder,
192184
#variant_idx,
193-
|__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
185+
|__encoder| { #encode_fields }
194186
)
195187
}
196188
} else {
@@ -223,7 +215,7 @@ fn encodable_body(
223215
fn encode(
224216
&self,
225217
__encoder: &mut #encoder_ty,
226-
) -> ::std::result::Result<(), <#encoder_ty as ::rustc_serialize::Encoder>::Error> {
218+
) {
227219
#lints
228220
#encode_body
229221
}

compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::rmeta::MetadataBlob;
44
use rustc_data_structures::owning_ref::OwningRef;
55
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
66
use rustc_middle::parameterized_over_tcx;
7-
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
7+
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
88
use rustc_span::def_id::{DefIndex, DefPathHash};
99

1010
pub(crate) enum DefPathHashMapRef<'tcx> {
@@ -29,12 +29,12 @@ impl DefPathHashMapRef<'_> {
2929
}
3030

3131
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> {
32-
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
32+
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
3333
match *self {
3434
DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => {
3535
let bytes = def_path_hash_map.raw_bytes();
36-
e.emit_usize(bytes.len())?;
37-
e.emit_raw_bytes(bytes)
36+
e.emit_usize(bytes.len());
37+
e.emit_raw_bytes(bytes);
3838
}
3939
DefPathHashMapRef::OwnedFromMetadata(_) => {
4040
panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization")

0 commit comments

Comments
 (0)