]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/query/on_disk_cache.rs
Rollup merge of #84442 - jyn514:doc-cfg, r=petrochenkov
[rust.git] / compiler / rustc_middle / src / ty / query / on_disk_cache.rs
1 use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
2 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
3 use crate::mir::{self, interpret};
4 use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
5 use crate::ty::context::TyCtxt;
6 use crate::ty::{self, Ty};
7 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
8 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
9 use rustc_data_structures::thin_vec::ThinVec;
10 use rustc_data_structures::unhash::UnhashMap;
11 use rustc_errors::Diagnostic;
12 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
13 use rustc_hir::definitions::DefPathHash;
14 use rustc_hir::definitions::Definitions;
15 use rustc_index::vec::{Idx, IndexVec};
16 use rustc_query_system::dep_graph::DepContext;
17 use rustc_query_system::query::QueryContext;
18 use rustc_serialize::{
19     opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
20     Decodable, Decoder, Encodable, Encoder,
21 };
22 use rustc_session::{CrateDisambiguator, Session};
23 use rustc_span::hygiene::{
24     ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
25     SyntaxContext, SyntaxContextData,
26 };
27 use rustc_span::source_map::{SourceMap, StableSourceFileId};
28 use rustc_span::CachingSourceMapView;
29 use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP};
30 use std::collections::hash_map::Entry;
31 use std::iter::FromIterator;
32 use std::mem;
33
34 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
35
36 // A normal span encoded with both location information and a `SyntaxContext`
37 const TAG_FULL_SPAN: u8 = 0;
38 // A partial span with no location information, encoded only with a `SyntaxContext`
39 const TAG_PARTIAL_SPAN: u8 = 1;
40
41 const TAG_SYNTAX_CONTEXT: u8 = 0;
42 const TAG_EXPN_DATA: u8 = 1;
43
44 /// Provides an interface to incremental compilation data cached from the
45 /// previous compilation session. This data will eventually include the results
46 /// of a few selected queries (like `typeck` and `mir_optimized`) and
47 /// any diagnostics that have been emitted during a query.
48 pub struct OnDiskCache<'sess> {
49     // The complete cache data in serialized form.
50     serialized_data: Vec<u8>,
51
52     // Collects all `Diagnostic`s emitted during the current compilation
53     // session.
54     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
55
56     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
57     cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
58
59     source_map: &'sess SourceMap,
60     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
61
62     // Caches that are populated lazily during decoding.
63     file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
64
65     // A map from dep-node to the position of the cached query result in
66     // `serialized_data`.
67     query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
68
69     // A map from dep-node to the position of any associated diagnostics in
70     // `serialized_data`.
71     prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
72
73     alloc_decoding_state: AllocDecodingState,
74
75     // A map from syntax context ids to the position of their associated
76     // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext`
77     // to represent the fact that we are storing *encoded* ids. When we decode
78     // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
79     // which will almost certainly be different than the serialized id.
80     syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
81     // A map from the `DefPathHash` of an `ExpnId` to the position
82     // of their associated `ExpnData`. Ideally, we would store a `DefId`,
83     // but we need to decode this before we've constructed a `TyCtxt` (which
84     // makes it difficult to decode a `DefId`).
85
86     // Note that these `DefPathHashes` correspond to both local and foreign
87     // `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
88     // we could look up the `ExpnData` from the metadata of foreign crates,
89     // but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
90     expn_data: FxHashMap<u32, AbsoluteBytePos>,
91     // Additional information used when decoding hygiene data.
92     hygiene_context: HygieneDecodeContext,
93     // Maps `DefPathHash`es to their `RawDefId`s from the *previous*
94     // compilation session. This is used as an initial 'guess' when
95     // we try to map a `DefPathHash` to its `DefId` in the current compilation
96     // session.
97     foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
98
99     // The *next* compilation sessison's `foreign_def_path_hashes` - at
100     // the end of our current compilation session, this will get written
101     // out to the `foreign_def_path_hashes` field of the `Footer`, which
102     // will become `foreign_def_path_hashes` of the next compilation session.
103     // This stores any `DefPathHash` that we may need to map to a `DefId`
104     // during the next compilation session.
105     latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
106
107     // Maps `DefPathHashes` to their corresponding `LocalDefId`s for all
108     // local items in the current compilation session. This is only populated
109     // when we are in incremental mode and have loaded a pre-existing cache
110     // from disk, since this map is only used when deserializing a `DefPathHash`
111     // from the incremental cache.
112     local_def_path_hash_to_def_id: UnhashMap<DefPathHash, LocalDefId>,
113     // Caches all lookups of `DefPathHashes`, both for local and foreign
114     // definitions. A definition from the previous compilation session
115     // may no longer exist in the current compilation session, so
116     // we use `Option<DefId>` so that we can cache a lookup failure.
117     def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
118 }
119
120 // This type is used only for serialization and deserialization.
121 #[derive(Encodable, Decodable)]
122 struct Footer {
123     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
124     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
125     query_result_index: EncodedQueryResultIndex,
126     diagnostics_index: EncodedQueryResultIndex,
127     // The location of all allocations.
128     interpret_alloc_index: Vec<u32>,
129     // See `OnDiskCache.syntax_contexts`
130     syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
131     // See `OnDiskCache.expn_data`
132     expn_data: FxHashMap<u32, AbsoluteBytePos>,
133     foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
134 }
135
136 pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
137 type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
138 type EncodedDiagnostics = Vec<Diagnostic>;
139
140 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
141 struct SourceFileIndex(u32);
142
143 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
144 pub struct AbsoluteBytePos(u32);
145
146 impl AbsoluteBytePos {
147     fn new(pos: usize) -> AbsoluteBytePos {
148         debug_assert!(pos <= u32::MAX as usize);
149         AbsoluteBytePos(pos as u32)
150     }
151
152     fn to_usize(self) -> usize {
153         self.0 as usize
154     }
155 }
156
157 /// Represents a potentially invalid `DefId`. This is used during incremental
158 /// compilation to represent a `DefId` from the *previous* compilation session,
159 /// which may no longer be valid. This is used to help map a `DefPathHash`
160 /// to a `DefId` in the current compilation session.
161 #[derive(Encodable, Decodable, Copy, Clone, Debug)]
162 crate struct RawDefId {
163     // We deliberately do not use `CrateNum` and `DefIndex`
164     // here, since a crate/index from the previous compilation
165     // session may no longer exist.
166     pub krate: u32,
167     pub index: u32,
168 }
169
170 fn make_local_def_path_hash_map(definitions: &Definitions) -> UnhashMap<DefPathHash, LocalDefId> {
171     UnhashMap::from_iter(
172         definitions
173             .def_path_table()
174             .all_def_path_hashes_and_def_ids(LOCAL_CRATE)
175             .map(|(hash, def_id)| (hash, def_id.as_local().unwrap())),
176     )
177 }
178
179 impl<'sess> OnDiskCache<'sess> {
180     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
181     pub fn new(
182         sess: &'sess Session,
183         data: Vec<u8>,
184         start_pos: usize,
185         definitions: &Definitions,
186     ) -> Self {
187         debug_assert!(sess.opts.incremental.is_some());
188
189         // Wrap in a scope so we can borrow `data`.
190         let footer: Footer = {
191             let mut decoder = opaque::Decoder::new(&data[..], start_pos);
192
193             // Decode the *position* of the footer, which can be found in the
194             // last 8 bytes of the file.
195             decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
196             let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder)
197                 .expect("error while trying to decode footer position")
198                 .0 as usize;
199
200             // Decode the file footer, which contains all the lookup tables, etc.
201             decoder.set_position(footer_pos);
202
203             decode_tagged(&mut decoder, TAG_FILE_FOOTER)
204                 .expect("error while trying to decode footer position")
205         };
206
207         Self {
208             serialized_data: data,
209             file_index_to_stable_id: footer.file_index_to_stable_id,
210             file_index_to_file: Default::default(),
211             prev_cnums: footer.prev_cnums,
212             cnum_map: OnceCell::new(),
213             source_map: sess.source_map(),
214             current_diagnostics: Default::default(),
215             query_result_index: footer.query_result_index.into_iter().collect(),
216             prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
217             alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
218             syntax_contexts: footer.syntax_contexts,
219             expn_data: footer.expn_data,
220             hygiene_context: Default::default(),
221             foreign_def_path_hashes: footer.foreign_def_path_hashes,
222             latest_foreign_def_path_hashes: Default::default(),
223             local_def_path_hash_to_def_id: make_local_def_path_hash_map(definitions),
224             def_path_hash_to_def_id_cache: Default::default(),
225         }
226     }
227
228     pub fn new_empty(source_map: &'sess SourceMap) -> Self {
229         Self {
230             serialized_data: Vec::new(),
231             file_index_to_stable_id: Default::default(),
232             file_index_to_file: Default::default(),
233             prev_cnums: vec![],
234             cnum_map: OnceCell::new(),
235             source_map,
236             current_diagnostics: Default::default(),
237             query_result_index: Default::default(),
238             prev_diagnostics_index: Default::default(),
239             alloc_decoding_state: AllocDecodingState::new(Vec::new()),
240             syntax_contexts: FxHashMap::default(),
241             expn_data: FxHashMap::default(),
242             hygiene_context: Default::default(),
243             foreign_def_path_hashes: Default::default(),
244             latest_foreign_def_path_hashes: Default::default(),
245             local_def_path_hash_to_def_id: Default::default(),
246             def_path_hash_to_def_id_cache: Default::default(),
247         }
248     }
249
250     pub fn serialize<'tcx>(
251         &self,
252         tcx: TyCtxt<'tcx>,
253         encoder: &mut FileEncoder,
254     ) -> FileEncodeResult {
255         // Serializing the `DepGraph` should not modify it.
256         tcx.dep_graph.with_ignore(|| {
257             // Allocate `SourceFileIndex`es.
258             let (file_to_file_index, file_index_to_stable_id) = {
259                 let files = tcx.sess.source_map().files();
260                 let mut file_to_file_index =
261                     FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
262                 let mut file_index_to_stable_id =
263                     FxHashMap::with_capacity_and_hasher(files.len(), Default::default());
264
265                 for (index, file) in files.iter().enumerate() {
266                     let index = SourceFileIndex(index as u32);
267                     let file_ptr: *const SourceFile = &**file as *const _;
268                     file_to_file_index.insert(file_ptr, index);
269                     file_index_to_stable_id.insert(index, StableSourceFileId::new(&file));
270                 }
271
272                 (file_to_file_index, file_index_to_stable_id)
273             };
274
275             // Register any dep nodes that we reused from the previous session,
276             // but didn't `DepNode::construct` in this session. This ensures
277             // that their `DefPathHash` to `RawDefId` mappings are registered
278             // in 'latest_foreign_def_path_hashes' if necessary, since that
279             // normally happens in `DepNode::construct`.
280             tcx.dep_graph.register_reused_dep_nodes(tcx);
281
282             // Load everything into memory so we can write it out to the on-disk
283             // cache. The vast majority of cacheable query results should already
284             // be in memory, so this should be a cheap operation.
285             // Do this *before* we clone 'latest_foreign_def_path_hashes', since
286             // loading existing queries may cause us to create new DepNodes, which
287             // may in turn end up invoking `store_foreign_def_id_hash`
288             tcx.queries.exec_cache_promotions(tcx);
289
290             let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
291             let hygiene_encode_context = HygieneEncodeContext::default();
292
293             let mut encoder = CacheEncoder {
294                 tcx,
295                 encoder,
296                 type_shorthands: Default::default(),
297                 predicate_shorthands: Default::default(),
298                 interpret_allocs: Default::default(),
299                 source_map: CachingSourceMapView::new(tcx.sess.source_map()),
300                 file_to_file_index,
301                 hygiene_context: &hygiene_encode_context,
302                 latest_foreign_def_path_hashes,
303             };
304
305             // Encode query results.
306             let mut query_result_index = EncodedQueryResultIndex::new();
307
308             tcx.sess.time("encode_query_results", || -> FileEncodeResult {
309                 let enc = &mut encoder;
310                 let qri = &mut query_result_index;
311                 tcx.queries.encode_query_results(tcx, enc, qri)
312             })?;
313
314             // Encode diagnostics.
315             let diagnostics_index: EncodedDiagnosticsIndex = self
316                 .current_diagnostics
317                 .borrow()
318                 .iter()
319                 .map(
320                     |(dep_node_index, diagnostics)| -> Result<_, <FileEncoder as Encoder>::Error> {
321                         let pos = AbsoluteBytePos::new(encoder.position());
322                         // Let's make sure we get the expected type here.
323                         let diagnostics: &EncodedDiagnostics = diagnostics;
324                         let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
325                         encoder.encode_tagged(dep_node_index, diagnostics)?;
326
327                         Ok((dep_node_index, pos))
328                     },
329                 )
330                 .collect::<Result<_, _>>()?;
331
332             let interpret_alloc_index = {
333                 let mut interpret_alloc_index = Vec::new();
334                 let mut n = 0;
335                 loop {
336                     let new_n = encoder.interpret_allocs.len();
337                     // If we have found new IDs, serialize those too.
338                     if n == new_n {
339                         // Otherwise, abort.
340                         break;
341                     }
342                     interpret_alloc_index.reserve(new_n - n);
343                     for idx in n..new_n {
344                         let id = encoder.interpret_allocs[idx];
345                         let pos = encoder.position() as u32;
346                         interpret_alloc_index.push(pos);
347                         interpret::specialized_encode_alloc_id(&mut encoder, tcx, id)?;
348                     }
349                     n = new_n;
350                 }
351                 interpret_alloc_index
352             };
353
354             let sorted_cnums = sorted_cnums_including_local_crate(tcx);
355             let prev_cnums: Vec<_> = sorted_cnums
356                 .iter()
357                 .map(|&cnum| {
358                     let crate_name = tcx.original_crate_name(cnum).to_string();
359                     let crate_disambiguator = tcx.crate_disambiguator(cnum);
360                     (cnum.as_u32(), crate_name, crate_disambiguator)
361                 })
362                 .collect();
363
364             let mut syntax_contexts = FxHashMap::default();
365             let mut expn_ids = FxHashMap::default();
366
367             // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
368             // session.
369
370             hygiene_encode_context.encode(
371                 &mut encoder,
372                 |encoder, index, ctxt_data| -> FileEncodeResult {
373                     let pos = AbsoluteBytePos::new(encoder.position());
374                     encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data)?;
375                     syntax_contexts.insert(index, pos);
376                     Ok(())
377                 },
378                 |encoder, index, expn_data| -> FileEncodeResult {
379                     let pos = AbsoluteBytePos::new(encoder.position());
380                     encoder.encode_tagged(TAG_EXPN_DATA, expn_data)?;
381                     expn_ids.insert(index, pos);
382                     Ok(())
383                 },
384             )?;
385
386             let foreign_def_path_hashes =
387                 std::mem::take(&mut encoder.latest_foreign_def_path_hashes);
388
389             // `Encode the file footer.
390             let footer_pos = encoder.position() as u64;
391             encoder.encode_tagged(
392                 TAG_FILE_FOOTER,
393                 &Footer {
394                     file_index_to_stable_id,
395                     prev_cnums,
396                     query_result_index,
397                     diagnostics_index,
398                     interpret_alloc_index,
399                     syntax_contexts,
400                     expn_data: expn_ids,
401                     foreign_def_path_hashes,
402                 },
403             )?;
404
405             // Encode the position of the footer as the last 8 bytes of the
406             // file so we know where to look for it.
407             IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
408
409             // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
410             // of the footer must be the last thing in the data stream.
411
412             return Ok(());
413
414             fn sorted_cnums_including_local_crate(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
415                 let mut cnums = vec![LOCAL_CRATE];
416                 cnums.extend_from_slice(tcx.crates());
417                 cnums.sort_unstable();
418                 // Just to be sure...
419                 cnums.dedup();
420                 cnums
421             }
422         })
423     }
424
425     /// Loads a diagnostic emitted during the previous compilation session.
426     pub fn load_diagnostics(
427         &self,
428         tcx: TyCtxt<'_>,
429         dep_node_index: SerializedDepNodeIndex,
430     ) -> Vec<Diagnostic> {
431         let diagnostics: Option<EncodedDiagnostics> =
432             self.load_indexed(tcx, dep_node_index, &self.prev_diagnostics_index, "diagnostics");
433
434         diagnostics.unwrap_or_default()
435     }
436
437     /// Stores a diagnostic emitted during the current compilation session.
438     /// Anything stored like this will be available via `load_diagnostics` in
439     /// the next compilation session.
440     #[inline(never)]
441     #[cold]
442     pub fn store_diagnostics(
443         &self,
444         dep_node_index: DepNodeIndex,
445         diagnostics: ThinVec<Diagnostic>,
446     ) {
447         let mut current_diagnostics = self.current_diagnostics.borrow_mut();
448         let prev = current_diagnostics.insert(dep_node_index, diagnostics.into());
449         debug_assert!(prev.is_none());
450     }
451
452     fn get_raw_def_id(&self, hash: &DefPathHash) -> Option<RawDefId> {
453         self.foreign_def_path_hashes.get(hash).copied()
454     }
455
456     fn try_remap_cnum(&self, tcx: TyCtxt<'_>, cnum: u32) -> Option<CrateNum> {
457         let cnum_map =
458             self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
459         debug!("try_remap_cnum({}): cnum_map={:?}", cnum, cnum_map);
460
461         cnum_map[CrateNum::from_u32(cnum)]
462     }
463
464     pub(crate) fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
465         // We may overwrite an existing entry, but it will have the same value,
466         // so it's fine
467         self.latest_foreign_def_path_hashes
468             .lock()
469             .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
470     }
471
472     /// If the given `dep_node`'s hash still exists in the current compilation,
473     /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
474     ///
475     /// Normally, `store_foreign_def_id_hash` can be called directly by
476     /// the dependency graph when we construct a `DepNode`. However,
477     /// when we re-use a deserialized `DepNode` from the previous compilation
478     /// session, we only have the `DefPathHash` available. This method is used
479     /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
480     /// out for usage in the next compilation session.
481     pub fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) {
482         // For reused dep nodes, we only need to store the mapping if the node
483         // is one whose query key we can reconstruct from the hash. We use the
484         // mapping to aid that reconstruction in the next session. While we also
485         // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
486         // they're already registered during `DefId` encoding.
487         if dep_node.kind.can_reconstruct_query_key() {
488             let hash = DefPathHash(dep_node.hash.into());
489
490             // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
491             // `latest_foreign_def_path_hashes`, since the `RawDefId` might have
492             // changed in the current compilation session (e.g. we've added/removed crates,
493             // or added/removed definitions before/after the target definition).
494             if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
495                 if !def_id.is_local() {
496                     self.store_foreign_def_id_hash(def_id, hash);
497                 }
498             }
499         }
500     }
501
502     /// Returns the cached query result if there is something in the cache for
503     /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
504     pub fn try_load_query_result<'tcx, T>(
505         &self,
506         tcx: TyCtxt<'tcx>,
507         dep_node_index: SerializedDepNodeIndex,
508     ) -> Option<T>
509     where
510         T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
511     {
512         self.load_indexed(tcx, dep_node_index, &self.query_result_index, "query result")
513     }
514
515     /// Stores a diagnostic emitted during computation of an anonymous query.
516     /// Since many anonymous queries can share the same `DepNode`, we aggregate
517     /// them -- as opposed to regular queries where we assume that there is a
518     /// 1:1 relationship between query-key and `DepNode`.
519     #[inline(never)]
520     #[cold]
521     pub fn store_diagnostics_for_anon_node(
522         &self,
523         dep_node_index: DepNodeIndex,
524         diagnostics: ThinVec<Diagnostic>,
525     ) {
526         let mut current_diagnostics = self.current_diagnostics.borrow_mut();
527
528         let x = current_diagnostics.entry(dep_node_index).or_default();
529
530         x.extend(Into::<Vec<_>>::into(diagnostics));
531     }
532
533     fn load_indexed<'tcx, T>(
534         &self,
535         tcx: TyCtxt<'tcx>,
536         dep_node_index: SerializedDepNodeIndex,
537         index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
538         debug_tag: &'static str,
539     ) -> Option<T>
540     where
541         T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
542     {
543         let pos = index.get(&dep_node_index).cloned()?;
544
545         self.with_decoder(tcx, pos, |decoder| match decode_tagged(decoder, dep_node_index) {
546             Ok(v) => Some(v),
547             Err(e) => bug!("could not decode cached {}: {}", debug_tag, e),
548         })
549     }
550
551     fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
552         &'sess self,
553         tcx: TyCtxt<'tcx>,
554         pos: AbsoluteBytePos,
555         f: F,
556     ) -> T
557     where
558         T: Decodable<CacheDecoder<'a, 'tcx>>,
559     {
560         let cnum_map =
561             self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
562
563         let mut decoder = CacheDecoder {
564             tcx,
565             opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
566             source_map: self.source_map,
567             cnum_map,
568             file_index_to_file: &self.file_index_to_file,
569             file_index_to_stable_id: &self.file_index_to_stable_id,
570             alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
571             syntax_contexts: &self.syntax_contexts,
572             expn_data: &self.expn_data,
573             hygiene_context: &self.hygiene_context,
574         };
575         f(&mut decoder)
576     }
577
578     // This function builds mapping from previous-session-`CrateNum` to
579     // current-session-`CrateNum`. There might be `CrateNum`s from the previous
580     // `Session` that don't occur in the current one. For these, the mapping
581     // maps to None.
582     fn compute_cnum_map(
583         tcx: TyCtxt<'_>,
584         prev_cnums: &[(u32, String, CrateDisambiguator)],
585     ) -> IndexVec<CrateNum, Option<CrateNum>> {
586         tcx.dep_graph.with_ignore(|| {
587             let current_cnums = tcx
588                 .all_crate_nums(LOCAL_CRATE)
589                 .iter()
590                 .map(|&cnum| {
591                     let crate_name = tcx.original_crate_name(cnum).to_string();
592                     let crate_disambiguator = tcx.crate_disambiguator(cnum);
593                     ((crate_name, crate_disambiguator), cnum)
594                 })
595                 .collect::<FxHashMap<_, _>>();
596
597             let map_size = prev_cnums.iter().map(|&(cnum, ..)| cnum).max().unwrap_or(0) + 1;
598             let mut map = IndexVec::from_elem_n(None, map_size as usize);
599
600             for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
601                 let key = (crate_name.clone(), crate_disambiguator);
602                 map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
603             }
604
605             map[LOCAL_CRATE] = Some(LOCAL_CRATE);
606             map
607         })
608     }
609
610     /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
611     /// session, if it still exists. This is used during incremental compilation to
612     /// turn a deserialized `DefPathHash` into its current `DefId`.
613     pub(crate) fn def_path_hash_to_def_id(
614         &self,
615         tcx: TyCtxt<'tcx>,
616         hash: DefPathHash,
617     ) -> Option<DefId> {
618         let mut cache = self.def_path_hash_to_def_id_cache.lock();
619         match cache.entry(hash) {
620             Entry::Occupied(e) => *e.get(),
621             Entry::Vacant(e) => {
622                 debug!("def_path_hash_to_def_id({:?})", hash);
623                 // Check if the `DefPathHash` corresponds to a definition in the current
624                 // crate
625                 if let Some(def_id) = self.local_def_path_hash_to_def_id.get(&hash).cloned() {
626                     let def_id = def_id.to_def_id();
627                     e.insert(Some(def_id));
628                     return Some(def_id);
629                 }
630                 // This `raw_def_id` represents the `DefId` of this `DefPathHash` in
631                 // the *previous* compliation session. The `DefPathHash` includes the
632                 // owning crate, so if the corresponding definition still exists in the
633                 // current compilation session, the crate is guaranteed to be the same
634                 // (otherwise, we would compute a different `DefPathHash`).
635                 let raw_def_id = self.get_raw_def_id(&hash)?;
636                 debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
637                 // If the owning crate no longer exists, the corresponding definition definitely
638                 // no longer exists.
639                 let krate = self.try_remap_cnum(tcx, raw_def_id.krate)?;
640                 debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
641                 // If our `DefPathHash` corresponded to a definition in the local crate,
642                 // we should have either found it in `local_def_path_hash_to_def_id`, or
643                 // never attempted to load it in the first place. Any query result or `DepNode`
644                 // that references a local `DefId` should depend on some HIR-related `DepNode`.
645                 // If a local definition is removed/modified such that its old `DefPathHash`
646                 // no longer has a corresponding definition, that HIR-related `DepNode` should
647                 // end up red. This should prevent us from ever calling
648                 // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
649                 // queries involved.
650                 debug_assert_ne!(krate, LOCAL_CRATE);
651                 // Try to find a definition in the current session, using the previous `DefIndex`
652                 // as an initial guess.
653                 let opt_def_id = tcx.cstore.def_path_hash_to_def_id(krate, raw_def_id.index, hash);
654                 debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
655                 e.insert(opt_def_id);
656                 opt_def_id
657             }
658         }
659     }
660 }
661
662 //- DECODING -------------------------------------------------------------------
663
664 /// A decoder that can read from the incremental compilation cache. It is similar to the one
665 /// we use for crate metadata decoding in that it can rebase spans and eventually
666 /// will also handle things that contain `Ty` instances.
667 pub struct CacheDecoder<'a, 'tcx> {
668     tcx: TyCtxt<'tcx>,
669     opaque: opaque::Decoder<'a>,
670     source_map: &'a SourceMap,
671     cnum_map: &'a IndexVec<CrateNum, Option<CrateNum>>,
672     file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
673     file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, StableSourceFileId>,
674     alloc_decoding_session: AllocDecodingSession<'a>,
675     syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
676     expn_data: &'a FxHashMap<u32, AbsoluteBytePos>,
677     hygiene_context: &'a HygieneDecodeContext,
678 }
679
680 impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
681     fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
682         let CacheDecoder {
683             ref file_index_to_file,
684             ref file_index_to_stable_id,
685             ref source_map,
686             ..
687         } = *self;
688
689         file_index_to_file
690             .borrow_mut()
691             .entry(index)
692             .or_insert_with(|| {
693                 let stable_id = file_index_to_stable_id[&index];
694                 source_map
695                     .source_file_by_stable_id(stable_id)
696                     .expect("failed to lookup `SourceFile` in new context")
697             })
698             .clone()
699     }
700 }
701
702 trait DecoderWithPosition: Decoder {
703     fn position(&self) -> usize;
704 }
705
706 impl<'a> DecoderWithPosition for opaque::Decoder<'a> {
707     fn position(&self) -> usize {
708         self.position()
709     }
710 }
711
712 impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> {
713     fn position(&self) -> usize {
714         self.opaque.position()
715     }
716 }
717
718 // Decodes something that was encoded with `encode_tagged()` and verify that the
719 // tag matches and the correct amount of bytes was read.
720 fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Error>
721 where
722     T: Decodable<D> + Eq + std::fmt::Debug,
723     V: Decodable<D>,
724     D: DecoderWithPosition,
725 {
726     let start_pos = decoder.position();
727
728     let actual_tag = T::decode(decoder)?;
729     assert_eq!(actual_tag, expected_tag);
730     let value = V::decode(decoder)?;
731     let end_pos = decoder.position();
732
733     let expected_len: u64 = Decodable::decode(decoder)?;
734     assert_eq!((end_pos - start_pos) as u64, expected_len);
735
736     Ok(value)
737 }
738
739 impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
740     const CLEAR_CROSS_CRATE: bool = false;
741
742     #[inline]
743     fn tcx(&self) -> TyCtxt<'tcx> {
744         self.tcx
745     }
746
747     #[inline]
748     fn position(&self) -> usize {
749         self.opaque.position()
750     }
751
752     #[inline]
753     fn peek_byte(&self) -> u8 {
754         self.opaque.data[self.opaque.position()]
755     }
756
757     fn cached_ty_for_shorthand<F>(
758         &mut self,
759         shorthand: usize,
760         or_insert_with: F,
761     ) -> Result<Ty<'tcx>, Self::Error>
762     where
763         F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>,
764     {
765         let tcx = self.tcx();
766
767         let cache_key =
768             ty::CReaderCacheKey { cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand };
769
770         if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) {
771             return Ok(ty);
772         }
773
774         let ty = or_insert_with(self)?;
775         // This may overwrite the entry, but it should overwrite with the same value.
776         tcx.ty_rcache.borrow_mut().insert_same(cache_key, ty);
777         Ok(ty)
778     }
779
780     fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
781     where
782         F: FnOnce(&mut Self) -> R,
783     {
784         debug_assert!(pos < self.opaque.data.len());
785
786         let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
787         let old_opaque = mem::replace(&mut self.opaque, new_opaque);
788         let r = f(self);
789         self.opaque = old_opaque;
790         r
791     }
792
793     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
794         self.cnum_map[cnum].unwrap_or_else(|| bug!("could not find new `CrateNum` for {:?}", cnum))
795     }
796
797     fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
798         let alloc_decoding_session = self.alloc_decoding_session;
799         alloc_decoding_session.decode_alloc_id(self)
800     }
801 }
802
803 crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
804
805 // This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
806 // when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
807 // into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
808 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
809     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
810         Decodable::decode(&mut d.opaque)
811     }
812 }
813
814 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
815     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
816         let syntax_contexts = decoder.syntax_contexts;
817         rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
818             // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
819             // We look up the position of the associated `SyntaxData` and decode it.
820             let pos = syntax_contexts.get(&id).unwrap();
821             this.with_position(pos.to_usize(), |decoder| {
822                 let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT)?;
823                 Ok(data)
824             })
825         })
826     }
827 }
828
829 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
830     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
831         let expn_data = decoder.expn_data;
832         rustc_span::hygiene::decode_expn_id(
833             decoder,
834             ExpnDataDecodeMode::incr_comp(decoder.hygiene_context),
835             |this, index| {
836                 // This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
837                 // We look up the position of the associated `ExpnData` and decode it.
838                 let pos = expn_data
839                     .get(&index)
840                     .unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data));
841
842                 this.with_position(pos.to_usize(), |decoder| {
843                     let data: ExpnData = decode_tagged(decoder, TAG_EXPN_DATA)?;
844                     Ok(data)
845                 })
846             },
847         )
848     }
849 }
850
851 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
852     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
853         let tag: u8 = Decodable::decode(decoder)?;
854
855         if tag == TAG_PARTIAL_SPAN {
856             let ctxt = SyntaxContext::decode(decoder)?;
857             return Ok(DUMMY_SP.with_ctxt(ctxt));
858         } else {
859             debug_assert_eq!(tag, TAG_FULL_SPAN);
860         }
861
862         let file_lo_index = SourceFileIndex::decode(decoder)?;
863         let line_lo = usize::decode(decoder)?;
864         let col_lo = BytePos::decode(decoder)?;
865         let len = BytePos::decode(decoder)?;
866         let ctxt = SyntaxContext::decode(decoder)?;
867
868         let file_lo = decoder.file_index_to_file(file_lo_index);
869         let lo = file_lo.lines[line_lo - 1] + col_lo;
870         let hi = lo + len;
871
872         Ok(Span::new(lo, hi, ctxt))
873     }
874 }
875
876 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
877     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
878         let cnum = CrateNum::from_u32(u32::decode(d)?);
879         Ok(d.map_encoded_cnum_to_current(cnum))
880     }
881 }
882
883 // This impl makes sure that we get a runtime error when we try decode a
884 // `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
885 // because we would not know how to transform the `DefIndex` to the current
886 // context.
887 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
888     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<DefIndex, String> {
889         Err(d.error("trying to decode `DefIndex` outside the context of a `DefId`"))
890     }
891 }
892
893 // Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
894 // compilation sessions. We use the `DefPathHash`, which is stable across
895 // sessions, to map the old `DefId` to the new one.
896 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
897     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
898         // Load the `DefPathHash` which is was we encoded the `DefId` as.
899         let def_path_hash = DefPathHash::decode(d)?;
900
901         // Using the `DefPathHash`, we can lookup the new `DefId`.
902         // Subtle: We only encode a `DefId` as part of a query result.
903         // If we get to this point, then all of the query inputs were green,
904         // which means that the definition with this hash is guaranteed to
905         // still exist in the current compilation session.
906         Ok(d.tcx()
907             .on_disk_cache
908             .as_ref()
909             .unwrap()
910             .def_path_hash_to_def_id(d.tcx(), def_path_hash)
911             .unwrap())
912     }
913 }
914
915 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
916     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
917         RefDecodable::decode(d)
918     }
919 }
920
921 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
922     for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
923 {
924     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
925         RefDecodable::decode(d)
926     }
927 }
928
929 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
930     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
931         RefDecodable::decode(d)
932     }
933 }
934
935 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
936     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
937         RefDecodable::decode(d)
938     }
939 }
940
941 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsmTemplatePiece] {
942     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
943         RefDecodable::decode(d)
944     }
945 }
946
947 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Span] {
948     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
949         RefDecodable::decode(d)
950     }
951 }
952
953 //- ENCODING -------------------------------------------------------------------
954
955 pub trait OpaqueEncoder: Encoder {
956     fn position(&self) -> usize;
957 }
958
959 impl OpaqueEncoder for FileEncoder {
960     #[inline]
961     fn position(&self) -> usize {
962         FileEncoder::position(self)
963     }
964 }
965
966 /// An encoder that can write to the incremental compilation cache.
967 pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
968     tcx: TyCtxt<'tcx>,
969     encoder: &'a mut E,
970     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
971     predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
972     interpret_allocs: FxIndexSet<interpret::AllocId>,
973     source_map: CachingSourceMapView<'tcx>,
974     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
975     hygiene_context: &'a HygieneEncodeContext,
976     latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
977 }
978
979 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
980 where
981     E: 'a + OpaqueEncoder,
982 {
983     fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
984         self.file_to_file_index[&(&*source_file as *const SourceFile)]
985     }
986
987     /// Encode something with additional information that allows to do some
988     /// sanity checks when decoding the data again. This method will first
989     /// encode the specified tag, then the given value, then the number of
990     /// bytes taken up by tag and value. On decoding, we can then verify that
991     /// we get the expected tag and read the expected number of bytes.
992     fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
993         &mut self,
994         tag: T,
995         value: &V,
996     ) -> Result<(), E::Error> {
997         let start_pos = self.position();
998
999         tag.encode(self)?;
1000         value.encode(self)?;
1001
1002         let end_pos = self.position();
1003         ((end_pos - start_pos) as u64).encode(self)
1004     }
1005 }
1006
1007 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
1008 where
1009     E: 'a + OpaqueEncoder,
1010 {
1011     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
1012         rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
1013     }
1014 }
1015
1016 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId
1017 where
1018     E: 'a + OpaqueEncoder,
1019 {
1020     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
1021         rustc_span::hygiene::raw_encode_expn_id(
1022             *self,
1023             s.hygiene_context,
1024             ExpnDataEncodeMode::IncrComp,
1025             s,
1026         )
1027     }
1028 }
1029
1030 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span
1031 where
1032     E: 'a + OpaqueEncoder,
1033 {
1034     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
1035         let span_data = self.data();
1036         if self.is_dummy() {
1037             TAG_PARTIAL_SPAN.encode(s)?;
1038             return span_data.ctxt.encode(s);
1039         }
1040
1041         let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
1042         let partial_span = match &pos {
1043             Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
1044             None => true,
1045         };
1046
1047         if partial_span {
1048             TAG_PARTIAL_SPAN.encode(s)?;
1049             return span_data.ctxt.encode(s);
1050         }
1051
1052         let (file_lo, line_lo, col_lo) = pos.unwrap();
1053
1054         let len = span_data.hi - span_data.lo;
1055
1056         let source_file_index = s.source_file_index(file_lo);
1057
1058         TAG_FULL_SPAN.encode(s)?;
1059         source_file_index.encode(s)?;
1060         line_lo.encode(s)?;
1061         col_lo.encode(s)?;
1062         len.encode(s)?;
1063         span_data.ctxt.encode(s)
1064     }
1065 }
1066
1067 impl<'a, 'tcx, E> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx, E>
1068 where
1069     E: 'a + OpaqueEncoder,
1070 {
1071     const CLEAR_CROSS_CRATE: bool = false;
1072
1073     fn position(&self) -> usize {
1074         self.encoder.position()
1075     }
1076     fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
1077         &mut self.type_shorthands
1078     }
1079     fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
1080         &mut self.predicate_shorthands
1081     }
1082     fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
1083         let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
1084
1085         index.encode(self)
1086     }
1087 }
1088
1089 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
1090 where
1091     E: 'a + OpaqueEncoder,
1092 {
1093     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
1094         let def_path_hash = s.tcx.def_path_hash(*self);
1095         // Store additional information when we encode a foreign `DefId`,
1096         // so that we can map its `DefPathHash` back to a `DefId` in the next
1097         // compilation session.
1098         if !self.is_local() {
1099             s.latest_foreign_def_path_hashes.insert(
1100                 def_path_hash,
1101                 RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() },
1102             );
1103         }
1104         def_path_hash.encode(s)
1105     }
1106 }
1107
1108 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex
1109 where
1110     E: 'a + OpaqueEncoder,
1111 {
1112     fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
1113         bug!("encoding `DefIndex` without context");
1114     }
1115 }
1116
1117 macro_rules! encoder_methods {
1118     ($($name:ident($ty:ty);)*) => {
1119         #[inline]
1120         $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
1121             self.encoder.$name(value)
1122         })*
1123     }
1124 }
1125
1126 impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
1127 where
1128     E: 'a + OpaqueEncoder,
1129 {
1130     type Error = E::Error;
1131
1132     #[inline]
1133     fn emit_unit(&mut self) -> Result<(), Self::Error> {
1134         Ok(())
1135     }
1136
1137     encoder_methods! {
1138         emit_usize(usize);
1139         emit_u128(u128);
1140         emit_u64(u64);
1141         emit_u32(u32);
1142         emit_u16(u16);
1143         emit_u8(u8);
1144
1145         emit_isize(isize);
1146         emit_i128(i128);
1147         emit_i64(i64);
1148         emit_i32(i32);
1149         emit_i16(i16);
1150         emit_i8(i8);
1151
1152         emit_bool(bool);
1153         emit_f64(f64);
1154         emit_f32(f32);
1155         emit_char(char);
1156         emit_str(&str);
1157         emit_raw_bytes(&[u8]);
1158     }
1159 }
1160
1161 // This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
1162 // is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
1163 // Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
1164 // and the encoding traits currently work.
1165 impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] {
1166     fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResult {
1167         self.encode(e.encoder)
1168     }
1169 }
1170
1171 pub fn encode_query_results<'a, 'tcx, CTX, Q>(
1172     tcx: CTX,
1173     encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,
1174     query_result_index: &mut EncodedQueryResultIndex,
1175 ) -> FileEncodeResult
1176 where
1177     CTX: QueryContext + 'tcx,
1178     Q: super::QueryDescription<CTX> + super::QueryAccessors<CTX>,
1179     Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>,
1180 {
1181     let _timer = tcx
1182         .dep_context()
1183         .profiler()
1184         .extra_verbose_generic_activity("encode_query_results_for", std::any::type_name::<Q>());
1185
1186     assert!(Q::query_state(tcx).all_inactive());
1187     let cache = Q::query_cache(tcx);
1188     let mut res = Ok(());
1189     cache.iter_results(&mut |key, value, dep_node| {
1190         if res.is_err() {
1191             return;
1192         }
1193         if Q::cache_on_disk(tcx, &key, Some(value)) {
1194             let dep_node = SerializedDepNodeIndex::new(dep_node.index());
1195
1196             // Record position of the cache entry.
1197             query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.encoder.position())));
1198
1199             // Encode the type check tables with the `SerializedDepNodeIndex`
1200             // as tag.
1201             match encoder.encode_tagged(dep_node, value) {
1202                 Ok(()) => {}
1203                 Err(e) => {
1204                     res = Err(e);
1205                 }
1206             }
1207         }
1208     });
1209
1210     res
1211 }