about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2022-06-07 13:30:45 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2022-06-08 07:01:26 +1000
commit1acbe7573dc32f917f51a784a36b7afc690900e3 (patch)
tree1b4e8d414de3d349bd3ae038c28e9dc77e54c345 /compiler
parent582b9cbc45334a73467d6ccaf0a8b9de559c2011 (diff)
downloadrust-1acbe7573dc32f917f51a784a36b7afc690900e3.tar.gz
rust-1acbe7573dc32f917f51a784a36b7afc690900e3.zip
Use delayed error handling for `Encodable` and `Encoder` infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and
`opaque::FileEncoder`. The former encodes into memory and is infallible, the
latter writes to file and is fallible.

Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a
bit verbose and has non-trivial cost, which is annoying given how rare failures
are (especially in the infallible `opaque::Encoder` case).

This commit changes how `Encoder` fallibility is handled. All the `emit_*`
methods are now infallible. `opaque::Encoder` requires no great changes for
this. `opaque::FileEncoder` now implements a delayed error handling strategy.
If a failure occurs, it records this via the `res` field, and all subsequent
encoding operations are skipped if `res` indicates an error has occurred. Once
encoding is complete, the new `finish` method is called, which returns a
`Result`. In other words, there is now a single `Result`-producing method
instead of many of them.

This has very little effect on how any file errors are reported if
`opaque::FileEncoder` has any failures.

Much of this commit is boring mechanical changes, removing `Result` return
values and `?` or `unwrap` from expressions. The more interesting parts are as
follows.
- serialize.rs: The `Encoder` trait gains an `Ok` associated type. The
  `into_inner` method is changed into `finish`, which returns
  `Result<Vec<u8>, !>`.
- opaque.rs: The `FileEncoder` adopts the delayed error handling
  strategy. Its `Ok` type is a `usize`, returning the number of bytes
  written, replacing previous uses of `FileEncoder::position`.
- Various methods that take an encoder now consume it, rather than being
  passed a mutable reference, e.g. `serialize_query_result_cache`.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast/src/ptr.rs8
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs12
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs9
-rw-r--r--compiler/rustc_data_structures/src/svh.rs4
-rw-r--r--compiler/rustc_incremental/src/persist/file_format.rs49
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs29
-rw-r--r--compiler/rustc_index/src/vec.rs4
-rw-r--r--compiler/rustc_macros/src/newtype.rs4
-rw-r--r--compiler/rustc_macros/src/serialize.rs22
-rw-r--r--compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs98
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs2
-rw-r--r--compiler/rustc_middle/src/mir/graph_cyclic_cache.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs15
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs8
-rw-r--r--compiler/rustc_middle/src/mir/predecessors.rs4
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs4
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs4
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs47
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs6
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/list.rs4
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs2
-rw-r--r--compiler/rustc_query_impl/src/lib.rs1
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs151
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs6
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs25
-rw-r--r--compiler/rustc_serialize/src/collection_impls.rs74
-rw-r--r--compiler/rustc_serialize/src/opaque.rs240
-rw-r--r--compiler/rustc_serialize/src/serialize.rs156
-rw-r--r--compiler/rustc_serialize/tests/opaque.rs7
-rw-r--r--compiler/rustc_span/src/def_id.rs16
-rw-r--r--compiler/rustc_span/src/hygiene.rs47
-rw-r--r--compiler/rustc_span/src/lib.rs52
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_type_ir/src/codec.rs5
-rw-r--r--compiler/rustc_type_ir/src/sty.rs101
40 files changed, 582 insertions, 666 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index b64f7b8ad1b..9e6a186219b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2473,9 +2473,7 @@ rustc_index::newtype_index! {
 }
 
 impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId {
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        Ok(())
-    }
+    fn encode(&self, _s: &mut S) {}
 }
 
 impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
index bab85a3019d..30481eddf91 100644
--- a/compiler/rustc_ast/src/ptr.rs
+++ b/compiler/rustc_ast/src/ptr.rs
@@ -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> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
+    fn encode(&self, s: &mut 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]> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        Encodable::encode(&**self, s)
+    fn encode(&self, s: &mut S) {
+        Encodable::encode(&**self, s);
     }
 }
 
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index c58fe7287bf..84d8829c398 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -142,9 +142,9 @@ impl fmt::Debug 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.
-        Encodable::encode(&self.create_token_stream(), s)
+        Encodable::encode(&self.create_token_stream(), s);
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index cc7efaac893..771157dcad9 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -29,7 +29,7 @@ use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::ty::query::{ExternProviders, Providers};
-use rustc_serialize::{opaque, Decodable, Decoder, Encoder};
+use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::utils::NativeLibKind;
@@ -204,13 +204,13 @@ const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 impl CodegenResults {
     pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
         let mut encoder = opaque::Encoder::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
         // Encoder's inner representation of `u32`.
-        encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()).unwrap();
-        encoder.emit_str(RUSTC_VERSION.unwrap()).unwrap();
-        rustc_serialize::Encodable::encode(codegen_results, &mut encoder).unwrap();
-        encoder.into_inner()
+        encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
+        encoder.emit_str(RUSTC_VERSION.unwrap());
+        Encodable::encode(codegen_results, &mut encoder);
+        encoder.finish().unwrap()
     }
 
     pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> {
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index c88f3e73cff..a032b039f34 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -144,9 +144,8 @@ impl_stable_hash_via_hash!(Fingerprint);
 
 impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
     #[inline]
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_raw_bytes(&self.to_le_bytes())?;
-        Ok(())
+    fn encode(&self, s: &mut E) {
+        s.emit_raw_bytes(&self.to_le_bytes());
     }
 }
 
@@ -187,10 +186,10 @@ impl std::fmt::Display for PackedFingerprint {
 
 impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint {
     #[inline]
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut E) {
         // Copy to avoid taking reference to packed field.
         let copy = self.0;
-        copy.encode(s)
+        copy.encode(s);
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs
index 12ef286091c..61654b9e8f5 100644
--- a/compiler/rustc_data_structures/src/svh.rs
+++ b/compiler/rustc_data_structures/src/svh.rs
@@ -49,8 +49,8 @@ impl fmt::Display for Svh {
 }
 
 impl<S: Encoder> Encodable<S> for Svh {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u64(self.as_u64().to_le())
+    fn encode(&self, s: &mut S) {
+        s.emit_u64(self.as_u64().to_le());
     }
 }
 
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index 68180a2214a..2dbd4b6bce8 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -30,22 +30,20 @@ const HEADER_FORMAT_VERSION: u16 = 0;
 /// the Git commit hash.
 const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 
-pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
-    stream.emit_raw_bytes(FILE_MAGIC)?;
-    stream.emit_raw_bytes(&[
-        (HEADER_FORMAT_VERSION >> 0) as u8,
-        (HEADER_FORMAT_VERSION >> 8) as u8,
-    ])?;
+pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) {
+    stream.emit_raw_bytes(FILE_MAGIC);
+    stream
+        .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
 
     let rustc_version = rustc_version(nightly_build);
     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.as_bytes())
+    stream.emit_raw_bytes(&[rustc_version.len() as u8]);
+    stream.emit_raw_bytes(rustc_version.as_bytes());
 }
 
 pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
 where
-    F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
+    F: FnOnce(FileEncoder) -> FileEncodeResult,
 {
     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()) {
-        sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
-        return;
-    }
-
-    if let Err(err) = encode(&mut encoder) {
-        sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
-        return;
-    }
+    write_file_header(&mut encoder, sess.is_nightly_build());
 
-    if let Err(err) = encoder.flush() {
-        sess.err(&format!("failed to flush {} 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));
+        }
     }
-
-    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.
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 0223976b08a..9341a742925 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::sync::join;
 use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
 use rustc_middle::ty::TyCtxt;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
-use rustc_serialize::Encodable as RustcEncodable;
+use rustc_serialize::{Encodable as RustcEncodable, Encoder};
 use rustc_session::Session;
 use std::fs;
 
@@ -96,8 +96,9 @@ pub fn save_work_product_index(
     debug!("save_work_product_index()");
     dep_graph.assert_ignored();
     let path = work_products_path(sess);
-    file_format::save_in(sess, path, "work product index", |e| {
-        encode_work_product_index(&new_work_products, e)
+    file_format::save_in(sess, path, "work product index", |mut 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
@@ -123,7 +124,7 @@ pub fn save_work_product_index(
 fn encode_work_product_index(
     work_products: &FxHashMap<WorkProductId, WorkProduct>,
     encoder: &mut FileEncoder,
-) -> FileEncodeResult {
+) {
     let serialized_products: Vec<_> = work_products
         .iter()
         .map(|(id, work_product)| SerializedWorkProduct {
@@ -135,7 +136,7 @@ fn encode_work_product_index(
     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))
 }
 
@@ -170,24 +171,10 @@ pub fn build_dep_graph(
         }
     };
 
-    if let Err(err) = 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;
-    }
+    file_format::write_file_header(&mut encoder, sess.is_nightly_build());
 
     // First encode the commandline arguments hash
-    if let Err(err) = sess.opts.dep_tracking_hash(false).encode(&mut encoder) {
-        sess.err(&format!(
-            "failed to write dependency graph hash `{}`: {}",
-            path_buf.display(),
-            err
-        ));
-        return None;
-    }
+    sess.opts.dep_tracking_hash(false).encode(&mut encoder);
 
     Some(DepGraph::new(
         &sess.prof,
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index a8c611e18ff..1a55519d7b1 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -60,8 +60,8 @@ pub struct IndexVec<I: Idx, T> {
 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> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        Encodable::encode(&self.raw, s)
+    fn encode(&self, s: &mut S) {
+        Encodable::encode(&self.raw, s);
     }
 }
 
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index c8b31cd0c4d..0a77b734c76 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -137,8 +137,8 @@ impl Parse for Newtype {
                     }
                 }
                 impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
-                    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-                        e.emit_u32(self.private)
+                    fn encode(&self, e: &mut E) {
+                        e.emit_u32(self.private);
                     }
                 }
             }
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index e99fa6c113b..82e6972d027 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -146,21 +146,17 @@ fn encodable_body(
                     .map(|binding| {
                         let bind_ident = &binding.binding;
                         let result = quote! {
-                            match ::rustc_serialize::Encodable::<#encoder_ty>::encode(
+                            ::rustc_serialize::Encodable::<#encoder_ty>::encode(
                                 #bind_ident,
                                 __encoder,
-                            ) {
-                                ::std::result::Result::Ok(()) => (),
-                                ::std::result::Result::Err(__err)
-                                    => return ::std::result::Result::Err(__err),
-                            }
+                            );
                         };
                         result
                     })
                     .collect::<TokenStream>()
             });
             quote! {
-                ::std::result::Result::Ok(match *self { #encode_inner })
+                match *self { #encode_inner }
             }
         }
         _ => {
@@ -172,14 +168,10 @@ fn encodable_body(
                     .map(|binding| {
                         let bind_ident = &binding.binding;
                         let result = quote! {
-                            match ::rustc_serialize::Encodable::<#encoder_ty>::encode(
+                            ::rustc_serialize::Encodable::<#encoder_ty>::encode(
                                 #bind_ident,
                                 __encoder,
-                            ) {
-                                ::std::result::Result::Ok(()) => (),
-                                ::std::result::Result::Err(__err)
-                                    => return ::std::result::Result::Err(__err),
-                            }
+                            );
                         };
                         result
                     })
@@ -190,7 +182,7 @@ fn encodable_body(
                         ::rustc_serialize::Encoder::emit_enum_variant(
                             __encoder,
                             #variant_idx,
-                            |__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
+                            |__encoder| { #encode_fields }
                         )
                     }
                 } else {
@@ -223,7 +215,7 @@ fn encodable_body(
             fn encode(
                 &self,
                 __encoder: &mut #encoder_ty,
-            ) -> ::std::result::Result<(), <#encoder_ty as ::rustc_serialize::Encoder>::Error> {
+            ) {
                 #lints
                 #encode_body
             }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 15fd190b049..40c94b372bb 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -4,7 +4,7 @@ use crate::rmeta::MetadataBlob;
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
 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};
 
 pub(crate) enum DefPathHashMapRef<'tcx> {
@@ -29,12 +29,12 @@ impl DefPathHashMapRef<'_> {
 }
 
 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 {
             DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => {
                 let bytes = def_path_hash_map.raw_bytes();
-                e.emit_usize(bytes.len())?;
-                e.emit_raw_bytes(bytes)
+                e.emit_usize(bytes.len());
+                e.emit_raw_bytes(bytes);
             }
             DefPathHashMapRef::OwnedFromMetadata(_) => {
                 panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization")
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 2b606018f86..3285273ba90 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -86,14 +86,15 @@ macro_rules! empty_proc_macro {
 
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
-        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
+        $(fn $name(&mut self, value: $ty) {
             self.opaque.$name(value)
         })*
     }
 }
 
 impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
-    type Error = <opaque::Encoder as Encoder>::Error;
+    type Ok = <opaque::Encoder as Encoder>::Ok;
+    type Err = <opaque::Encoder as Encoder>::Err;
 
     encoder_methods! {
         emit_usize(usize);
@@ -117,60 +118,63 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
         emit_str(&str);
         emit_raw_bytes(&[u8]);
     }
+
+    fn finish(self) -> Result<Self::Ok, Self::Err> {
+        self.opaque.finish()
+    }
 }
 
 impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
-    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        e.emit_lazy_distance(self.position)
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
+        e.emit_lazy_distance(self.position);
     }
 }
 
 impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
-    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        e.emit_usize(self.num_elems)?;
-        if self.num_elems == 0 {
-            return Ok(());
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
+        e.emit_usize(self.num_elems);
+        if self.num_elems > 0 {
+            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> {
-    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        e.emit_usize(self.encoded_size)?;
-        e.emit_lazy_distance(self.position)
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
+        e.emit_usize(self.encoded_size);
+        e.emit_lazy_distance(self.position);
     }
 }
 
 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 {
             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 {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        s.emit_u32(self.as_u32())
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+        s.emit_u32(self.as_u32());
     }
 }
 
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        s.emit_u32(self.as_u32())
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+        s.emit_u32(self.as_u32());
     }
 }
 
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
-        rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+        rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s);
     }
 }
 
 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 {
             // We will only write details for local expansions.  Non-local expansions will fetch
             // data from the corresponding crate's metadata.
@@ -178,13 +182,13 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
             // metadata from proc-macro crates.
             s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
         }
-        self.krate.encode(s)?;
-        self.local_id.encode(s)
+        self.krate.encode(s);
+        self.local_id.encode(s);
     }
 }
 
 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();
 
         // Don't serialize any `SyntaxContext`s from a proc-macro crate,
@@ -219,9 +223,9 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
         // `rustc_span::hygiene::raw_encode_expn_id` to handle
         // encoding `ExpnData` for proc-macro crates.
         if s.is_proc_macro {
-            SyntaxContext::root().encode(s)?;
+            SyntaxContext::root().encode(s);
         } else {
-            span.ctxt.encode(s)?;
+            span.ctxt.encode(s);
         }
 
         if self.is_dummy() {
@@ -289,22 +293,20 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
             (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
         };
 
-        tag.encode(s)?;
-        lo.encode(s)?;
+        tag.encode(s);
+        lo.encode(s);
 
         // Encode length which is usually less than span.hi and profits more
         // from the variable-length integer encoding that we use.
         let len = hi - lo;
-        len.encode(s)?;
+        len.encode(s);
 
         if tag == TAG_VALID_SPAN_FOREIGN {
             // This needs to be two lines to avoid holding the `s.source_file_cache`
             // while calling `cnum.encode(s)`
             let cnum = s.source_file_cache.0.cnum;
-            cnum.encode(s)?;
+            cnum.encode(s);
         }
-
-        Ok(())
     }
 }
 
@@ -325,13 +327,10 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
         &mut self.predicate_shorthands
     }
 
-    fn encode_alloc_id(
-        &mut self,
-        alloc_id: &rustc_middle::mir::interpret::AllocId,
-    ) -> Result<(), Self::Error> {
+    fn encode_alloc_id(&mut self, alloc_id: &rustc_middle::mir::interpret::AllocId) {
         let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
 
-        index.encode(self)
+        index.encode(self);
     }
 }
 
@@ -360,10 +359,7 @@ macro_rules! record_array {
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn emit_lazy_distance(
-        &mut self,
-        position: NonZeroUsize,
-    ) -> Result<(), <Self as Encoder>::Error> {
+    fn emit_lazy_distance(&mut self, position: NonZeroUsize) {
         let pos = position.get();
         let distance = match self.lazy_state {
             LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
@@ -382,7 +378,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
         };
         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>
@@ -393,7 +389,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         assert_eq!(self.lazy_state, LazyState::NoNode);
         self.lazy_state = LazyState::NodeStart(pos);
-        value.borrow().encode(self).unwrap();
+        value.borrow().encode(self);
         self.lazy_state = LazyState::NoNode;
 
         assert!(pos.get() <= self.position());
@@ -412,7 +408,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         assert_eq!(self.lazy_state, LazyState::NoNode);
         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;
 
         assert!(pos.get() <= self.position());
@@ -615,7 +611,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     let id = self.interpret_allocs[idx];
                     let pos = self.position() as u32;
                     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;
             }
@@ -1640,18 +1636,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let mut expn_data_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),
             |(this, syntax_contexts, _, _), index, ctxt_data| {
                 syntax_contexts.set(index, this.lazy(ctxt_data));
-                Ok(())
             },
             |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
                 if let Some(index) = index.as_local() {
                     expn_data_table.set(index.as_raw(), this.lazy(expn_data));
                     expn_hash_table.set(index.as_raw(), this.lazy(hash));
                 }
-                Ok(())
             },
         );
 
@@ -2195,10 +2189,10 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
 
 fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
     let mut encoder = opaque::Encoder::new();
-    encoder.emit_raw_bytes(METADATA_HEADER).unwrap();
+    encoder.emit_raw_bytes(METADATA_HEADER);
 
     // 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_file_cache = (source_map_files[0].clone(), 0);
@@ -2223,13 +2217,13 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
     };
 
     // 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,
     // culminating in the `CrateRoot` which points to all of it.
     let root = ecx.encode_crate_root();
 
-    let mut result = ecx.opaque.into_inner();
+    let mut result = ecx.opaque.finish().unwrap();
 
     // Encode the root position.
     let header = METADATA_HEADER.len();
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 100bac15b80..8baa67a8f9f 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -287,7 +287,7 @@ where
     {
         let pos = buf.position();
         for block in &self.blocks {
-            buf.emit_raw_bytes(block).unwrap();
+            buf.emit_raw_bytes(block);
         }
         let num_bytes = self.blocks.len() * N;
         LazyTable::from_position_and_encoded_size(
diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
index e2f3d6e078f..096bf8cbc15 100644
--- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
+++ b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
@@ -38,8 +38,8 @@ impl GraphIsCyclicCache {
 
 impl<S: serialize::Encoder> serialize::Encodable<S> for GraphIsCyclicCache {
     #[inline]
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        serialize::Encodable::encode(&(), s)
+    fn encode(&self, s: &mut S) {
+        serialize::Encodable::encode(&(), s);
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 06cd6a66e39..214b919e24d 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -207,27 +207,26 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>(
     encoder: &mut E,
     tcx: TyCtxt<'tcx>,
     alloc_id: AllocId,
-) -> Result<(), E::Error> {
+) {
     match tcx.global_alloc(alloc_id) {
         GlobalAlloc::Memory(alloc) => {
             trace!("encoding {:?} with {:#?}", alloc_id, alloc);
-            AllocDiscriminant::Alloc.encode(encoder)?;
-            alloc.encode(encoder)?;
+            AllocDiscriminant::Alloc.encode(encoder);
+            alloc.encode(encoder);
         }
         GlobalAlloc::Function(fn_instance) => {
             trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
-            AllocDiscriminant::Fn.encode(encoder)?;
-            fn_instance.encode(encoder)?;
+            AllocDiscriminant::Fn.encode(encoder);
+            fn_instance.encode(encoder);
         }
         GlobalAlloc::Static(did) => {
             assert!(!tcx.is_thread_local_static(did));
             // References to statics doesn't need to know about their allocations,
             // just about its `DefId`.
-            AllocDiscriminant::Static.encode(encoder)?;
-            did.encode(encoder)?;
+            AllocDiscriminant::Static.encode(encoder);
+            did.encode(encoder);
         }
     }
-    Ok(())
 }
 
 // Used to avoid infinite recursion when decoding cyclic allocations.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index f3db359ec33..581b3257c73 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -672,16 +672,16 @@ const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
 
 impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
     #[inline]
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, e: &mut E) {
         if E::CLEAR_CROSS_CRATE {
-            return Ok(());
+            return;
         }
 
         match *self {
             ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
             ClearCrossCrate::Set(ref val) => {
-                TAG_CLEAR_CROSS_CRATE_SET.encode(e)?;
-                val.encode(e)
+                TAG_CLEAR_CROSS_CRATE_SET.encode(e);
+                val.encode(e);
             }
         }
     }
diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs
index 0b9ddaf64d4..9bc0cb1138f 100644
--- a/compiler/rustc_middle/src/mir/predecessors.rs
+++ b/compiler/rustc_middle/src/mir/predecessors.rs
@@ -56,9 +56,7 @@ impl PredecessorCache {
 
 impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache {
     #[inline]
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        Ok(())
-    }
+    fn encode(&self, _s: &mut S) {}
 }
 
 impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache {
diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs
index fbb26800e29..4872a7835e3 100644
--- a/compiler/rustc_middle/src/mir/switch_sources.rs
+++ b/compiler/rustc_middle/src/mir/switch_sources.rs
@@ -56,9 +56,7 @@ impl SwitchSourceCache {
 
 impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache {
     #[inline]
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        Ok(())
-    }
+    fn encode(&self, _s: &mut S) {}
 }
 
 impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache {
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 7e395902ad3..f745e55307a 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -367,9 +367,7 @@ impl PostorderCache {
 
 impl<S: serialize::Encoder> serialize::Encodable<S> for PostorderCache {
     #[inline]
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        Ok(())
-    }
+    fn encode(&self, _s: &mut S) {}
 }
 
 impl<D: serialize::Decoder> serialize::Decodable<D> for PostorderCache {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 1e2d1fbeb4b..9a363914dc3 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -69,11 +69,7 @@ pub trait RefDecodable<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> {
 }
 
 /// Encode the given value or a previously cached shorthand.
-pub fn encode_with_shorthand<'tcx, E, T, M>(
-    encoder: &mut E,
-    value: &T,
-    cache: M,
-) -> Result<(), E::Error>
+pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
 where
     E: TyEncoder<I = TyCtxt<'tcx>>,
     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();
     if let Some(shorthand) = existing_shorthand {
-        return encoder.emit_usize(shorthand);
+        encoder.emit_usize(shorthand);
+        return;
     }
 
     let variant = value.variant();
 
     let start = encoder.position();
-    variant.encode(encoder)?;
+    variant.encode(encoder);
     let len = encoder.position() - start;
 
     // The shorthand encoding uses the same usize as the
@@ -108,57 +105,55 @@ where
     if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
         cache(encoder).insert(*value, shorthand);
     }
-
-    Ok(())
 }
 
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Ty<'tcx> {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        encode_with_shorthand(e, self, TyEncoder::type_shorthands)
+    fn encode(&self, e: &mut E) {
+        encode_with_shorthand(e, self, TyEncoder::type_shorthands);
     }
 }
 
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E>
     for ty::Binder<'tcx, ty::PredicateKind<'tcx>>
 {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        self.bound_vars().encode(e)?;
-        encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands)
+    fn encode(&self, e: &mut E) {
+        self.bound_vars().encode(e);
+        encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands);
     }
 }
 
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        self.kind().encode(e)
+    fn encode(&self, e: &mut E) {
+        self.kind().encode(e);
     }
 }
 
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        self.kind().encode(e)
+    fn encode(&self, e: &mut E) {
+        self.kind().encode(e);
     }
 }
 
 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Const<'tcx> {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        self.0.0.encode(e)
+    fn encode(&self, e: &mut E) {
+        self.0.0.encode(e);
     }
 }
 
 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)
     }
 }
 
 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)
     }
 }
 
 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)
     }
 }
@@ -508,9 +503,9 @@ macro_rules! impl_binder_encode_decode {
     ($($t:ty),+ $(,)?) => {
         $(
             impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Binder<'tcx, $t> {
-                fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-                    self.bound_vars().encode(e)?;
-                    self.as_ref().skip_binder().encode(e)
+                fn encode(&self, e: &mut E) {
+                    self.bound_vars().encode(e);
+                    self.as_ref().skip_binder().encode(e);
                 }
             }
             impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Binder<'tcx, $t> {
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index a3ce674c115..51e51a63fd0 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -140,9 +140,9 @@ impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
 }
 
 impl<S: Encoder> Encodable<S> for ScalarInt {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u128(self.data)?;
-        s.emit_u8(self.size)
+    fn encode(&self, s: &mut S) {
+        s.emit_u128(self.data);
+        s.emit_u8(self.size);
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index e668edad7c4..610234d45ce 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -87,7 +87,7 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
 
     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)]
@@ -1466,8 +1466,8 @@ impl<'tcx> TyCtxt<'tcx> {
         )
     }
 
-    pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult {
-        self.on_disk_cache.as_ref().map_or(Ok(()), |c| c.serialize(self, encoder))
+    pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
+        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
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 3c9e96df59a..db3b5cfd180 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -117,8 +117,8 @@ impl<T: fmt::Debug> fmt::Debug for List<T> {
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
     #[inline]
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s);
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 290485ab5fe..de30387ef4c 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -217,7 +217,7 @@ impl<'tcx> TypeFoldable<'tcx> 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)
     }
 }
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 5e28c229aa5..d06eb97798e 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -2,6 +2,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(min_specialization)]
+#![feature(never_type)]
 #![feature(once_cell)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index e93bf1a4752..c2c876f7f1a 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -221,7 +221,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
         *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.
         tcx.dep_graph.with_ignore(|| {
             // Allocate `SourceFileIndex`es.
@@ -259,27 +259,25 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
             // Encode query results.
             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 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.
             let side_effects_index: EncodedDepNodeIndex = self
                 .current_side_effects
                 .borrow()
                 .iter()
-                .map(
-                    |(dep_node_index, side_effects)| -> Result<_, <FileEncoder as Encoder>::Error> {
-                        let pos = AbsoluteBytePos::new(encoder.position());
-                        let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
-                        encoder.encode_tagged(dep_node_index, side_effects)?;
+                .map(|(dep_node_index, side_effects)| {
+                    let pos = AbsoluteBytePos::new(encoder.position());
+                    let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
+                    encoder.encode_tagged(dep_node_index, side_effects);
 
-                        Ok((dep_node_index, pos))
-                    },
-                )
-                .collect::<Result<_, _>>()?;
+                    (dep_node_index, pos)
+                })
+                .collect();
 
             let interpret_alloc_index = {
                 let mut interpret_alloc_index = Vec::new();
@@ -296,7 +294,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
                         let id = encoder.interpret_allocs[idx];
                         let pos = encoder.position() as u32;
                         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;
                 }
@@ -312,23 +310,21 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
 
             hygiene_encode_context.encode(
                 &mut encoder,
-                |encoder, index, ctxt_data| -> FileEncodeResult {
+                |encoder, index, ctxt_data| {
                     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);
-                    Ok(())
                 },
-                |encoder, expn_id, data, hash| -> FileEncodeResult {
+                |encoder, expn_id, data, hash| {
                     if expn_id.krate == LOCAL_CRATE {
                         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);
                     } else {
                         foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
                     }
-                    Ok(())
                 },
-            )?;
+            );
 
             // `Encode the file footer.
             let footer_pos = encoder.position() as u64;
@@ -343,16 +339,16 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
                     expn_data,
                     foreign_expn_data,
                 },
-            )?;
+            );
 
             // Encode the position of the footer as the last 8 bytes of the
             // 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
             // of the footer must be the last thing in the data stream.
 
-            Ok(())
+            encoder.finish()
         })
     }
 }
@@ -825,7 +821,7 @@ impl OpaqueEncoder for FileEncoder {
 /// An encoder that can write to the incremental compilation cache.
 pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
     tcx: TyCtxt<'tcx>,
-    encoder: &'a mut E,
+    encoder: E,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
     interpret_allocs: FxIndexSet<interpret::AllocId>,
@@ -836,7 +832,7 @@ pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
     fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
         self.file_to_file_index[&(&*source_file as *const SourceFile)]
@@ -847,48 +843,44 @@ where
     /// 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
     /// we get the expected tag and read the expected number of bytes.
-    fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
-        &mut self,
-        tag: T,
-        value: &V,
-    ) -> Result<(), E::Error> {
+    fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
         let start_pos = self.position();
 
-        tag.encode(self)?;
-        value.encode(self)?;
+        tag.encode(self);
+        value.encode(self);
 
         let end_pos = self.position();
-        ((end_pos - start_pos) as u64).encode(self)
+        ((end_pos - start_pos) as u64).encode(self);
     }
 }
 
 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
+        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s);
     }
 }
 
 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
         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
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
         let span_data = self.data_untracked();
-        span_data.ctxt.encode(s)?;
-        span_data.parent.encode(s)?;
+        span_data.ctxt.encode(s);
+        span_data.parent.encode(s);
 
         if span_data.is_dummy() {
             return TAG_PARTIAL_SPAN.encode(s);
@@ -897,10 +889,10 @@ where
         if let Some(parent) = span_data.parent {
             let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked();
             if enclosing.contains(span_data) {
-                TAG_RELATIVE_SPAN.encode(s)?;
-                (span_data.lo - enclosing.lo).to_u32().encode(s)?;
-                (span_data.hi - enclosing.lo).to_u32().encode(s)?;
-                return Ok(());
+                TAG_RELATIVE_SPAN.encode(s);
+                (span_data.lo - enclosing.lo).to_u32().encode(s);
+                (span_data.hi - enclosing.lo).to_u32().encode(s);
+                return;
             }
         }
 
@@ -920,17 +912,17 @@ where
 
         let source_file_index = s.source_file_index(file_lo);
 
-        TAG_FULL_SPAN.encode(s)?;
-        source_file_index.encode(s)?;
-        line_lo.encode(s)?;
-        col_lo.encode(s)?;
-        len.encode(s)
+        TAG_FULL_SPAN.encode(s);
+        source_file_index.encode(s);
+        line_lo.encode(s);
+        col_lo.encode(s);
+        len.encode(s);
     }
 }
 
 impl<'a, 'tcx, E> TyEncoder for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
     type I = TyCtxt<'tcx>;
     const CLEAR_CROSS_CRATE: bool = false;
@@ -944,36 +936,36 @@ where
     fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
         &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);
 
-        index.encode(self)
+        index.encode(self);
     }
 }
 
 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for CrateNum
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        s.tcx.stable_crate_id(*self).encode(s)
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
+        s.tcx.stable_crate_id(*self).encode(s);
     }
 }
 
 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        s.tcx.def_path_hash(*self).encode(s)
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
+        s.tcx.def_path_hash(*self).encode(s);
     }
 }
 
 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+    fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) {
         bug!("encoding `DefIndex` without context");
     }
 }
@@ -981,7 +973,7 @@ where
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
         #[inline]
-        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
+        $(fn $name(&mut self, value: $ty) {
             self.encoder.$name(value)
         })*
     }
@@ -989,9 +981,10 @@ macro_rules! encoder_methods {
 
 impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + OpaqueEncoder,
+    E: OpaqueEncoder,
 {
-    type Error = E::Error;
+    type Ok = E::Ok;
+    type Err = E::Err;
 
     encoder_methods! {
         emit_usize(usize);
@@ -1015,6 +1008,10 @@ where
         emit_str(&str);
         emit_raw_bytes(&[u8]);
     }
+
+    fn finish(self) -> Result<E::Ok, E::Err> {
+        self.encoder.finish()
+    }
 }
 
 // This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
@@ -1022,8 +1019,8 @@ where
 // Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
 // and the encoding traits currently work.
 impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] {
-    fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResult {
-        self.encode(e.encoder)
+    fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) {
+        self.encode(&mut e.encoder);
     }
 }
 
@@ -1031,8 +1028,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
     tcx: CTX,
     encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,
     query_result_index: &mut EncodedDepNodeIndex,
-) -> FileEncodeResult
-where
+) where
     CTX: QueryContext + 'tcx,
     Q: super::QueryDescription<CTX>,
     Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>,
@@ -1044,11 +1040,7 @@ where
 
     assert!(Q::query_state(tcx).all_inactive());
     let cache = Q::query_cache(tcx);
-    let mut res = Ok(());
     cache.iter(&mut |key, value, dep_node| {
-        if res.is_err() {
-            return;
-        }
         if Q::cache_on_disk(*tcx.dep_context(), &key) {
             let dep_node = SerializedDepNodeIndex::new(dep_node.index());
 
@@ -1057,14 +1049,7 @@ where
 
             // Encode the type check tables with the `SerializedDepNodeIndex`
             // as tag.
-            match encoder.encode_tagged(dep_node, value) {
-                Ok(()) => {}
-                Err(e) => {
-                    res = Err(e);
-                }
-            }
+            encoder.encode_tagged(dep_node, value);
         }
     });
-
-    res
 }
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 634236c0dac..87aedc6542d 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -142,7 +142,7 @@ impl<'tcx> QueryCtxt<'tcx> {
         self,
         encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx, opaque::FileEncoder>,
         query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
-    ) -> opaque::FileEncodeResult {
+    ) {
         macro_rules! encode_queries {
             ($($query:ident,)*) => {
                 $(
@@ -150,14 +150,12 @@ impl<'tcx> QueryCtxt<'tcx> {
                         self,
                         encoder,
                         query_result_index
-                    )?;
+                    );
                 )*
             }
         }
 
         rustc_cached_queries!(encode_queries!);
-
-        Ok(())
     }
 
     pub fn try_print_query_stack(
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index f6d06e4362c..5a32d7075db 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -842,7 +842,7 @@ impl<K: DepKind> DepGraph<K> {
         if let Some(data) = &self.data {
             data.current.encoder.steal().finish(profiler)
         } else {
-            Ok(())
+            Ok(0)
         }
     }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 1f8d87a7e91..7fde9c0119b 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -20,7 +20,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sync::Lock;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize};
-use rustc_serialize::{Decodable, Decoder, Encodable};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use smallvec::SmallVec;
 use std::convert::TryInto;
 
@@ -166,7 +166,6 @@ struct EncoderState<K: DepKind> {
     encoder: FileEncoder,
     total_node_count: usize,
     total_edge_count: usize,
-    result: FileEncodeResult,
     stats: Option<FxHashMap<K, Stat<K>>>,
 }
 
@@ -176,7 +175,6 @@ impl<K: DepKind> EncoderState<K> {
             encoder,
             total_edge_count: 0,
             total_node_count: 0,
-            result: Ok(()),
             stats: record_stats.then(FxHashMap::default),
         }
     }
@@ -208,29 +206,28 @@ impl<K: DepKind> EncoderState<K> {
         }
 
         let encoder = &mut self.encoder;
-        if self.result.is_ok() {
-            self.result = node.encode(encoder);
-        }
+        node.encode(encoder);
         index
     }
 
     fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
-        let Self { mut encoder, total_node_count, total_edge_count, result, stats: _ } = self;
-        let () = result?;
+        let Self { mut encoder, total_node_count, total_edge_count, stats: _ } = self;
 
         let node_count = total_node_count.try_into().unwrap();
         let edge_count = total_edge_count.try_into().unwrap();
 
         debug!(?node_count, ?edge_count);
         debug!("position: {:?}", encoder.position());
-        IntEncodedWithFixedSize(node_count).encode(&mut encoder)?;
-        IntEncodedWithFixedSize(edge_count).encode(&mut encoder)?;
+        IntEncodedWithFixedSize(node_count).encode(&mut encoder);
+        IntEncodedWithFixedSize(edge_count).encode(&mut encoder);
         debug!("position: {:?}", encoder.position());
         // Drop the encoder so that nothing is written after the counts.
-        let result = encoder.flush();
-        // FIXME(rylev): we hardcode the dep graph file name so we don't need a dependency on
-        // rustc_incremental just for that.
-        profiler.artifact_size("dep_graph", "dep-graph.bin", encoder.position() as u64);
+        let result = encoder.finish();
+        if let Ok(position) = result {
+            // FIXME(rylev): we hardcode the dep graph file name so we
+            // don't need a dependency on rustc_incremental just for that.
+            profiler.artifact_size("dep_graph", "dep-graph.bin", position as u64);
+        }
         result
     }
 }
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs
index c4541bbcac9..5e53f0b104d 100644
--- a/compiler/rustc_serialize/src/collection_impls.rs
+++ b/compiler/rustc_serialize/src/collection_impls.rs
@@ -10,9 +10,9 @@ use std::sync::Arc;
 use smallvec::{Array, SmallVec};
 
 impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         let slice: &[A::Item] = self;
-        slice.encode(s)
+        slice.encode(s);
     }
 }
 
@@ -24,12 +24,11 @@ impl<D: Decoder, A: Array<Item: Decodable<D>>> Decodable<D> for SmallVec<A> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for LinkedList<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_usize(self.len())?;
+    fn encode(&self, s: &mut S) {
+        s.emit_usize(self.len());
         for e in self.iter() {
-            e.encode(s)?;
+            e.encode(s);
         }
-        Ok(())
     }
 }
 
@@ -41,12 +40,11 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for LinkedList<T> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for VecDeque<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_usize(self.len())?;
+    fn encode(&self, s: &mut S) {
+        s.emit_usize(self.len());
         for e in self.iter() {
-            e.encode(s)?;
+            e.encode(s);
         }
-        Ok(())
     }
 }
 
@@ -62,13 +60,12 @@ where
     K: Encodable<S> + PartialEq + Ord,
     V: Encodable<S>,
 {
-    fn encode(&self, e: &mut S) -> Result<(), S::Error> {
-        e.emit_usize(self.len())?;
+    fn encode(&self, e: &mut S) {
+        e.emit_usize(self.len());
         for (key, val) in self.iter() {
-            key.encode(e)?;
-            val.encode(e)?;
+            key.encode(e);
+            val.encode(e);
         }
-        Ok(())
     }
 }
 
@@ -93,12 +90,11 @@ impl<S: Encoder, T> Encodable<S> for BTreeSet<T>
 where
     T: Encodable<S> + PartialEq + Ord,
 {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_usize(self.len())?;
+    fn encode(&self, s: &mut S) {
+        s.emit_usize(self.len());
         for e in self.iter() {
-            e.encode(s)?;
+            e.encode(s);
         }
-        Ok(())
     }
 }
 
@@ -122,13 +118,12 @@ where
     V: Encodable<E>,
     S: BuildHasher,
 {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        e.emit_usize(self.len())?;
+    fn encode(&self, e: &mut E) {
+        e.emit_usize(self.len());
         for (key, val) in self.iter() {
-            key.encode(e)?;
-            val.encode(e)?;
+            key.encode(e);
+            val.encode(e);
         }
-        Ok(())
     }
 }
 
@@ -156,12 +151,11 @@ where
     T: Encodable<E> + Eq,
     S: BuildHasher,
 {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_usize(self.len())?;
+    fn encode(&self, s: &mut E) {
+        s.emit_usize(self.len());
         for e in self.iter() {
-            e.encode(s)?;
+            e.encode(s);
         }
-        Ok(())
     }
 }
 
@@ -187,13 +181,12 @@ where
     V: Encodable<E>,
     S: BuildHasher,
 {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        e.emit_usize(self.len())?;
+    fn encode(&self, e: &mut E) {
+        e.emit_usize(self.len());
         for (key, val) in self.iter() {
-            key.encode(e)?;
-            val.encode(e)?;
+            key.encode(e);
+            val.encode(e);
         }
-        Ok(())
     }
 }
 
@@ -221,12 +214,11 @@ where
     T: Encodable<E> + Hash + Eq,
     S: BuildHasher,
 {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_usize(self.len())?;
+    fn encode(&self, s: &mut E) {
+        s.emit_usize(self.len());
         for e in self.iter() {
-            e.encode(s)?;
+            e.encode(s);
         }
-        Ok(())
     }
 }
 
@@ -247,9 +239,9 @@ where
 }
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut E) {
         let slice: &[T] = self;
-        slice.encode(s)
+        slice.encode(s);
     }
 }
 
@@ -261,9 +253,9 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
 }
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut E) {
         let slice: &[T] = self;
-        slice.encode(s)
+        slice.encode(s);
     }
 }
 
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 40b79ba89ef..b2dbf937eb7 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -11,8 +11,6 @@ use std::ptr;
 // Encoder
 // -----------------------------------------------------------------------------
 
-pub type EncodeResult = Result<(), !>;
-
 pub struct Encoder {
     pub data: Vec<u8>,
 }
@@ -22,10 +20,6 @@ impl Encoder {
         Encoder { data: vec![] }
     }
 
-    pub fn into_inner(self) -> Vec<u8> {
-        self.data
-    }
-
     #[inline]
     pub fn position(&self) -> usize {
         self.data.len()
@@ -49,8 +43,6 @@ macro_rules! write_leb128 {
             let encoded = leb128::$fun(buf, $value);
             $enc.data.set_len(old_len + encoded.len());
         }
-
-        Ok(())
     }};
 }
 
@@ -62,108 +54,109 @@ macro_rules! write_leb128 {
 const STR_SENTINEL: u8 = 0xC1;
 
 impl serialize::Encoder for Encoder {
-    type Error = !;
+    type Ok = Vec<u8>;
+    type Err = !;
 
     #[inline]
-    fn emit_usize(&mut self, v: usize) -> EncodeResult {
+    fn emit_usize(&mut self, v: usize) {
         write_leb128!(self, v, usize, write_usize_leb128)
     }
 
     #[inline]
-    fn emit_u128(&mut self, v: u128) -> EncodeResult {
-        write_leb128!(self, v, u128, write_u128_leb128)
+    fn emit_u128(&mut self, v: u128) {
+        write_leb128!(self, v, u128, write_u128_leb128);
     }
 
     #[inline]
-    fn emit_u64(&mut self, v: u64) -> EncodeResult {
-        write_leb128!(self, v, u64, write_u64_leb128)
+    fn emit_u64(&mut self, v: u64) {
+        write_leb128!(self, v, u64, write_u64_leb128);
     }
 
     #[inline]
-    fn emit_u32(&mut self, v: u32) -> EncodeResult {
-        write_leb128!(self, v, u32, write_u32_leb128)
+    fn emit_u32(&mut self, v: u32) {
+        write_leb128!(self, v, u32, write_u32_leb128);
     }
 
     #[inline]
-    fn emit_u16(&mut self, v: u16) -> EncodeResult {
+    fn emit_u16(&mut self, v: u16) {
         self.data.extend_from_slice(&v.to_le_bytes());
-        Ok(())
     }
 
     #[inline]
-    fn emit_u8(&mut self, v: u8) -> EncodeResult {
+    fn emit_u8(&mut self, v: u8) {
         self.data.push(v);
-        Ok(())
     }
 
     #[inline]
-    fn emit_isize(&mut self, v: isize) -> EncodeResult {
+    fn emit_isize(&mut self, v: isize) {
         write_leb128!(self, v, isize, write_isize_leb128)
     }
 
     #[inline]
-    fn emit_i128(&mut self, v: i128) -> EncodeResult {
+    fn emit_i128(&mut self, v: i128) {
         write_leb128!(self, v, i128, write_i128_leb128)
     }
 
     #[inline]
-    fn emit_i64(&mut self, v: i64) -> EncodeResult {
+    fn emit_i64(&mut self, v: i64) {
         write_leb128!(self, v, i64, write_i64_leb128)
     }
 
     #[inline]
-    fn emit_i32(&mut self, v: i32) -> EncodeResult {
+    fn emit_i32(&mut self, v: i32) {
         write_leb128!(self, v, i32, write_i32_leb128)
     }
 
     #[inline]
-    fn emit_i16(&mut self, v: i16) -> EncodeResult {
+    fn emit_i16(&mut self, v: i16) {
         self.data.extend_from_slice(&v.to_le_bytes());
-        Ok(())
     }
 
     #[inline]
-    fn emit_i8(&mut self, v: i8) -> EncodeResult {
-        self.emit_u8(v as u8)
+    fn emit_i8(&mut self, v: i8) {
+        self.emit_u8(v as u8);
     }
 
     #[inline]
-    fn emit_bool(&mut self, v: bool) -> EncodeResult {
-        self.emit_u8(if v { 1 } else { 0 })
+    fn emit_bool(&mut self, v: bool) {
+        self.emit_u8(if v { 1 } else { 0 });
     }
 
     #[inline]
-    fn emit_f64(&mut self, v: f64) -> EncodeResult {
+    fn emit_f64(&mut self, v: f64) {
         let as_u64: u64 = v.to_bits();
-        self.emit_u64(as_u64)
+        self.emit_u64(as_u64);
     }
 
     #[inline]
-    fn emit_f32(&mut self, v: f32) -> EncodeResult {
+    fn emit_f32(&mut self, v: f32) {
         let as_u32: u32 = v.to_bits();
-        self.emit_u32(as_u32)
+        self.emit_u32(as_u32);
     }
 
     #[inline]
-    fn emit_char(&mut self, v: char) -> EncodeResult {
-        self.emit_u32(v as u32)
+    fn emit_char(&mut self, v: char) {
+        self.emit_u32(v as u32);
     }
 
     #[inline]
-    fn emit_str(&mut self, v: &str) -> EncodeResult {
-        self.emit_usize(v.len())?;
-        self.emit_raw_bytes(v.as_bytes())?;
-        self.emit_u8(STR_SENTINEL)
+    fn emit_str(&mut self, v: &str) {
+        self.emit_usize(v.len());
+        self.emit_raw_bytes(v.as_bytes());
+        self.emit_u8(STR_SENTINEL);
     }
 
     #[inline]
-    fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
+    fn emit_raw_bytes(&mut self, s: &[u8]) {
         self.data.extend_from_slice(s);
-        Ok(())
+    }
+
+    fn finish(self) -> Result<Self::Ok, Self::Err> {
+        Ok(self.data)
     }
 }
 
-pub type FileEncodeResult = Result<(), io::Error>;
+pub type FileEncodeResult = Result<usize, io::Error>;
 
 // `FileEncoder` encodes data to file via fixed-size buffer.
 //
@@ -182,6 +175,9 @@ pub struct FileEncoder {
     buffered: usize,
     flushed: usize,
     file: File,
+    // This is used to implement delayed error handling, as described in the
+    // comment on `trait Encoder`.
+    res: Result<(), io::Error>,
 }
 
 impl FileEncoder {
@@ -202,7 +198,13 @@ impl FileEncoder {
 
         let file = File::create(path)?;
 
-        Ok(FileEncoder { buf: Box::new_uninit_slice(capacity), buffered: 0, flushed: 0, file })
+        Ok(FileEncoder {
+            buf: Box::new_uninit_slice(capacity),
+            buffered: 0,
+            flushed: 0,
+            file,
+            res: Ok(()),
+        })
     }
 
     #[inline]
@@ -212,7 +214,7 @@ impl FileEncoder {
         self.flushed + self.buffered
     }
 
-    pub fn flush(&mut self) -> FileEncodeResult {
+    pub fn flush(&mut self) {
         // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever
         // offers a raw buffer access API, we can use it, and remove this.
 
@@ -267,6 +269,12 @@ impl FileEncoder {
             }
         }
 
+        // If we've already had an error, do nothing. It'll get reported after
+        // `finish` is called.
+        if self.res.is_err() {
+            return;
+        }
+
         let mut guard = BufGuard::new(
             unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) },
             &mut self.buffered,
@@ -276,18 +284,20 @@ impl FileEncoder {
         while !guard.done() {
             match self.file.write(guard.remaining()) {
                 Ok(0) => {
-                    return Err(io::Error::new(
+                    self.res = Err(io::Error::new(
                         io::ErrorKind::WriteZero,
                         "failed to write the buffered data",
                     ));
+                    return;
                 }
                 Ok(n) => guard.consume(n),
                 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
-                Err(e) => return Err(e),
+                Err(e) => {
+                    self.res = Err(e);
+                    return;
+                }
             }
         }
-
-        Ok(())
     }
 
     #[inline]
@@ -296,14 +306,14 @@ impl FileEncoder {
     }
 
     #[inline]
-    fn write_one(&mut self, value: u8) -> FileEncodeResult {
+    fn write_one(&mut self, value: u8) {
         // We ensure this during `FileEncoder` construction.
         debug_assert!(self.capacity() >= 1);
 
         let mut buffered = self.buffered;
 
         if std::intrinsics::unlikely(buffered >= self.capacity()) {
-            self.flush()?;
+            self.flush();
             buffered = 0;
         }
 
@@ -314,12 +324,10 @@ impl FileEncoder {
         }
 
         self.buffered = buffered + 1;
-
-        Ok(())
     }
 
     #[inline]
-    fn write_all(&mut self, buf: &[u8]) -> FileEncodeResult {
+    fn write_all(&mut self, buf: &[u8]) {
         let capacity = self.capacity();
         let buf_len = buf.len();
 
@@ -327,7 +335,7 @@ impl FileEncoder {
             let mut buffered = self.buffered;
 
             if std::intrinsics::unlikely(buf_len > capacity - buffered) {
-                self.flush()?;
+                self.flush();
                 buffered = 0;
             }
 
@@ -340,16 +348,20 @@ impl FileEncoder {
             }
 
             self.buffered = buffered + buf_len;
-
-            Ok(())
         } else {
-            self.write_all_unbuffered(buf)
+            self.write_all_unbuffered(buf);
         }
     }
 
-    fn write_all_unbuffered(&mut self, mut buf: &[u8]) -> FileEncodeResult {
+    fn write_all_unbuffered(&mut self, mut buf: &[u8]) {
+        // If we've already had an error, do nothing. It'll get reported after
+        // `finish` is called.
+        if self.res.is_err() {
+            return;
+        }
+
         if self.buffered > 0 {
-            self.flush()?;
+            self.flush();
         }
 
         // This is basically a copy of `Write::write_all` but also updates our
@@ -359,26 +371,30 @@ impl FileEncoder {
         while !buf.is_empty() {
             match self.file.write(buf) {
                 Ok(0) => {
-                    return Err(io::Error::new(
+                    self.res = Err(io::Error::new(
                         io::ErrorKind::WriteZero,
                         "failed to write whole buffer",
                     ));
+                    return;
                 }
                 Ok(n) => {
                     buf = &buf[n..];
                     self.flushed += n;
                 }
                 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
-                Err(e) => return Err(e),
+                Err(e) => {
+                    self.res = Err(e);
+                    return;
+                }
             }
         }
-
-        Ok(())
     }
 }
 
 impl Drop for FileEncoder {
     fn drop(&mut self) {
+        // Likely to be a no-op, because `finish` should have been called and
+        // it also flushes. But do it just in case.
         let _result = self.flush();
     }
 }
@@ -394,7 +410,7 @@ macro_rules! file_encoder_write_leb128 {
 
         // This can't overflow. See assertion in `FileEncoder::with_capacity`.
         if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) {
-            $enc.flush()?;
+            $enc.flush();
             buffered = 0;
         }
 
@@ -406,106 +422,112 @@ macro_rules! file_encoder_write_leb128 {
 
         let encoded = leb128::$fun(buf, $value);
         $enc.buffered = buffered + encoded.len();
-
-        Ok(())
     }};
 }
 
 impl serialize::Encoder for FileEncoder {
-    type Error = io::Error;
+    type Ok = usize;
+    type Err = io::Error;
 
     #[inline]
-    fn emit_usize(&mut self, v: usize) -> FileEncodeResult {
+    fn emit_usize(&mut self, v: usize) {
         file_encoder_write_leb128!(self, v, usize, write_usize_leb128)
     }
 
     #[inline]
-    fn emit_u128(&mut self, v: u128) -> FileEncodeResult {
+    fn emit_u128(&mut self, v: u128) {
         file_encoder_write_leb128!(self, v, u128, write_u128_leb128)
     }
 
     #[inline]
-    fn emit_u64(&mut self, v: u64) -> FileEncodeResult {
+    fn emit_u64(&mut self, v: u64) {
         file_encoder_write_leb128!(self, v, u64, write_u64_leb128)
     }
 
     #[inline]
-    fn emit_u32(&mut self, v: u32) -> FileEncodeResult {
+    fn emit_u32(&mut self, v: u32) {
         file_encoder_write_leb128!(self, v, u32, write_u32_leb128)
     }
 
     #[inline]
-    fn emit_u16(&mut self, v: u16) -> FileEncodeResult {
-        self.write_all(&v.to_le_bytes())
+    fn emit_u16(&mut self, v: u16) {
+        self.write_all(&v.to_le_bytes());
     }
 
     #[inline]
-    fn emit_u8(&mut self, v: u8) -> FileEncodeResult {
-        self.write_one(v)
+    fn emit_u8(&mut self, v: u8) {
+        self.write_one(v);
     }
 
     #[inline]
-    fn emit_isize(&mut self, v: isize) -> FileEncodeResult {
+    fn emit_isize(&mut self, v: isize) {
         file_encoder_write_leb128!(self, v, isize, write_isize_leb128)
     }
 
     #[inline]
-    fn emit_i128(&mut self, v: i128) -> FileEncodeResult {
+    fn emit_i128(&mut self, v: i128) {
         file_encoder_write_leb128!(self, v, i128, write_i128_leb128)
     }
 
     #[inline]
-    fn emit_i64(&mut self, v: i64) -> FileEncodeResult {
+    fn emit_i64(&mut self, v: i64) {
         file_encoder_write_leb128!(self, v, i64, write_i64_leb128)
     }
 
     #[inline]
-    fn emit_i32(&mut self, v: i32) -> FileEncodeResult {
+    fn emit_i32(&mut self, v: i32) {
         file_encoder_write_leb128!(self, v, i32, write_i32_leb128)
     }
 
     #[inline]
-    fn emit_i16(&mut self, v: i16) -> FileEncodeResult {
-        self.write_all(&v.to_le_bytes())
+    fn emit_i16(&mut self, v: i16) {
+        self.write_all(&v.to_le_bytes());
     }
 
     #[inline]
-    fn emit_i8(&mut self, v: i8) -> FileEncodeResult {
-        self.emit_u8(v as u8)
+    fn emit_i8(&mut self, v: i8) {
+        self.emit_u8(v as u8);
     }
 
     #[inline]
-    fn emit_bool(&mut self, v: bool) -> FileEncodeResult {
-        self.emit_u8(if v { 1 } else { 0 })
+    fn emit_bool(&mut self, v: bool) {
+        self.emit_u8(if v { 1 } else { 0 });
     }
 
     #[inline]
-    fn emit_f64(&mut self, v: f64) -> FileEncodeResult {
+    fn emit_f64(&mut self, v: f64) {
         let as_u64: u64 = v.to_bits();
-        self.emit_u64(as_u64)
+        self.emit_u64(as_u64);
     }
 
     #[inline]
-    fn emit_f32(&mut self, v: f32) -> FileEncodeResult {
+    fn emit_f32(&mut self, v: f32) {
         let as_u32: u32 = v.to_bits();
-        self.emit_u32(as_u32)
+        self.emit_u32(as_u32);
     }
 
     #[inline]
-    fn emit_char(&mut self, v: char) -> FileEncodeResult {
-        self.emit_u32(v as u32)
+    fn emit_char(&mut self, v: char) {
+        self.emit_u32(v as u32);
     }
 
     #[inline]
-    fn emit_str(&mut self, v: &str) -> FileEncodeResult {
-        self.emit_usize(v.len())?;
-        self.emit_raw_bytes(v.as_bytes())?;
-        self.emit_u8(STR_SENTINEL)
+    fn emit_str(&mut self, v: &str) {
+        self.emit_usize(v.len());
+        self.emit_raw_bytes(v.as_bytes());
+        self.emit_u8(STR_SENTINEL);
     }
 
     #[inline]
-    fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult {
-        self.write_all(s)
+    fn emit_raw_bytes(&mut self, s: &[u8]) {
+        self.write_all(s);
+    }
+
+    fn finish(mut self) -> Result<usize, io::Error> {
+        self.flush();
+
+        let res = std::mem::replace(&mut self.res, Ok(()));
+        res.map(|()| self.position())
     }
 }
 
@@ -667,16 +689,16 @@ impl<'a> serialize::Decoder for Decoder<'a> {
 // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
 // since the default implementations call `encode` on their slices internally.
 impl serialize::Encodable<Encoder> for [u8] {
-    fn encode(&self, e: &mut Encoder) -> EncodeResult {
-        serialize::Encoder::emit_usize(e, self.len())?;
-        e.emit_raw_bytes(self)
+    fn encode(&self, e: &mut Encoder) {
+        serialize::Encoder::emit_usize(e, self.len());
+        e.emit_raw_bytes(self);
     }
 }
 
 impl serialize::Encodable<FileEncoder> for [u8] {
-    fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
-        serialize::Encoder::emit_usize(e, self.len())?;
-        e.emit_raw_bytes(self)
+    fn encode(&self, e: &mut FileEncoder) {
+        serialize::Encoder::emit_usize(e, self.len());
+        e.emit_raw_bytes(self);
     }
 }
 
@@ -698,23 +720,21 @@ impl IntEncodedWithFixedSize {
 
 impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize {
     #[inline]
-    fn encode(&self, e: &mut Encoder) -> EncodeResult {
+    fn encode(&self, e: &mut Encoder) {
         let _start_pos = e.position();
-        e.emit_raw_bytes(&self.0.to_le_bytes())?;
+        e.emit_raw_bytes(&self.0.to_le_bytes());
         let _end_pos = e.position();
         debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
-        Ok(())
     }
 }
 
 impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize {
     #[inline]
-    fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
+    fn encode(&self, e: &mut FileEncoder) {
         let _start_pos = e.position();
-        e.emit_raw_bytes(&self.0.to_le_bytes())?;
+        e.emit_raw_bytes(&self.0.to_le_bytes());
         let _end_pos = e.position();
         debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
-        Ok(())
     }
 }
 
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 817a0c9dcb1..98bb18581f5 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -11,36 +11,47 @@ use std::path;
 use std::rc::Rc;
 use std::sync::Arc;
 
+/// A note about error handling.
+///
+/// Encoders may be fallible, but in practice failure is rare and there are so
+/// many nested calls that typical Rust error handling (via `Result` and `?`)
+/// is pervasive and has non-trivial cost. Instead, impls of this trait must
+/// implement a delayed error handling strategy. If a failure occurs, they
+/// should record this internally, and all subsequent encoding operations can
+/// be processed or ignored, whichever is appropriate. Then when `finish()` is
+/// called, an error result should be returned to indicate the failure. If no
+/// failures occurred, then `finish()` should return a success result.
 pub trait Encoder {
-    type Error;
+    type Ok;
+    type Err;
 
     // Primitive types:
-    fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>;
-    fn emit_u128(&mut self, v: u128) -> Result<(), Self::Error>;
-    fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
-    fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>;
-    fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>;
-    fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>;
-    fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>;
-    fn emit_i128(&mut self, v: i128) -> Result<(), Self::Error>;
-    fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
-    fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>;
-    fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>;
-    fn emit_i8(&mut self, v: i8) -> Result<(), Self::Error>;
-    fn emit_bool(&mut self, v: bool) -> Result<(), Self::Error>;
-    fn emit_f64(&mut self, v: f64) -> Result<(), Self::Error>;
-    fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>;
-    fn emit_char(&mut self, v: char) -> Result<(), Self::Error>;
-    fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>;
-    fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>;
+    fn emit_usize(&mut self, v: usize);
+    fn emit_u128(&mut self, v: u128);
+    fn emit_u64(&mut self, v: u64);
+    fn emit_u32(&mut self, v: u32);
+    fn emit_u16(&mut self, v: u16);
+    fn emit_u8(&mut self, v: u8);
+    fn emit_isize(&mut self, v: isize);
+    fn emit_i128(&mut self, v: i128);
+    fn emit_i64(&mut self, v: i64);
+    fn emit_i32(&mut self, v: i32);
+    fn emit_i16(&mut self, v: i16);
+    fn emit_i8(&mut self, v: i8);
+    fn emit_bool(&mut self, v: bool);
+    fn emit_f64(&mut self, v: f64);
+    fn emit_f32(&mut self, v: f32);
+    fn emit_char(&mut self, v: char);
+    fn emit_str(&mut self, v: &str);
+    fn emit_raw_bytes(&mut self, s: &[u8]);
 
     // Convenience for the derive macro:
-    fn emit_enum_variant<F>(&mut self, v_id: usize, f: F) -> Result<(), Self::Error>
+    fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
     where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
+        F: FnOnce(&mut Self),
     {
-        self.emit_usize(v_id)?;
-        f(self)
+        self.emit_usize(v_id);
+        f(self);
     }
 
     // We put the field index in a const generic to allow the emit_usize to be
@@ -50,9 +61,12 @@ pub trait Encoder {
     // optimization that would otherwise be necessary here, likely due to the
     // multiple levels of inlining and const-prop that are needed.
     #[inline]
-    fn emit_fieldless_enum_variant<const ID: usize>(&mut self) -> Result<(), Self::Error> {
+    fn emit_fieldless_enum_variant<const ID: usize>(&mut self) {
         self.emit_usize(ID)
     }
+
+    // Consume the encoder, getting the result.
+    fn finish(self) -> Result<Self::Ok, Self::Err>;
 }
 
 // Note: all the methods in this trait are infallible, which may be surprising.
@@ -95,7 +109,7 @@ pub trait Decoder {
 /// * `TyEncodable` should be used for types that are only serialized in crate
 ///   metadata or the incremental cache. This is most types in `rustc_middle`.
 pub trait Encodable<S: Encoder> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error>;
+    fn encode(&self, s: &mut S);
 }
 
 /// Trait for types that can be deserialized
@@ -117,8 +131,8 @@ macro_rules! direct_serialize_impls {
     ($($ty:ident $emit_method:ident $read_method:ident),*) => {
         $(
             impl<S: Encoder> Encodable<S> for $ty {
-                fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-                    s.$emit_method(*self)
+                fn encode(&self, s: &mut S) {
+                    s.$emit_method(*self);
                 }
             }
 
@@ -138,12 +152,14 @@ direct_serialize_impls! {
     u32 emit_u32 read_u32,
     u64 emit_u64 read_u64,
     u128 emit_u128 read_u128,
+
     isize emit_isize read_isize,
     i8 emit_i8 read_i8,
     i16 emit_i16 read_i16,
     i32 emit_i32 read_i32,
     i64 emit_i64 read_i64,
     i128 emit_i128 read_i128,
+
     f32 emit_f32 read_f32,
     f64 emit_f64 read_f64,
     bool emit_bool read_bool,
@@ -154,14 +170,14 @@ impl<S: Encoder, T: ?Sized> Encodable<S> for &T
 where
     T: Encodable<S>,
 {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         (**self).encode(s)
     }
 }
 
 impl<S: Encoder> Encodable<S> for ! {
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        unreachable!()
+    fn encode(&self, _s: &mut S) {
+        unreachable!();
     }
 }
 
@@ -172,8 +188,8 @@ impl<D: Decoder> Decodable<D> for ! {
 }
 
 impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u32(self.get())
+    fn encode(&self, s: &mut S) {
+        s.emit_u32(self.get());
     }
 }
 
@@ -184,14 +200,14 @@ impl<D: Decoder> Decodable<D> for ::std::num::NonZeroU32 {
 }
 
 impl<S: Encoder> Encodable<S> for str {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self)
+    fn encode(&self, s: &mut S) {
+        s.emit_str(self);
     }
 }
 
 impl<S: Encoder> Encodable<S> for String {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(&self[..])
+    fn encode(&self, s: &mut S) {
+        s.emit_str(&self[..]);
     }
 }
 
@@ -202,9 +218,7 @@ impl<D: Decoder> Decodable<D> for String {
 }
 
 impl<S: Encoder> Encodable<S> for () {
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        Ok(())
-    }
+    fn encode(&self, _s: &mut S) {}
 }
 
 impl<D: Decoder> Decodable<D> for () {
@@ -212,9 +226,7 @@ impl<D: Decoder> Decodable<D> for () {
 }
 
 impl<S: Encoder, T> Encodable<S> for PhantomData<T> {
-    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
-        Ok(())
-    }
+    fn encode(&self, _s: &mut S) {}
 }
 
 impl<D: Decoder, T> Decodable<D> for PhantomData<T> {
@@ -231,8 +243,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<[T]> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for Rc<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s);
     }
 }
 
@@ -243,19 +255,18 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
-    default fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_usize(self.len())?;
+    default fn encode(&self, s: &mut S) {
+        s.emit_usize(self.len());
         for e in self.iter() {
-            e.encode(s)?
+            e.encode(s);
         }
-        Ok(())
     }
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         let slice: &[T] = self;
-        slice.encode(s)
+        slice.encode(s);
     }
 }
 
@@ -277,9 +288,9 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
 }
 
 impl<S: Encoder, T: Encodable<S>, const N: usize> Encodable<S> for [T; N] {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         let slice: &[T] = self;
-        slice.encode(s)
+        slice.encode(s);
     }
 }
 
@@ -299,9 +310,9 @@ impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]>
 where
     [T]: ToOwned<Owned = Vec<T>>,
 {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         let slice: &[T] = self;
-        slice.encode(s)
+        slice.encode(s);
     }
 }
 
@@ -316,7 +327,7 @@ where
 }
 
 impl<'a, S: Encoder> Encodable<S> for Cow<'a, str> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         let val: &str = self;
         val.encode(s)
     }
@@ -330,9 +341,9 @@ impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         match *self {
-            None => s.emit_enum_variant(0, |_| Ok(())),
+            None => s.emit_enum_variant(0, |_| {}),
             Some(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
         }
     }
@@ -349,7 +360,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
 }
 
 impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) {
         match *self {
             Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)),
             Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
@@ -381,10 +392,9 @@ macro_rules! tuple {
         }
         impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) {
             #[allow(non_snake_case)]
-            fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+            fn encode(&self, s: &mut S) {
                 let ($(ref $name,)+) = *self;
-                $($name.encode(s)?;)+
-                Ok(())
+                $($name.encode(s);)+
             }
         }
         peel! { $($name,)+ }
@@ -394,14 +404,14 @@ macro_rules! tuple {
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
 impl<S: Encoder> Encodable<S> for path::Path {
-    fn encode(&self, e: &mut S) -> Result<(), S::Error> {
-        self.to_str().unwrap().encode(e)
+    fn encode(&self, e: &mut S) {
+        self.to_str().unwrap().encode(e);
     }
 }
 
 impl<S: Encoder> Encodable<S> for path::PathBuf {
-    fn encode(&self, e: &mut S) -> Result<(), S::Error> {
-        path::Path::encode(self, e)
+    fn encode(&self, e: &mut S) {
+        path::Path::encode(self, e);
     }
 }
 
@@ -413,8 +423,8 @@ impl<D: Decoder> Decodable<D> for path::PathBuf {
 }
 
 impl<S: Encoder, T: Encodable<S> + Copy> Encodable<S> for Cell<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        self.get().encode(s)
+    fn encode(&self, s: &mut S) {
+        self.get().encode(s);
     }
 }
 
@@ -430,8 +440,8 @@ impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> {
 // from `encode` when `try_borrow` returns `None`.
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        self.borrow().encode(s)
+    fn encode(&self, s: &mut S) {
+        self.borrow().encode(s);
     }
 }
 
@@ -442,8 +452,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for RefCell<T> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for Arc<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s);
     }
 }
 
@@ -454,8 +464,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<T> {
 }
 
 impl<S: Encoder, T: ?Sized + Encodable<S>> Encodable<S> for Box<T> {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
+    fn encode(&self, s: &mut S) {
+        (**self).encode(s);
     }
 }
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<T> {
diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs
index ec3c34f8bdb..703b7f5e7a5 100644
--- a/compiler/rustc_serialize/tests/opaque.rs
+++ b/compiler/rustc_serialize/tests/opaque.rs
@@ -2,7 +2,7 @@
 
 use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::opaque::{Decoder, Encoder};
-use rustc_serialize::{Decodable, Encodable};
+use rustc_serialize::{Decodable, Encodable, Encoder as EncoderTrait};
 use std::fmt::Debug;
 
 #[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
@@ -32,12 +32,11 @@ fn check_round_trip<T: Encodable<Encoder> + for<'a> Decodable<Decoder<'a>> + Par
     values: Vec<T>,
 ) {
     let mut encoder = Encoder::new();
-
     for value in &values {
-        Encodable::encode(value, &mut encoder).unwrap();
+        Encodable::encode(value, &mut encoder);
     }
 
-    let data = encoder.into_inner();
+    let data = encoder.finish().unwrap();
     let mut decoder = Decoder::new(&data[..], 0);
 
     for value in values {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 2bd0880a7c4..a1533fe46b3 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -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.
 /// Therefore, make sure to include the context when encode a `CrateNum`.
 impl<E: Encoder> Encodable<E> for CrateNum {
-    default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_u32(self.as_u32())
+    default fn encode(&self, s: &mut E) {
+        s.emit_u32(self.as_u32());
     }
 }
 
@@ -203,7 +203,7 @@ rustc_index::newtype_index! {
 }
 
 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>());
     }
 }
@@ -306,9 +306,9 @@ impl DefId {
 }
 
 impl<E: Encoder> Encodable<E> for DefId {
-    default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        self.krate.encode(s)?;
-        self.index.encode(s)
+    default fn encode(&self, s: &mut E) {
+        self.krate.encode(s);
+        self.index.encode(s);
     }
 }
 
@@ -382,8 +382,8 @@ impl fmt::Debug for LocalDefId {
 }
 
 impl<E: Encoder> Encodable<E> for LocalDefId {
-    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        self.to_def_id().encode(s)
+    fn encode(&self, s: &mut E) {
+        self.to_def_id().encode(s);
     }
 }
 
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 59f2badbabb..955db72157c 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1189,12 +1189,12 @@ impl HygieneEncodeContext {
         }
     }
 
-    pub fn encode<T, R>(
+    pub fn encode<T>(
         &self,
         encoder: &mut T,
-        mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
-        mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash) -> Result<(), R>,
-    ) -> Result<(), R> {
+        mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData),
+        mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash),
+    ) {
         // When we serialize a `SyntaxContextData`, we may end up serializing
         // a `SyntaxContext` that we haven't seen before
         while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() {
@@ -1213,22 +1213,19 @@ impl HygieneEncodeContext {
             // order
             for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| {
                 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()) };
 
             for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| {
                 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");
-        Ok(())
     }
 }
 
@@ -1378,40 +1375,38 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
     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>,
     mut f: F,
-) -> Result<(), E> {
+) {
     let all_data: Vec<_> = HygieneData::with(|data| {
         ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect()
     });
     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>,
-    mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
-) -> Result<(), E> {
+    mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash),
+) {
     let all_data: Vec<_> = HygieneData::with(|data| {
         expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect()
     });
     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 {
-    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
-        self.to_expn_id().encode(e)
+    fn encode(&self, e: &mut E) {
+        self.to_expn_id().encode(e);
     }
 }
 
 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>());
     }
 }
@@ -1432,15 +1427,15 @@ pub fn raw_encode_syntax_context<E: Encoder>(
     ctxt: SyntaxContext,
     context: &HygieneEncodeContext,
     e: &mut E,
-) -> Result<(), E::Error> {
+) {
     if !context.serialized_ctxts.lock().contains(&ctxt) {
         context.latest_ctxts.lock().insert(ctxt);
     }
-    ctxt.0.encode(e)
+    ctxt.0.encode(e);
 }
 
 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>());
     }
 }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index ae0228d6ea0..7f227217e3c 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -194,12 +194,10 @@ impl Hash for RealFileName {
 // This is functionally identical to #[derive(Encodable)], with the exception of
 // an added assert statement
 impl<S: Encoder> Encodable<S> for RealFileName {
-    fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, encoder: &mut S) {
         match *self {
             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
@@ -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
                     // if they have been remapped by --remap-path-prefix
                     assert!(local_path.is_none());
-                    local_path.encode(encoder)?;
-                    virtual_name.encode(encoder)?;
-                    Ok(())
+                    local_path.encode(encoder);
+                    virtual_name.encode(encoder);
                 }),
         }
     }
@@ -946,10 +943,10 @@ impl Default 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();
-        span.lo.encode(s)?;
-        span.hi.encode(s)
+        span.lo.encode(s);
+        span.hi.encode(s);
     }
 }
 impl<D: Decoder> Decodable<D> for Span {
@@ -1297,17 +1294,17 @@ pub struct SourceFile {
 }
 
 impl<S: Encoder> Encodable<S> for SourceFile {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        self.name.encode(s)?;
-        self.src_hash.encode(s)?;
-        self.start_pos.encode(s)?;
-        self.end_pos.encode(s)?;
+    fn encode(&self, s: &mut S) {
+        self.name.encode(s);
+        self.src_hash.encode(s);
+        self.start_pos.encode(s);
+        self.end_pos.encode(s);
 
         // We are always in `Lines` form by the time we reach here.
         assert!(self.lines.borrow().is_lines());
         self.lines(|lines| {
             // Store the length.
-            s.emit_u32(lines.len() as u32)?;
+            s.emit_u32(lines.len() as u32);
 
             // Compute and store the difference list.
             if lines.len() != 0 {
@@ -1329,10 +1326,10 @@ impl<S: Encoder> Encodable<S> for SourceFile {
                 };
 
                 // 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.
-                lines[0].encode(s)?;
+                lines[0].encode(s);
 
                 // Encode the difference list.
                 let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst);
@@ -1359,16 +1356,15 @@ impl<S: Encoder> Encodable<S> for SourceFile {
                     }
                     _ => unreachable!(),
                 }
-                s.emit_raw_bytes(&raw_diffs)?;
+                s.emit_raw_bytes(&raw_diffs);
             }
-            Ok(())
-        })?;
+        });
 
-        self.multibyte_chars.encode(s)?;
-        self.non_narrow_chars.encode(s)?;
-        self.name_hash.encode(s)?;
-        self.normalized_pos.encode(s)?;
-        self.cnum.encode(s)
+        self.multibyte_chars.encode(s);
+        self.non_narrow_chars.encode(s);
+        self.name_hash.encode(s);
+        self.normalized_pos.encode(s);
+        self.cnum.encode(s);
     }
 }
 
@@ -1916,8 +1912,8 @@ impl_pos! {
 }
 
 impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u32(self.0)
+    fn encode(&self, s: &mut S) {
+        s.emit_u32(self.0);
     }
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index bcaf53639cc..7b0fa65e808 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1802,8 +1802,8 @@ impl fmt::Display for Symbol {
 }
 
 impl<S: Encoder> Encodable<S> for Symbol {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self.as_str())
+    fn encode(&self, s: &mut S) {
+        s.emit_str(self.as_str());
     }
 }
 
diff --git a/compiler/rustc_type_ir/src/codec.rs b/compiler/rustc_type_ir/src/codec.rs
index 09f781fae75..6a9ea790a30 100644
--- a/compiler/rustc_type_ir/src/codec.rs
+++ b/compiler/rustc_type_ir/src/codec.rs
@@ -31,10 +31,7 @@ pub trait TyEncoder: Encoder {
     fn predicate_shorthands(
         &mut self,
     ) -> &mut FxHashMap<<Self::I as Interner>::PredicateKind, usize>;
-    fn encode_alloc_id(
-        &mut self,
-        alloc_id: &<Self::I as Interner>::AllocId,
-    ) -> Result<(), Self::Error>;
+    fn encode_alloc_id(&mut self, alloc_id: &<Self::I as Interner>::AllocId);
 }
 
 pub trait TyDecoder: Decoder {
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 22b5b475b2c..a6a0d02c8ba 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -715,115 +715,92 @@ where
     I::PredicateKind: 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);
         match self {
-            Bool => e.emit_enum_variant(disc, |_| Ok(())),
-            Char => e.emit_enum_variant(disc, |_| Ok(())),
+            Bool => e.emit_enum_variant(disc, |_| {}),
+            Char => e.emit_enum_variant(disc, |_| {}),
             Int(i) => e.emit_enum_variant(disc, |e| {
-                i.encode(e)?;
-                Ok(())
+                i.encode(e);
             }),
             Uint(u) => e.emit_enum_variant(disc, |e| {
-                u.encode(e)?;
-                Ok(())
+                u.encode(e);
             }),
             Float(f) => e.emit_enum_variant(disc, |e| {
-                f.encode(e)?;
-                Ok(())
+                f.encode(e);
             }),
             Adt(adt, substs) => e.emit_enum_variant(disc, |e| {
-                adt.encode(e)?;
-                substs.encode(e)?;
-                Ok(())
+                adt.encode(e);
+                substs.encode(e);
             }),
             Foreign(def_id) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e)?;
-                Ok(())
+                def_id.encode(e);
             }),
-            Str => e.emit_enum_variant(disc, |_| Ok(())),
+            Str => e.emit_enum_variant(disc, |_| {}),
             Array(t, c) => e.emit_enum_variant(disc, |e| {
-                t.encode(e)?;
-                c.encode(e)?;
-                Ok(())
+                t.encode(e);
+                c.encode(e);
             }),
             Slice(t) => e.emit_enum_variant(disc, |e| {
-                t.encode(e)?;
-                Ok(())
+                t.encode(e);
             }),
             RawPtr(tam) => e.emit_enum_variant(disc, |e| {
-                tam.encode(e)?;
-                Ok(())
+                tam.encode(e);
             }),
             Ref(r, t, m) => e.emit_enum_variant(disc, |e| {
-                r.encode(e)?;
-                t.encode(e)?;
-                m.encode(e)?;
-                Ok(())
+                r.encode(e);
+                t.encode(e);
+                m.encode(e);
             }),
             FnDef(def_id, substs) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e)?;
-                substs.encode(e)?;
-                Ok(())
+                def_id.encode(e);
+                substs.encode(e);
             }),
             FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
-                polyfnsig.encode(e)?;
-                Ok(())
+                polyfnsig.encode(e);
             }),
             Dynamic(l, r) => e.emit_enum_variant(disc, |e| {
-                l.encode(e)?;
-                r.encode(e)?;
-                Ok(())
+                l.encode(e);
+                r.encode(e);
             }),
             Closure(def_id, substs) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e)?;
-                substs.encode(e)?;
-                Ok(())
+                def_id.encode(e);
+                substs.encode(e);
             }),
             Generator(def_id, substs, m) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e)?;
-                substs.encode(e)?;
-                m.encode(e)?;
-                Ok(())
+                def_id.encode(e);
+                substs.encode(e);
+                m.encode(e);
             }),
             GeneratorWitness(b) => e.emit_enum_variant(disc, |e| {
-                b.encode(e)?;
-                Ok(())
+                b.encode(e);
             }),
-            Never => e.emit_enum_variant(disc, |_| Ok(())),
+            Never => e.emit_enum_variant(disc, |_| {}),
             Tuple(substs) => e.emit_enum_variant(disc, |e| {
-                substs.encode(e)?;
-                Ok(())
+                substs.encode(e);
             }),
             Projection(p) => e.emit_enum_variant(disc, |e| {
-                p.encode(e)?;
-                Ok(())
+                p.encode(e);
             }),
             Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| {
-                def_id.encode(e)?;
-                substs.encode(e)?;
-                Ok(())
+                def_id.encode(e);
+                substs.encode(e);
             }),
             Param(p) => e.emit_enum_variant(disc, |e| {
-                p.encode(e)?;
-                Ok(())
+                p.encode(e);
             }),
             Bound(d, b) => e.emit_enum_variant(disc, |e| {
-                d.encode(e)?;
-                b.encode(e)?;
-                Ok(())
+                d.encode(e);
+                b.encode(e);
             }),
             Placeholder(p) => e.emit_enum_variant(disc, |e| {
-                p.encode(e)?;
-                Ok(())
+                p.encode(e);
             }),
             Infer(i) => e.emit_enum_variant(disc, |e| {
-                i.encode(e)?;
-                Ok(())
+                i.encode(e);
             }),
             Error(d) => e.emit_enum_variant(disc, |e| {
-                d.encode(e)?;
-                Ok(())
+                d.encode(e);
             }),
         }
     }