about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs106
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs93
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs158
-rw-r--r--compiler/rustc_span/src/def_id.rs47
-rw-r--r--compiler/rustc_span/src/hygiene.rs30
-rw-r--r--compiler/rustc_span/src/lib.rs137
-rw-r--r--compiler/rustc_span/src/symbol.rs14
7 files changed, 301 insertions, 284 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 2dffd5446a3..d20f4bc7a94 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -409,21 +409,6 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for CrateNum {
-    #[inline]
-    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> CrateNum {
-        let cnum = CrateNum::from_u32(d.read_u32());
-        d.map_encoded_cnum_to_current(cnum)
-    }
-}
-
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex {
-    #[inline]
-    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefIndex {
-        DefIndex::from_u32(d.read_u32())
-    }
-}
-
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
     #[inline]
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ExpnIndex {
@@ -439,11 +424,24 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ast::AttrId {
     }
 }
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
-    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext {
-        let cdata = decoder.cdata();
+impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
+    fn decode_crate_num(&mut self) -> CrateNum {
+        let cnum = CrateNum::from_u32(self.read_u32());
+        self.map_encoded_cnum_to_current(cnum)
+    }
 
-        let Some(sess) = decoder.sess else {
+    fn decode_def_index(&mut self) -> DefIndex {
+        DefIndex::from_u32(self.read_u32())
+    }
+
+    fn decode_def_id(&mut self) -> DefId {
+        DefId { krate: Decodable::decode(self), index: Decodable::decode(self) }
+    }
+
+    fn decode_syntax_context(&mut self) -> SyntaxContext {
+        let cdata = self.cdata();
+
+        let Some(sess) = self.sess else {
             bug!(
                 "Cannot decode SyntaxContext without Session.\
                 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
@@ -451,7 +449,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
         };
 
         let cname = cdata.root.name();
-        rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| {
+        rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
             debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
             cdata
                 .root
@@ -461,21 +459,19 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
                 .decode((cdata, sess))
         })
     }
-}
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
-    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> ExpnId {
-        let local_cdata = decoder.cdata();
+    fn decode_expn_id(&mut self) -> ExpnId {
+        let local_cdata = self.cdata();
 
-        let Some(sess) = decoder.sess else {
+        let Some(sess) = self.sess else {
             bug!(
                 "Cannot decode ExpnId without Session. \
                 You need to explicitly pass `(crate_metadata_ref, tcx)` to `decode` instead of just `crate_metadata_ref`."
             );
         };
 
-        let cnum = CrateNum::decode(decoder);
-        let index = u32::decode(decoder);
+        let cnum = CrateNum::decode(self);
+        let index = u32::decode(self);
 
         let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| {
             let ExpnId { krate: cnum, local_id: index } = expn_id;
@@ -503,9 +499,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
         });
         expn_id
     }
-}
 
-impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
     fn decode_span(&mut self) -> Span {
         let start = self.position();
         let tag = SpanTag(self.peek_byte());
@@ -524,6 +518,32 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
         };
         Span::new(data.lo, data.hi, data.ctxt, data.parent)
     }
+
+    fn decode_symbol(&mut self) -> Symbol {
+        let tag = self.read_u8();
+
+        match tag {
+            SYMBOL_STR => {
+                let s = self.read_str();
+                Symbol::intern(s)
+            }
+            SYMBOL_OFFSET => {
+                // read str offset
+                let pos = self.read_usize();
+
+                // move to str offset and read
+                self.opaque.with_position(pos, |d| {
+                    let s = d.read_str();
+                    Symbol::intern(s)
+                })
+            }
+            SYMBOL_PREINTERNED => {
+                let symbol_index = self.read_u32();
+                Symbol::new_from_decoded(symbol_index)
+            }
+            _ => unreachable!(),
+        }
+    }
 }
 
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
@@ -631,34 +651,6 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
     }
 }
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol {
-    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
-        let tag = d.read_u8();
-
-        match tag {
-            SYMBOL_STR => {
-                let s = d.read_str();
-                Symbol::intern(s)
-            }
-            SYMBOL_OFFSET => {
-                // read str offset
-                let pos = d.read_usize();
-
-                // move to str offset and read
-                d.opaque.with_position(pos, |d| {
-                    let s = d.read_str();
-                    Symbol::intern(s)
-                })
-            }
-            SYMBOL_PREINTERNED => {
-                let symbol_index = d.read_u32();
-                Symbol::new_from_decoded(symbol_index)
-            }
-            _ => unreachable!(),
-        }
-    }
-}
-
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
         ty::codec::RefDecodable::decode(d)
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index dbd82d3ab79..2ed4385df08 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -125,48 +125,45 @@ impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
     }
 }
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum {
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        if *self != LOCAL_CRATE && s.is_proc_macro {
-            panic!("Attempted to encode non-local CrateNum {self:?} for proc-macro crate");
-        }
         s.emit_u32(self.as_u32());
     }
 }
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        s.emit_u32(self.as_u32());
+impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
+    fn encode_crate_num(&mut self, crate_num: CrateNum) {
+        if crate_num != LOCAL_CRATE && self.is_proc_macro {
+            panic!("Attempted to encode non-local CrateNum {crate_num:?} for proc-macro crate");
+        }
+        self.emit_u32(crate_num.as_u32());
     }
-}
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        s.emit_u32(self.as_u32());
+    fn encode_def_index(&mut self, def_index: DefIndex) {
+        self.emit_u32(def_index.as_u32());
     }
-}
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_ctxt, s);
+    fn encode_def_id(&mut self, def_id: DefId) {
+        def_id.krate.encode(self);
+        def_id.index.encode(self);
     }
-}
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        if self.krate == LOCAL_CRATE {
+    fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) {
+        rustc_span::hygiene::raw_encode_syntax_context(syntax_context, self.hygiene_ctxt, self);
+    }
+
+    fn encode_expn_id(&mut self, expn_id: ExpnId) {
+        if expn_id.krate == LOCAL_CRATE {
             // We will only write details for local expansions. Non-local expansions will fetch
             // data from the corresponding crate's metadata.
             // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
             // metadata from proc-macro crates.
-            s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
+            self.hygiene_ctxt.schedule_expn_data_for_encoding(expn_id);
         }
-        self.krate.encode(s);
-        self.local_id.encode(s);
+        expn_id.krate.encode(self);
+        expn_id.local_id.encode(self);
     }
-}
 
-impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
     fn encode_span(&mut self, span: Span) {
         match self.span_shorthands.entry(span) {
             Entry::Occupied(o) => {
@@ -192,6 +189,29 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
             }
         }
     }
+
+    fn encode_symbol(&mut self, symbol: Symbol) {
+        // if symbol preinterned, emit tag and symbol index
+        if symbol.is_preinterned() {
+            self.opaque.emit_u8(SYMBOL_PREINTERNED);
+            self.opaque.emit_u32(symbol.as_u32());
+        } else {
+            // otherwise write it as string or as offset to it
+            match self.symbol_table.entry(symbol) {
+                Entry::Vacant(o) => {
+                    self.opaque.emit_u8(SYMBOL_STR);
+                    let pos = self.opaque.position();
+                    o.insert(pos);
+                    self.emit_str(symbol.as_str());
+                }
+                Entry::Occupied(o) => {
+                    let x = *o.get();
+                    self.emit_u8(SYMBOL_OFFSET);
+                    self.emit_usize(x);
+                }
+            }
+        }
+    }
 }
 
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
@@ -337,31 +357,6 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
     }
 }
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Symbol {
-    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
-        // if symbol preinterned, emit tag and symbol index
-        if self.is_preinterned() {
-            s.opaque.emit_u8(SYMBOL_PREINTERNED);
-            s.opaque.emit_u32(self.as_u32());
-        } else {
-            // otherwise write it as string or as offset to it
-            match s.symbol_table.entry(*self) {
-                Entry::Vacant(o) => {
-                    s.opaque.emit_u8(SYMBOL_STR);
-                    let pos = s.opaque.position();
-                    o.insert(pos);
-                    s.emit_str(self.as_str());
-                }
-                Entry::Occupied(o) => {
-                    let x = *o.get();
-                    s.emit_u8(SYMBOL_OFFSET);
-                    s.emit_usize(x);
-                }
-            }
-        }
-    }
-}
-
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for [u8] {
     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
         Encoder::emit_usize(e, self.len());
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index f8a34e05eb0..8d084f5f131 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -583,10 +583,10 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
     }
 }
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
-    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Self {
-        let syntax_contexts = decoder.syntax_contexts;
-        rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
+impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
+    fn decode_syntax_context(&mut self) -> SyntaxContext {
+        let syntax_contexts = self.syntax_contexts;
+        rustc_span::hygiene::decode_syntax_context(self, self.hygiene_context, |this, id| {
             // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
             // We look up the position of the associated `SyntaxData` and decode it.
             let pos = syntax_contexts.get(&id).unwrap();
@@ -596,11 +596,9 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
             })
         })
     }
-}
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
-    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Self {
-        let hash = ExpnHash::decode(decoder);
+    fn decode_expn_id(&mut self) -> ExpnId {
+        let hash = ExpnHash::decode(self);
         if hash.is_root() {
             return ExpnId::root();
         }
@@ -609,23 +607,23 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
             return expn_id;
         }
 
-        let krate = decoder.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id());
+        let krate = self.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id());
 
         let expn_id = if krate == LOCAL_CRATE {
             // We look up the position of the associated `ExpnData` and decode it.
-            let pos = decoder
+            let pos = self
                 .expn_data
                 .get(&hash)
-                .unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data));
+                .unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, self.expn_data));
 
-            let data: ExpnData = decoder
-                .with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA));
+            let data: ExpnData =
+                self.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA));
             let expn_id = rustc_span::hygiene::register_local_expn_id(data, hash);
 
             #[cfg(debug_assertions)]
             {
                 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-                let local_hash = decoder.tcx.with_stable_hashing_context(|mut hcx| {
+                let local_hash = self.tcx.with_stable_hashing_context(|mut hcx| {
                     let mut hasher = StableHasher::new();
                     expn_id.expn_data().hash_stable(&mut hcx, &mut hasher);
                     hasher.finish()
@@ -635,9 +633,9 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
 
             expn_id
         } else {
-            let index_guess = decoder.foreign_expn_data[&hash];
-            decoder.tcx.cstore_untracked().expn_hash_to_expn_id(
-                decoder.tcx.sess,
+            let index_guess = self.foreign_expn_data[&hash];
+            self.tcx.cstore_untracked().expn_hash_to_expn_id(
+                self.tcx.sess,
                 krate,
                 index_guess,
                 hash,
@@ -647,9 +645,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
         debug_assert_eq!(expn_id.krate, krate);
         expn_id
     }
-}
 
-impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
     fn decode_span(&mut self) -> Span {
         let ctxt = SyntaxContext::decode(self);
         let parent = Option::<LocalDefId>::decode(self);
@@ -686,72 +682,62 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
 
         Span::new(lo, hi, ctxt, parent)
     }
-}
 
-// copy&paste impl from rustc_metadata
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Symbol {
+    // copy&paste impl from rustc_metadata
     #[inline]
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
-        let tag = d.read_u8();
+    fn decode_symbol(&mut self) -> Symbol {
+        let tag = self.read_u8();
 
         match tag {
             SYMBOL_STR => {
-                let s = d.read_str();
+                let s = self.read_str();
                 Symbol::intern(s)
             }
             SYMBOL_OFFSET => {
                 // read str offset
-                let pos = d.read_usize();
+                let pos = self.read_usize();
 
                 // move to str offset and read
-                d.opaque.with_position(pos, |d| {
+                self.opaque.with_position(pos, |d| {
                     let s = d.read_str();
                     Symbol::intern(s)
                 })
             }
             SYMBOL_PREINTERNED => {
-                let symbol_index = d.read_u32();
+                let symbol_index = self.read_u32();
                 Symbol::new_from_decoded(symbol_index)
             }
             _ => unreachable!(),
         }
     }
-}
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
-    #[inline]
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
-        let stable_id = StableCrateId::decode(d);
-        let cnum = d.tcx.stable_crate_id_to_crate_num(stable_id);
+    fn decode_crate_num(&mut self) -> CrateNum {
+        let stable_id = StableCrateId::decode(self);
+        let cnum = self.tcx.stable_crate_id_to_crate_num(stable_id);
         cnum
     }
-}
 
-// This impl makes sure that we get a runtime error when we try decode a
-// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
-// because we would not know how to transform the `DefIndex` to the current
-// context.
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
-    fn decode(_d: &mut CacheDecoder<'a, 'tcx>) -> DefIndex {
+    // This impl makes sure that we get a runtime error when we try decode a
+    // `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
+    // because we would not know how to transform the `DefIndex` to the current
+    // context.
+    fn decode_def_index(&mut self) -> DefIndex {
         panic!("trying to decode `DefIndex` outside the context of a `DefId`")
     }
-}
 
-// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
-// compilation sessions. We use the `DefPathHash`, which is stable across
-// sessions, to map the old `DefId` to the new one.
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
-    #[inline]
-    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
+    // Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
+    // compilation sessions. We use the `DefPathHash`, which is stable across
+    // sessions, to map the old `DefId` to the new one.
+    fn decode_def_id(&mut self) -> DefId {
         // Load the `DefPathHash` which is was we encoded the `DefId` as.
-        let def_path_hash = DefPathHash::decode(d);
+        let def_path_hash = DefPathHash::decode(self);
 
         // Using the `DefPathHash`, we can lookup the new `DefId`.
         // Subtle: We only encode a `DefId` as part of a query result.
         // If we get to this point, then all of the query inputs were green,
         // which means that the definition with this hash is guaranteed to
         // still exist in the current compilation session.
-        d.tcx.def_path_hash_to_def_id(def_path_hash, &mut || {
+        self.tcx.def_path_hash_to_def_id(def_path_hash, &mut || {
             panic!("Failed to convert DefPathHash {def_path_hash:?}")
         })
     }
@@ -860,20 +846,16 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for SyntaxContext {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
-        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s);
+impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> {
+    fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) {
+        rustc_span::hygiene::raw_encode_syntax_context(syntax_context, self.hygiene_context, self);
     }
-}
 
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for ExpnId {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
-        s.hygiene_context.schedule_expn_data_for_encoding(*self);
-        self.expn_hash().encode(s);
+    fn encode_expn_id(&mut self, expn_id: ExpnId) {
+        self.hygiene_context.schedule_expn_data_for_encoding(expn_id);
+        expn_id.expn_hash().encode(self);
     }
-}
 
-impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> {
     fn encode_span(&mut self, span: Span) {
         let span_data = span.data_untracked();
         span_data.ctxt.encode(self);
@@ -915,32 +897,42 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> {
         col_lo.encode(self);
         len.encode(self);
     }
-}
 
-// copy&paste impl from rustc_metadata
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Symbol {
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
+    // copy&paste impl from rustc_metadata
+    fn encode_symbol(&mut self, symbol: Symbol) {
         // if symbol preinterned, emit tag and symbol index
-        if self.is_preinterned() {
-            s.encoder.emit_u8(SYMBOL_PREINTERNED);
-            s.encoder.emit_u32(self.as_u32());
+        if symbol.is_preinterned() {
+            self.encoder.emit_u8(SYMBOL_PREINTERNED);
+            self.encoder.emit_u32(symbol.as_u32());
         } else {
             // otherwise write it as string or as offset to it
-            match s.symbol_table.entry(*self) {
+            match self.symbol_table.entry(symbol) {
                 Entry::Vacant(o) => {
-                    s.encoder.emit_u8(SYMBOL_STR);
-                    let pos = s.encoder.position();
+                    self.encoder.emit_u8(SYMBOL_STR);
+                    let pos = self.encoder.position();
                     o.insert(pos);
-                    s.emit_str(self.as_str());
+                    self.emit_str(symbol.as_str());
                 }
                 Entry::Occupied(o) => {
                     let x = *o.get();
-                    s.emit_u8(SYMBOL_OFFSET);
-                    s.emit_usize(x);
+                    self.emit_u8(SYMBOL_OFFSET);
+                    self.emit_usize(x);
                 }
             }
         }
     }
+
+    fn encode_crate_num(&mut self, crate_num: CrateNum) {
+        self.tcx.stable_crate_id(crate_num).encode(self);
+    }
+
+    fn encode_def_id(&mut self, def_id: DefId) {
+        self.tcx.def_path_hash(def_id).encode(self);
+    }
+
+    fn encode_def_index(&mut self, _def_index: DefIndex) {
+        bug!("encoding `DefIndex` without context");
+    }
 }
 
 impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> {
@@ -967,26 +959,6 @@ impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for CrateNum {
-    #[inline]
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
-        s.tcx.stable_crate_id(*self).encode(s);
-    }
-}
-
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefId {
-    #[inline]
-    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
-        s.tcx.def_path_hash(*self).encode(s);
-    }
-}
-
-impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefIndex {
-    fn encode(&self, _: &mut CacheEncoder<'a, 'tcx>) {
-        bug!("encoding `DefIndex` without context");
-    }
-}
-
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
         #[inline]
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index e397fab5459..b498202dc92 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,11 +1,11 @@
-use crate::{HashStableContext, Symbol};
+use crate::{HashStableContext, SpanDecoder, SpanEncoder, Symbol};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::unhash::Unhasher;
 use rustc_data_structures::AtomicRef;
 use rustc_index::Idx;
 use rustc_macros::HashStable_Generic;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{Decodable, Encodable};
 use std::fmt;
 use std::hash::{BuildHasherDefault, Hash, Hasher};
 
@@ -46,20 +46,6 @@ 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) {
-        s.emit_u32(self.as_u32());
-    }
-}
-
-impl<D: Decoder> Decodable<D> for CrateNum {
-    default fn decode(d: &mut D) -> CrateNum {
-        CrateNum::from_u32(d.read_u32())
-    }
-}
-
 /// A `DefPathHash` is a fixed-size representation of a `DefPath` that is
 /// stable across crate and compilation session boundaries. It consists of two
 /// separate 64-bit hashes. The first uniquely identifies the crate this
@@ -220,18 +206,6 @@ rustc_index::newtype_index! {
     }
 }
 
-impl<E: Encoder> Encodable<E> for DefIndex {
-    default fn encode(&self, _: &mut E) {
-        panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
-    }
-}
-
-impl<D: Decoder> Decodable<D> for DefIndex {
-    default fn decode(_: &mut D) -> DefIndex {
-        panic!("cannot decode `DefIndex` with `{}`", std::any::type_name::<D>());
-    }
-}
-
 /// A `DefId` identifies a particular *definition*, by combining a crate
 /// index and a def index.
 ///
@@ -347,19 +321,6 @@ impl From<LocalDefId> for DefId {
     }
 }
 
-impl<E: Encoder> Encodable<E> for DefId {
-    default fn encode(&self, s: &mut E) {
-        self.krate.encode(s);
-        self.index.encode(s);
-    }
-}
-
-impl<D: Decoder> Decodable<D> for DefId {
-    default fn decode(d: &mut D) -> DefId {
-        DefId { krate: Decodable::decode(d), index: Decodable::decode(d) }
-    }
-}
-
 pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
 }
@@ -423,13 +384,13 @@ impl fmt::Debug for LocalDefId {
     }
 }
 
-impl<E: Encoder> Encodable<E> for LocalDefId {
+impl<E: SpanEncoder> Encodable<E> for LocalDefId {
     fn encode(&self, s: &mut E) {
         self.to_def_id().encode(s);
     }
 }
 
-impl<D: Decoder> Decodable<D> for LocalDefId {
+impl<D: SpanDecoder> Decodable<D> for LocalDefId {
     fn decode(d: &mut D) -> LocalDefId {
         DefId::decode(d).expect_local()
     }
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index b717229b68d..c4557017c87 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -27,7 +27,7 @@
 use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
 use crate::edition::Edition;
 use crate::symbol::{kw, sym, Symbol};
-use crate::{with_session_globals, HashStableContext, Span, DUMMY_SP};
+use crate::{with_session_globals, HashStableContext, Span, SpanDecoder, SpanEncoder, DUMMY_SP};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, StableHasher};
@@ -1431,30 +1431,18 @@ fn for_all_expns_in(
     }
 }
 
-impl<E: Encoder> Encodable<E> for LocalExpnId {
+impl<E: SpanEncoder> Encodable<E> for LocalExpnId {
     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) {
-        panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
-    }
-}
-
-impl<D: Decoder> Decodable<D> for LocalExpnId {
+impl<D: SpanDecoder> Decodable<D> for LocalExpnId {
     fn decode(d: &mut D) -> Self {
         ExpnId::expect_local(ExpnId::decode(d))
     }
 }
 
-impl<D: Decoder> Decodable<D> for ExpnId {
-    default fn decode(_: &mut D) -> Self {
-        panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
-    }
-}
-
 pub fn raw_encode_syntax_context<E: Encoder>(
     ctxt: SyntaxContext,
     context: &HygieneEncodeContext,
@@ -1466,18 +1454,6 @@ pub fn raw_encode_syntax_context<E: Encoder>(
     ctxt.0.encode(e);
 }
 
-impl<E: Encoder> Encodable<E> for SyntaxContext {
-    default fn encode(&self, _: &mut E) {
-        panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
-    }
-}
-
-impl<D: Decoder> Decodable<D> for SyntaxContext {
-    default fn decode(_: &mut D) -> Self {
-        panic!("cannot decode `SyntaxContext` with `{}`", std::any::type_name::<D>());
-    }
-}
-
 /// Updates the `disambiguator` field of the corresponding `ExpnData`
 /// such that the `Fingerprint` of the `ExpnData` does not collide with
 /// any other `ExpnIds`.
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 0eafbae6e82..18d1f14cf44 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -61,7 +61,7 @@ pub use hygiene::{DesugaringKind, ExpnKind, MacroKind};
 pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
 use rustc_data_structures::stable_hasher::HashingControls;
 pub mod def_id;
-use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, StableCrateId, LOCAL_CRATE};
+use def_id::{CrateNum, DefId, DefIndex, DefPathHash, LocalDefId, StableCrateId, LOCAL_CRATE};
 pub mod edit_distance;
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
@@ -1021,6 +1021,14 @@ impl Default for Span {
 
 pub trait SpanEncoder: Encoder {
     fn encode_span(&mut self, span: Span);
+    fn encode_symbol(&mut self, symbol: Symbol);
+    fn encode_expn_id(&mut self, expn_id: ExpnId);
+    fn encode_syntax_context(&mut self, syntax_context: SyntaxContext);
+    /// 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`.
+    fn encode_crate_num(&mut self, crate_num: CrateNum);
+    fn encode_def_index(&mut self, def_index: DefIndex);
+    fn encode_def_id(&mut self, def_id: DefId);
 }
 
 impl SpanEncoder for FileEncoder {
@@ -1029,6 +1037,31 @@ impl SpanEncoder for FileEncoder {
         span.lo.encode(self);
         span.hi.encode(self);
     }
+
+    fn encode_symbol(&mut self, symbol: Symbol) {
+        self.emit_str(symbol.as_str());
+    }
+
+    fn encode_expn_id(&mut self, _expn_id: ExpnId) {
+        panic!("cannot encode `ExpnId` with `FileEncoder`");
+    }
+
+    fn encode_syntax_context(&mut self, _syntax_context: SyntaxContext) {
+        panic!("cannot encode `SyntaxContext` with `FileEncoder`");
+    }
+
+    fn encode_crate_num(&mut self, crate_num: CrateNum) {
+        self.emit_u32(crate_num.as_u32());
+    }
+
+    fn encode_def_index(&mut self, _def_index: DefIndex) {
+        panic!("cannot encode `DefIndex` with `FileEncoder`");
+    }
+
+    fn encode_def_id(&mut self, def_id: DefId) {
+        def_id.krate.encode(self);
+        def_id.index.encode(self);
+    }
 }
 
 impl<E: SpanEncoder> Encodable<E> for Span {
@@ -1037,8 +1070,50 @@ impl<E: SpanEncoder> Encodable<E> for Span {
     }
 }
 
+impl<E: SpanEncoder> Encodable<E> for Symbol {
+    fn encode(&self, s: &mut E) {
+        s.encode_symbol(*self);
+    }
+}
+
+impl<E: SpanEncoder> Encodable<E> for ExpnId {
+    fn encode(&self, s: &mut E) {
+        s.encode_expn_id(*self)
+    }
+}
+
+impl<E: SpanEncoder> Encodable<E> for SyntaxContext {
+    fn encode(&self, s: &mut E) {
+        s.encode_syntax_context(*self)
+    }
+}
+
+impl<E: SpanEncoder> Encodable<E> for CrateNum {
+    fn encode(&self, s: &mut E) {
+        s.encode_crate_num(*self)
+    }
+}
+
+impl<E: SpanEncoder> Encodable<E> for DefIndex {
+    fn encode(&self, s: &mut E) {
+        s.encode_def_index(*self)
+    }
+}
+
+impl<E: SpanEncoder> Encodable<E> for DefId {
+    fn encode(&self, s: &mut E) {
+        s.encode_def_id(*self)
+    }
+}
+
 pub trait SpanDecoder: Decoder {
     fn decode_span(&mut self) -> Span;
+    fn decode_symbol(&mut self) -> Symbol;
+    fn decode_expn_id(&mut self) -> ExpnId;
+    fn decode_syntax_context(&mut self) -> SyntaxContext;
+    fn decode_crate_num(&mut self) -> CrateNum;
+    fn decode_def_index(&mut self) -> DefIndex;
+    fn decode_def_id(&mut self) -> DefId;
 }
 
 impl SpanDecoder for MemDecoder<'_> {
@@ -1048,6 +1123,30 @@ impl SpanDecoder for MemDecoder<'_> {
 
         Span::new(lo, hi, SyntaxContext::root(), None)
     }
+
+    fn decode_symbol(&mut self) -> Symbol {
+        Symbol::intern(self.read_str())
+    }
+
+    fn decode_expn_id(&mut self) -> ExpnId {
+        panic!("cannot decode `ExpnId` with `MemDecoder`");
+    }
+
+    fn decode_syntax_context(&mut self) -> SyntaxContext {
+        panic!("cannot decode `SyntaxContext` with `MemDecoder`");
+    }
+
+    fn decode_crate_num(&mut self) -> CrateNum {
+        CrateNum::from_u32(self.read_u32())
+    }
+
+    fn decode_def_index(&mut self) -> DefIndex {
+        panic!("cannot decode `DefIndex` with `MemDecoder`");
+    }
+
+    fn decode_def_id(&mut self) -> DefId {
+        DefId { krate: Decodable::decode(self), index: Decodable::decode(self) }
+    }
 }
 
 impl<D: SpanDecoder> Decodable<D> for Span {
@@ -1056,6 +1155,42 @@ impl<D: SpanDecoder> Decodable<D> for Span {
     }
 }
 
+impl<D: SpanDecoder> Decodable<D> for Symbol {
+    fn decode(s: &mut D) -> Symbol {
+        s.decode_symbol()
+    }
+}
+
+impl<D: SpanDecoder> Decodable<D> for ExpnId {
+    fn decode(s: &mut D) -> ExpnId {
+        s.decode_expn_id()
+    }
+}
+
+impl<D: SpanDecoder> Decodable<D> for SyntaxContext {
+    fn decode(s: &mut D) -> SyntaxContext {
+        s.decode_syntax_context()
+    }
+}
+
+impl<D: SpanDecoder> Decodable<D> for CrateNum {
+    fn decode(s: &mut D) -> CrateNum {
+        s.decode_crate_num()
+    }
+}
+
+impl<D: SpanDecoder> Decodable<D> for DefIndex {
+    fn decode(s: &mut D) -> DefIndex {
+        s.decode_def_index()
+    }
+}
+
+impl<D: SpanDecoder> Decodable<D> for DefId {
+    fn decode(s: &mut D) -> DefId {
+        s.decode_def_id()
+    }
+}
+
 /// Insert `source_map` into the session globals for the duration of the
 /// closure's execution.
 pub fn set_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0b44071496e..6e59806cf07 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::sync::Lock;
 use rustc_macros::HashStable_Generic;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
 use std::fmt;
 use std::hash::{Hash, Hasher};
@@ -2075,19 +2074,6 @@ impl ToString for Symbol {
     }
 }
 
-impl<S: Encoder> Encodable<S> for Symbol {
-    default fn encode(&self, s: &mut S) {
-        s.emit_str(self.as_str());
-    }
-}
-
-impl<D: Decoder> Decodable<D> for Symbol {
-    #[inline]
-    default fn decode(d: &mut D) -> Symbol {
-        Symbol::intern(d.read_str())
-    }
-}
-
 impl<CTX> HashStable<CTX> for Symbol {
     #[inline]
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {