]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/query/on_disk_cache.rs
Rollup merge of #54257 - alexcrichton:wasm-math-symbols, r=TimNN
[rust.git] / src / librustc / ty / query / on_disk_cache.rs
1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
12 use errors::Diagnostic;
13 use hir;
14 use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
15 use hir::map::definitions::DefPathHash;
16 use ich::{CachingSourceMapView, Fingerprint};
17 use mir::{self, interpret};
18 use mir::interpret::{AllocDecodingSession, AllocDecodingState};
19 use rustc_data_structures::fx::FxHashMap;
20 use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once};
21 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
22 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
23                       SpecializedDecoder, SpecializedEncoder,
24                       UseSpecializedDecodable, UseSpecializedEncodable};
25 use session::{CrateDisambiguator, Session};
26 use std::mem;
27 use syntax::ast::NodeId;
28 use syntax::source_map::{SourceMap, StableFilemapId};
29 use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile};
30 use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
31 use ty;
32 use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
33 use ty::context::TyCtxt;
34 use util::common::time;
35
36 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
37
38 const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
39 const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
40
41 const TAG_NO_EXPANSION_INFO: u8 = 0;
42 const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1;
43 const TAG_EXPANSION_INFO_INLINE: u8 = 2;
44
45 const TAG_VALID_SPAN: u8 = 0;
46 const TAG_INVALID_SPAN: u8 = 1;
47
48 /// `OnDiskCache` provides an interface to incr. comp. data cached from the
49 /// previous compilation session. This data will eventually include the results
50 /// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
51 /// any diagnostics that have been emitted during a query.
52 pub struct OnDiskCache<'sess> {
53
54     // The complete cache data in serialized form.
55     serialized_data: Vec<u8>,
56
57     // This field collects all Diagnostics emitted during the current
58     // compilation session.
59     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
60
61     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
62     cnum_map: Once<IndexVec<CrateNum, Option<CrateNum>>>,
63
64     source_map: &'sess SourceMap,
65     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableFilemapId>,
66
67     // These two fields caches that are populated lazily during decoding.
68     file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
69     synthetic_expansion_infos: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
70
71     // A map from dep-node to the position of the cached query result in
72     // `serialized_data`.
73     query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
74
75     // A map from dep-node to the position of any associated diagnostics in
76     // `serialized_data`.
77     prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
78
79     alloc_decoding_state: AllocDecodingState,
80 }
81
82 // This type is used only for (de-)serialization.
83 #[derive(RustcEncodable, RustcDecodable)]
84 struct Footer {
85     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableFilemapId>,
86     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
87     query_result_index: EncodedQueryResultIndex,
88     diagnostics_index: EncodedQueryResultIndex,
89     // the location of all allocations
90     interpret_alloc_index: Vec<u32>,
91 }
92
93 type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
94 type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
95 type EncodedDiagnostics = Vec<Diagnostic>;
96
97 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
98 struct SourceFileIndex(u32);
99
100 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RustcEncodable, RustcDecodable)]
101 struct AbsoluteBytePos(u32);
102
103 impl AbsoluteBytePos {
104     fn new(pos: usize) -> AbsoluteBytePos {
105         debug_assert!(pos <= ::std::u32::MAX as usize);
106         AbsoluteBytePos(pos as u32)
107     }
108
109     fn to_usize(self) -> usize {
110         self.0 as usize
111     }
112 }
113
114 impl<'sess> OnDiskCache<'sess> {
115     /// Create a new OnDiskCache instance from the serialized data in `data`.
116     pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> OnDiskCache<'sess> {
117         debug_assert!(sess.opts.incremental.is_some());
118
119         // Wrapping in a scope so we can borrow `data`
120         let footer: Footer = {
121             let mut decoder = opaque::Decoder::new(&data[..], start_pos);
122
123             // Decode the *position* of the footer which can be found in the
124             // last 8 bytes of the file.
125             decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
126             let query_result_index_pos = IntEncodedWithFixedSize::decode(&mut decoder)
127                 .expect("Error while trying to decode query result index position.")
128                 .0 as usize;
129
130             // Decoder the file footer which contains all the lookup tables, etc.
131             decoder.set_position(query_result_index_pos);
132             decode_tagged(&mut decoder, TAG_FILE_FOOTER)
133                 .expect("Error while trying to decode query result index position.")
134         };
135
136         OnDiskCache {
137             serialized_data: data,
138             file_index_to_stable_id: footer.file_index_to_stable_id,
139             file_index_to_file: Lock::new(FxHashMap()),
140             prev_cnums: footer.prev_cnums,
141             cnum_map: Once::new(),
142             source_map: sess.source_map(),
143             current_diagnostics: Lock::new(FxHashMap()),
144             query_result_index: footer.query_result_index.into_iter().collect(),
145             prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
146             synthetic_expansion_infos: Lock::new(FxHashMap()),
147             alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
148         }
149     }
150
151     pub fn new_empty(source_map: &'sess SourceMap) -> OnDiskCache<'sess> {
152         OnDiskCache {
153             serialized_data: Vec::new(),
154             file_index_to_stable_id: FxHashMap(),
155             file_index_to_file: Lock::new(FxHashMap()),
156             prev_cnums: vec![],
157             cnum_map: Once::new(),
158             source_map,
159             current_diagnostics: Lock::new(FxHashMap()),
160             query_result_index: FxHashMap(),
161             prev_diagnostics_index: FxHashMap(),
162             synthetic_expansion_infos: Lock::new(FxHashMap()),
163             alloc_decoding_state: AllocDecodingState::new(Vec::new()),
164         }
165     }
166
167     pub fn serialize<'a, 'tcx, E>(&self,
168                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
169                                   encoder: &mut E)
170                                   -> Result<(), E::Error>
171         where E: ty_codec::TyEncoder
172      {
173         // Serializing the DepGraph should not modify it:
174         tcx.dep_graph.with_ignore(|| {
175             // Allocate SourceFileIndices
176             let (file_to_file_index, file_index_to_stable_id) = {
177                 let mut file_to_file_index = FxHashMap();
178                 let mut file_index_to_stable_id = FxHashMap();
179
180                 for (index, file) in tcx.sess.source_map().files().iter().enumerate() {
181                     let index = SourceFileIndex(index as u32);
182                     let file_ptr: *const SourceFile = &**file as *const _;
183                     file_to_file_index.insert(file_ptr, index);
184                     file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
185                 }
186
187                 (file_to_file_index, file_index_to_stable_id)
188             };
189
190             let mut encoder = CacheEncoder {
191                 tcx,
192                 encoder,
193                 type_shorthands: FxHashMap(),
194                 predicate_shorthands: FxHashMap(),
195                 expn_info_shorthands: FxHashMap(),
196                 interpret_allocs: FxHashMap(),
197                 interpret_allocs_inverse: Vec::new(),
198                 source_map: CachingSourceMapView::new(tcx.sess.source_map()),
199                 file_to_file_index,
200             };
201
202             // Load everything into memory so we can write it out to the on-disk
203             // cache. The vast majority of cacheable query results should already
204             // be in memory, so this should be a cheap operation.
205             tcx.dep_graph.exec_cache_promotions(tcx);
206
207             // Encode query results
208             let mut query_result_index = EncodedQueryResultIndex::new();
209
210             time(tcx.sess, "encode query results", || {
211                 use ty::query::queries::*;
212                 let enc = &mut encoder;
213                 let qri = &mut query_result_index;
214
215                 encode_query_results::<type_of, _>(tcx, enc, qri)?;
216                 encode_query_results::<generics_of, _>(tcx, enc, qri)?;
217                 encode_query_results::<predicates_of, _>(tcx, enc, qri)?;
218                 encode_query_results::<used_trait_imports, _>(tcx, enc, qri)?;
219                 encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
220                 encode_query_results::<codegen_fulfill_obligation, _>(tcx, enc, qri)?;
221                 encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
222                 encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
223                 encode_query_results::<borrowck, _>(tcx, enc, qri)?;
224                 encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
225                 encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
226                 encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
227                 encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
228                 encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
229                 encode_query_results::<check_match, _>(tcx, enc, qri)?;
230                 encode_query_results::<codegen_fn_attrs, _>(tcx, enc, qri)?;
231                 encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
232
233                 // const eval is special, it only encodes successfully evaluated constants
234                 use ty::query::QueryAccessors;
235                 let cache = const_eval::query_cache(tcx).borrow();
236                 assert!(cache.active.is_empty());
237                 for (key, entry) in cache.results.iter() {
238                     use ty::query::config::QueryDescription;
239                     if const_eval::cache_on_disk(key.clone()) {
240                         if let Ok(ref value) = entry.value {
241                             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
242
243                             // Record position of the cache entry
244                             qri.push((dep_node, AbsoluteBytePos::new(enc.position())));
245
246                             // Encode the type check tables with the SerializedDepNodeIndex
247                             // as tag.
248                             enc.encode_tagged(dep_node, value)?;
249                         }
250                     }
251                 }
252
253                 Ok(())
254             })?;
255
256             // Encode diagnostics
257             let diagnostics_index = {
258                 let mut diagnostics_index = EncodedDiagnosticsIndex::new();
259
260                 for (dep_node_index, diagnostics) in self.current_diagnostics
261                                                         .borrow()
262                                                         .iter() {
263                     let pos = AbsoluteBytePos::new(encoder.position());
264                     // Let's make sure we get the expected type here:
265                     let diagnostics: &EncodedDiagnostics = diagnostics;
266                     let dep_node_index =
267                         SerializedDepNodeIndex::new(dep_node_index.index());
268                     encoder.encode_tagged(dep_node_index, diagnostics)?;
269                     diagnostics_index.push((dep_node_index, pos));
270                 }
271
272                 diagnostics_index
273             };
274
275             let interpret_alloc_index = {
276                 let mut interpret_alloc_index = Vec::new();
277                 let mut n = 0;
278                 loop {
279                     let new_n = encoder.interpret_allocs_inverse.len();
280                     // if we have found new ids, serialize those, too
281                     if n == new_n {
282                         // otherwise, abort
283                         break;
284                     }
285                     for idx in n..new_n {
286                         let id = encoder.interpret_allocs_inverse[idx];
287                         let pos = encoder.position() as u32;
288                         interpret_alloc_index.push(pos);
289                         interpret::specialized_encode_alloc_id(
290                             &mut encoder,
291                             tcx,
292                             id,
293                         )?;
294                     }
295                     n = new_n;
296                 }
297                 interpret_alloc_index
298             };
299
300             let sorted_cnums = sorted_cnums_including_local_crate(tcx);
301             let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
302                 let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
303                 let crate_disambiguator = tcx.crate_disambiguator(cnum);
304                 (cnum.as_u32(), crate_name, crate_disambiguator)
305             }).collect();
306
307             // Encode the file footer
308             let footer_pos = encoder.position() as u64;
309             encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
310                 file_index_to_stable_id,
311                 prev_cnums,
312                 query_result_index,
313                 diagnostics_index,
314                 interpret_alloc_index,
315             })?;
316
317             // Encode the position of the footer as the last 8 bytes of the
318             // file so we know where to look for it.
319             IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
320
321             // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
322             // of the footer must be the last thing in the data stream.
323
324             return Ok(());
325
326             fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
327                 let mut cnums = vec![LOCAL_CRATE];
328                 cnums.extend_from_slice(&tcx.crates()[..]);
329                 cnums.sort_unstable();
330                 // Just to be sure...
331                 cnums.dedup();
332                 cnums
333             }
334         })
335     }
336
337     /// Load a diagnostic emitted during the previous compilation session.
338     pub fn load_diagnostics<'a, 'tcx>(&self,
339                                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
340                                       dep_node_index: SerializedDepNodeIndex)
341                                       -> Vec<Diagnostic> {
342         let diagnostics: Option<EncodedDiagnostics> = self.load_indexed(
343             tcx,
344             dep_node_index,
345             &self.prev_diagnostics_index,
346             "diagnostics");
347
348         diagnostics.unwrap_or(Vec::new())
349     }
350
351     /// Store a diagnostic emitted during the current compilation session.
352     /// Anything stored like this will be available via `load_diagnostics` in
353     /// the next compilation session.
354     pub fn store_diagnostics(&self,
355                              dep_node_index: DepNodeIndex,
356                              diagnostics: Vec<Diagnostic>) {
357         let mut current_diagnostics = self.current_diagnostics.borrow_mut();
358         let prev = current_diagnostics.insert(dep_node_index, diagnostics);
359         debug_assert!(prev.is_none());
360     }
361
362     /// Returns the cached query result if there is something in the cache for
363     /// the given SerializedDepNodeIndex. Otherwise returns None.
364     pub fn try_load_query_result<'tcx, T>(&self,
365                                           tcx: TyCtxt<'_, 'tcx, 'tcx>,
366                                           dep_node_index: SerializedDepNodeIndex)
367                                           -> Option<T>
368         where T: Decodable
369     {
370         self.load_indexed(tcx,
371                           dep_node_index,
372                           &self.query_result_index,
373                           "query result")
374     }
375
376     /// Store a diagnostic emitted during computation of an anonymous query.
377     /// Since many anonymous queries can share the same `DepNode`, we aggregate
378     /// them -- as opposed to regular queries where we assume that there is a
379     /// 1:1 relationship between query-key and `DepNode`.
380     pub fn store_diagnostics_for_anon_node(&self,
381                                            dep_node_index: DepNodeIndex,
382                                            mut diagnostics: Vec<Diagnostic>) {
383         let mut current_diagnostics = self.current_diagnostics.borrow_mut();
384
385         let x = current_diagnostics.entry(dep_node_index).or_insert_with(|| {
386             mem::replace(&mut diagnostics, Vec::new())
387         });
388
389         x.extend(diagnostics.into_iter());
390     }
391
392     fn load_indexed<'tcx, T>(&self,
393                              tcx: TyCtxt<'_, 'tcx, 'tcx>,
394                              dep_node_index: SerializedDepNodeIndex,
395                              index: &FxHashMap<SerializedDepNodeIndex,
396                                                AbsoluteBytePos>,
397                              debug_tag: &'static str)
398                              -> Option<T>
399         where T: Decodable
400     {
401         let pos = if let Some(&pos) = index.get(&dep_node_index) {
402             pos
403         } else {
404             return None
405         };
406
407         // Initialize the cnum_map using the value from the thread which finishes the closure first
408         self.cnum_map.init_nonlocking_same(|| {
409             Self::compute_cnum_map(tcx, &self.prev_cnums[..])
410         });
411
412         let mut decoder = CacheDecoder {
413             tcx,
414             opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
415             source_map: self.source_map,
416             cnum_map: self.cnum_map.get(),
417             file_index_to_file: &self.file_index_to_file,
418             file_index_to_stable_id: &self.file_index_to_stable_id,
419             synthetic_expansion_infos: &self.synthetic_expansion_infos,
420             alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
421         };
422
423         match decode_tagged(&mut decoder, dep_node_index) {
424             Ok(value) => {
425                 Some(value)
426             }
427             Err(e) => {
428                 bug!("Could not decode cached {}: {}", debug_tag, e)
429             }
430         }
431     }
432
433     // This function builds mapping from previous-session-CrateNum to
434     // current-session-CrateNum. There might be CrateNums from the previous
435     // Session that don't occur in the current one. For these, the mapping
436     // maps to None.
437     fn compute_cnum_map(tcx: TyCtxt,
438                         prev_cnums: &[(u32, String, CrateDisambiguator)])
439                         -> IndexVec<CrateNum, Option<CrateNum>>
440     {
441         tcx.dep_graph.with_ignore(|| {
442             let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
443                 let crate_name = tcx.original_crate_name(cnum)
444                                     .as_str()
445                                     .to_string();
446                 let crate_disambiguator = tcx.crate_disambiguator(cnum);
447                 ((crate_name, crate_disambiguator), cnum)
448             }).collect::<FxHashMap<_,_>>();
449
450             let map_size = prev_cnums.iter()
451                                     .map(|&(cnum, ..)| cnum)
452                                     .max()
453                                     .unwrap_or(0) + 1;
454             let mut map = IndexVec::new();
455             map.resize(map_size as usize, None);
456
457             for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
458                 let key = (crate_name.clone(), crate_disambiguator);
459                 map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
460             }
461
462             map[LOCAL_CRATE] = Some(LOCAL_CRATE);
463             map
464         })
465     }
466 }
467
468
469 //- DECODING -------------------------------------------------------------------
470
471 /// A decoder that can read the incr. comp. cache. It is similar to the one
472 /// we use for crate metadata decoding in that it can rebase spans and
473 /// eventually will also handle things that contain `Ty` instances.
474 struct CacheDecoder<'a, 'tcx: 'a, 'x> {
475     tcx: TyCtxt<'a, 'tcx, 'tcx>,
476     opaque: opaque::Decoder<'x>,
477     source_map: &'x SourceMap,
478     cnum_map: &'x IndexVec<CrateNum, Option<CrateNum>>,
479     synthetic_expansion_infos: &'x Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
480     file_index_to_file: &'x Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
481     file_index_to_stable_id: &'x FxHashMap<SourceFileIndex, StableFilemapId>,
482     alloc_decoding_session: AllocDecodingSession<'x>,
483 }
484
485 impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
486     fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
487         let CacheDecoder {
488             ref file_index_to_file,
489             ref file_index_to_stable_id,
490             ref source_map,
491             ..
492         } = *self;
493
494         file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
495             let stable_id = file_index_to_stable_id[&index];
496             source_map.source_file_by_stable_id(stable_id)
497                    .expect("Failed to lookup SourceFile in new context.")
498         }).clone()
499     }
500 }
501
502 trait DecoderWithPosition: Decoder {
503     fn position(&self) -> usize;
504 }
505
506 impl<'enc> DecoderWithPosition for opaque::Decoder<'enc> {
507     fn position(&self) -> usize {
508         self.position()
509     }
510 }
511
512 impl<'a, 'tcx, 'x> DecoderWithPosition for CacheDecoder<'a, 'tcx, 'x> {
513     fn position(&self) -> usize {
514         self.opaque.position()
515     }
516 }
517
518 // Decode something that was encoded with encode_tagged() and verify that the
519 // tag matches and the correct amount of bytes was read.
520 fn decode_tagged<'a, 'tcx, D, T, V>(decoder: &mut D,
521                                     expected_tag: T)
522                                     -> Result<V, D::Error>
523     where T: Decodable + Eq + ::std::fmt::Debug,
524           V: Decodable,
525           D: DecoderWithPosition,
526           'tcx: 'a,
527 {
528     let start_pos = decoder.position();
529
530     let actual_tag = T::decode(decoder)?;
531     assert_eq!(actual_tag, expected_tag);
532     let value = V::decode(decoder)?;
533     let end_pos = decoder.position();
534
535     let expected_len: u64 = Decodable::decode(decoder)?;
536     assert_eq!((end_pos - start_pos) as u64, expected_len);
537
538     Ok(value)
539 }
540
541
542 impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, 'x> {
543
544     #[inline]
545     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
546         self.tcx
547     }
548
549     #[inline]
550     fn position(&self) -> usize {
551         self.opaque.position()
552     }
553
554     #[inline]
555     fn peek_byte(&self) -> u8 {
556         self.opaque.data[self.opaque.position()]
557     }
558
559     fn cached_ty_for_shorthand<F>(&mut self,
560                                   shorthand: usize,
561                                   or_insert_with: F)
562                                   -> Result<ty::Ty<'tcx>, Self::Error>
563         where F: FnOnce(&mut Self) -> Result<ty::Ty<'tcx>, Self::Error>
564     {
565         let tcx = self.tcx();
566
567         let cache_key = ty::CReaderCacheKey {
568             cnum: CrateNum::ReservedForIncrCompCache,
569             pos: shorthand,
570         };
571
572         if let Some(&ty) = tcx.rcache.borrow().get(&cache_key) {
573             return Ok(ty);
574         }
575
576         let ty = or_insert_with(self)?;
577         // This may overwrite the entry, but it should overwrite with the same value
578         tcx.rcache.borrow_mut().insert_same(cache_key, ty);
579         Ok(ty)
580     }
581
582     fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
583         where F: FnOnce(&mut Self) -> R
584     {
585         debug_assert!(pos < self.opaque.data.len());
586
587         let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
588         let old_opaque = mem::replace(&mut self.opaque, new_opaque);
589         let r = f(self);
590         self.opaque = old_opaque;
591         r
592     }
593
594     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
595         self.cnum_map[cnum].unwrap_or_else(|| {
596             bug!("Could not find new CrateNum for {:?}", cnum)
597         })
598     }
599 }
600
601 implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );
602
603 impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
604     fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
605         let alloc_decoding_session = self.alloc_decoding_session;
606         alloc_decoding_session.decode_alloc_id(self)
607     }
608 }
609 impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
610     fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
611         let tag: u8 = Decodable::decode(self)?;
612
613         if tag == TAG_INVALID_SPAN {
614             return Ok(DUMMY_SP);
615         } else {
616             debug_assert_eq!(tag, TAG_VALID_SPAN);
617         }
618
619         let file_lo_index = SourceFileIndex::decode(self)?;
620         let line_lo = usize::decode(self)?;
621         let col_lo = BytePos::decode(self)?;
622         let len = BytePos::decode(self)?;
623
624         let file_lo = self.file_index_to_file(file_lo_index);
625         let lo = file_lo.lines[line_lo - 1] + col_lo;
626         let hi = lo + len;
627
628         let expn_info_tag = u8::decode(self)?;
629
630         let ctxt = match expn_info_tag {
631             TAG_NO_EXPANSION_INFO => {
632                 SyntaxContext::empty()
633             }
634             TAG_EXPANSION_INFO_INLINE => {
635                 let pos = AbsoluteBytePos::new(self.opaque.position());
636                 let expn_info: ExpnInfo = Decodable::decode(self)?;
637                 let ctxt = SyntaxContext::allocate_directly(expn_info);
638                 self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
639                 ctxt
640             }
641             TAG_EXPANSION_INFO_SHORTHAND => {
642                 let pos = AbsoluteBytePos::decode(self)?;
643                 let cached_ctxt = self.synthetic_expansion_infos
644                                       .borrow()
645                                       .get(&pos)
646                                       .cloned();
647
648                 if let Some(ctxt) = cached_ctxt {
649                     ctxt
650                 } else {
651                     let expn_info = self.with_position(pos.to_usize(), |this| {
652                          ExpnInfo::decode(this)
653                     })?;
654                     let ctxt = SyntaxContext::allocate_directly(expn_info);
655                     self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
656                     ctxt
657                 }
658             }
659             _ => {
660                 unreachable!()
661             }
662         };
663
664         Ok(Span::new(lo, hi, ctxt))
665     }
666 }
667
668 // This impl makes sure that we get a runtime error when we try decode a
669 // DefIndex that is not contained in a DefId. Such a case would be problematic
670 // because we would not know how to transform the DefIndex to the current
671 // context.
672 impl<'a, 'tcx, 'x> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx, 'x> {
673     fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
674         bug!("Trying to decode DefIndex outside the context of a DefId")
675     }
676 }
677
678 // Both the CrateNum and the DefIndex of a DefId can change in between two
679 // compilation sessions. We use the DefPathHash, which is stable across
680 // sessions, to map the old DefId to the new one.
681 impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
682     #[inline]
683     fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
684         // Load the DefPathHash which is was we encoded the DefId as.
685         let def_path_hash = DefPathHash::decode(self)?;
686
687         // Using the DefPathHash, we can lookup the new DefId
688         Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
689     }
690 }
691
692 impl<'a, 'tcx, 'x> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx, 'x> {
693     #[inline]
694     fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
695         Ok(LocalDefId::from_def_id(DefId::decode(self)?))
696     }
697 }
698
699 impl<'a, 'tcx, 'x> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx, 'x> {
700     fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
701         // Load the DefPathHash which is was we encoded the DefIndex as.
702         let def_path_hash = DefPathHash::decode(self)?;
703
704         // Use the DefPathHash to map to the current DefId.
705         let def_id = self.tcx()
706                          .def_path_hash_to_def_id
707                          .as_ref()
708                          .unwrap()[&def_path_hash];
709
710         debug_assert!(def_id.is_local());
711
712         // The ItemLocalId needs no remapping.
713         let local_id = hir::ItemLocalId::decode(self)?;
714
715         // Reconstruct the HirId and look up the corresponding NodeId in the
716         // context of the current session.
717         Ok(hir::HirId {
718             owner: def_id.index,
719             local_id
720         })
721     }
722 }
723
724 // NodeIds are not stable across compilation sessions, so we store them in their
725 // HirId representation. This allows use to map them to the current NodeId.
726 impl<'a, 'tcx, 'x> SpecializedDecoder<NodeId> for CacheDecoder<'a, 'tcx, 'x> {
727     #[inline]
728     fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
729         let hir_id = hir::HirId::decode(self)?;
730         Ok(self.tcx().hir.hir_to_node_id(hir_id))
731     }
732 }
733
734 impl<'a, 'tcx, 'x> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx, 'x> {
735     fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
736         Fingerprint::decode_opaque(&mut self.opaque)
737     }
738 }
739
740 impl<'a, 'tcx, 'x, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
741 for CacheDecoder<'a, 'tcx, 'x> {
742     #[inline]
743     fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
744         let discr = u8::decode(self)?;
745
746         match discr {
747             TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(mir::ClearCrossCrate::Clear),
748             TAG_CLEAR_CROSS_CRATE_SET => {
749                 let val = T::decode(self)?;
750                 Ok(mir::ClearCrossCrate::Set(val))
751             }
752             _ => {
753                 unreachable!()
754             }
755         }
756     }
757 }
758
759 //- ENCODING -------------------------------------------------------------------
760
761 struct CacheEncoder<'enc, 'a, 'tcx, E>
762     where E: 'enc + ty_codec::TyEncoder,
763           'tcx: 'a,
764 {
765     tcx: TyCtxt<'a, 'tcx, 'tcx>,
766     encoder: &'enc mut E,
767     type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
768     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
769     expn_info_shorthands: FxHashMap<Mark, AbsoluteBytePos>,
770     interpret_allocs: FxHashMap<interpret::AllocId, usize>,
771     interpret_allocs_inverse: Vec<interpret::AllocId>,
772     source_map: CachingSourceMapView<'tcx>,
773     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
774 }
775
776 impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
777     where E: 'enc + ty_codec::TyEncoder
778 {
779     fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
780         self.file_to_file_index[&(&*source_file as *const SourceFile)]
781     }
782
783     /// Encode something with additional information that allows to do some
784     /// sanity checks when decoding the data again. This method will first
785     /// encode the specified tag, then the given value, then the number of
786     /// bytes taken up by tag and value. On decoding, we can then verify that
787     /// we get the expected tag and read the expected number of bytes.
788     fn encode_tagged<T: Encodable, V: Encodable>(&mut self,
789                                                  tag: T,
790                                                  value: &V)
791                                                  -> Result<(), E::Error>
792     {
793         use ty::codec::TyEncoder;
794         let start_pos = self.position();
795
796         tag.encode(self)?;
797         value.encode(self)?;
798
799         let end_pos = self.position();
800         ((end_pos - start_pos) as u64).encode(self)
801     }
802 }
803
804 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<'enc, 'a, 'tcx, E>
805     where E: 'enc + ty_codec::TyEncoder
806 {
807     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
808         use std::collections::hash_map::Entry;
809         let index = match self.interpret_allocs.entry(*alloc_id) {
810             Entry::Occupied(e) => *e.get(),
811             Entry::Vacant(e) => {
812                 let idx = self.interpret_allocs_inverse.len();
813                 self.interpret_allocs_inverse.push(*alloc_id);
814                 e.insert(idx);
815                 idx
816             },
817         };
818
819         index.encode(self)
820     }
821 }
822
823 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'enc, 'a, 'tcx, E>
824     where E: 'enc + ty_codec::TyEncoder
825 {
826     fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
827
828         if *span == DUMMY_SP {
829             return TAG_INVALID_SPAN.encode(self);
830         }
831
832         let span_data = span.data();
833
834         if span_data.hi < span_data.lo {
835             return TAG_INVALID_SPAN.encode(self);
836         }
837
838         let (file_lo, line_lo, col_lo) = match self.source_map
839                                                    .byte_pos_to_line_and_col(span_data.lo) {
840             Some(pos) => pos,
841             None => {
842                 return TAG_INVALID_SPAN.encode(self);
843             }
844         };
845
846         if !file_lo.contains(span_data.hi) {
847             return TAG_INVALID_SPAN.encode(self);
848         }
849
850         let len = span_data.hi - span_data.lo;
851
852         let source_file_index = self.source_file_index(file_lo);
853
854         TAG_VALID_SPAN.encode(self)?;
855         source_file_index.encode(self)?;
856         line_lo.encode(self)?;
857         col_lo.encode(self)?;
858         len.encode(self)?;
859
860         if span_data.ctxt == SyntaxContext::empty() {
861             TAG_NO_EXPANSION_INFO.encode(self)
862         } else {
863             let mark = span_data.ctxt.outer();
864
865             if let Some(expn_info) = mark.expn_info() {
866                 if let Some(pos) = self.expn_info_shorthands.get(&mark).cloned() {
867                     TAG_EXPANSION_INFO_SHORTHAND.encode(self)?;
868                     pos.encode(self)
869                 } else {
870                     TAG_EXPANSION_INFO_INLINE.encode(self)?;
871                     let pos = AbsoluteBytePos::new(self.position());
872                     self.expn_info_shorthands.insert(mark, pos);
873                     expn_info.encode(self)
874                 }
875             } else {
876                 TAG_NO_EXPANSION_INFO.encode(self)
877             }
878         }
879     }
880 }
881
882 impl<'enc, 'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'enc, 'a, 'tcx, E>
883     where E: 'enc + ty_codec::TyEncoder
884 {
885     #[inline]
886     fn position(&self) -> usize {
887         self.encoder.position()
888     }
889 }
890
891 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<CrateNum> for CacheEncoder<'enc, 'a, 'tcx, E>
892     where E: 'enc + ty_codec::TyEncoder
893 {
894     #[inline]
895     fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
896         self.emit_u32(cnum.as_u32())
897     }
898 }
899
900 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<ty::Ty<'tcx>> for CacheEncoder<'enc, 'a, 'tcx, E>
901     where E: 'enc + ty_codec::TyEncoder
902 {
903     #[inline]
904     fn specialized_encode(&mut self, ty: &ty::Ty<'tcx>) -> Result<(), Self::Error> {
905         ty_codec::encode_with_shorthand(self, ty,
906             |encoder| &mut encoder.type_shorthands)
907     }
908 }
909
910 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<ty::GenericPredicates<'tcx>>
911     for CacheEncoder<'enc, 'a, 'tcx, E>
912     where E: 'enc + ty_codec::TyEncoder
913 {
914     #[inline]
915     fn specialized_encode(&mut self,
916                           predicates: &ty::GenericPredicates<'tcx>)
917                           -> Result<(), Self::Error> {
918         ty_codec::encode_predicates(self, predicates,
919             |encoder| &mut encoder.predicate_shorthands)
920     }
921 }
922
923 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<hir::HirId> for CacheEncoder<'enc, 'a, 'tcx, E>
924     where E: 'enc + ty_codec::TyEncoder
925 {
926     #[inline]
927     fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> {
928         let hir::HirId {
929             owner,
930             local_id,
931         } = *id;
932
933         let def_path_hash = self.tcx.hir.definitions().def_path_hash(owner);
934
935         def_path_hash.encode(self)?;
936         local_id.encode(self)
937     }
938 }
939
940
941 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'enc, 'a, 'tcx, E>
942     where E: 'enc + ty_codec::TyEncoder
943 {
944     #[inline]
945     fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> {
946         let def_path_hash = self.tcx.def_path_hash(*id);
947         def_path_hash.encode(self)
948     }
949 }
950
951 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<LocalDefId> for CacheEncoder<'enc, 'a, 'tcx, E>
952     where E: 'enc + ty_codec::TyEncoder
953 {
954     #[inline]
955     fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> {
956         id.to_def_id().encode(self)
957     }
958 }
959
960 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<DefIndex> for CacheEncoder<'enc, 'a, 'tcx, E>
961     where E: 'enc + ty_codec::TyEncoder
962 {
963     fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> {
964         bug!("Encoding DefIndex without context.")
965     }
966 }
967
968 // NodeIds are not stable across compilation sessions, so we store them in their
969 // HirId representation. This allows use to map them to the current NodeId.
970 impl<'enc, 'a, 'tcx, E> SpecializedEncoder<NodeId> for CacheEncoder<'enc, 'a, 'tcx, E>
971     where E: 'enc + ty_codec::TyEncoder
972 {
973     #[inline]
974     fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> {
975         let hir_id = self.tcx.hir.node_to_hir_id(*node_id);
976         hir_id.encode(self)
977     }
978 }
979
980 impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
981 for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder>
982 {
983     fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
984         f.encode_opaque(&mut self.encoder)
985     }
986 }
987
988 impl<'enc, 'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>>
989 for CacheEncoder<'enc, 'a, 'tcx, E>
990     where E: 'enc + ty_codec::TyEncoder,
991           T: Encodable,
992 {
993     #[inline]
994     fn specialized_encode(&mut self,
995                           val: &mir::ClearCrossCrate<T>)
996                           -> Result<(), Self::Error> {
997         match *val {
998             mir::ClearCrossCrate::Clear => {
999                 TAG_CLEAR_CROSS_CRATE_CLEAR.encode(self)
1000             }
1001             mir::ClearCrossCrate::Set(ref val) => {
1002                 TAG_CLEAR_CROSS_CRATE_SET.encode(self)?;
1003                 val.encode(self)
1004             }
1005         }
1006     }
1007 }
1008
1009 macro_rules! encoder_methods {
1010     ($($name:ident($ty:ty);)*) => {
1011         $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
1012             self.encoder.$name(value)
1013         })*
1014     }
1015 }
1016
1017 impl<'enc, 'a, 'tcx, E> Encoder for CacheEncoder<'enc, 'a, 'tcx, E>
1018     where E: 'enc + ty_codec::TyEncoder
1019 {
1020     type Error = E::Error;
1021
1022     fn emit_unit(&mut self) -> Result<(), Self::Error> {
1023         Ok(())
1024     }
1025
1026     encoder_methods! {
1027         emit_usize(usize);
1028         emit_u128(u128);
1029         emit_u64(u64);
1030         emit_u32(u32);
1031         emit_u16(u16);
1032         emit_u8(u8);
1033
1034         emit_isize(isize);
1035         emit_i128(i128);
1036         emit_i64(i64);
1037         emit_i32(i32);
1038         emit_i16(i16);
1039         emit_i8(i8);
1040
1041         emit_bool(bool);
1042         emit_f64(f64);
1043         emit_f32(f32);
1044         emit_char(char);
1045         emit_str(&str);
1046     }
1047 }
1048
1049 // An integer that will always encode to 8 bytes.
1050 struct IntEncodedWithFixedSize(u64);
1051
1052 impl IntEncodedWithFixedSize {
1053     pub const ENCODED_SIZE: usize = 8;
1054 }
1055
1056 impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
1057 impl UseSpecializedDecodable for IntEncodedWithFixedSize {}
1058
1059 impl SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder {
1060     fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
1061         let start_pos = self.position();
1062         for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
1063             ((x.0 >> i * 8) as u8).encode(self)?;
1064         }
1065         let end_pos = self.position();
1066         assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
1067         Ok(())
1068     }
1069 }
1070
1071 impl<'enc> SpecializedDecoder<IntEncodedWithFixedSize> for opaque::Decoder<'enc> {
1072     fn specialized_decode(&mut self) -> Result<IntEncodedWithFixedSize, Self::Error> {
1073         let mut value: u64 = 0;
1074         let start_pos = self.position();
1075
1076         for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
1077             let byte: u8 = Decodable::decode(self)?;
1078             value |= (byte as u64) << (i * 8);
1079         }
1080
1081         let end_pos = self.position();
1082         assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
1083
1084         Ok(IntEncodedWithFixedSize(value))
1085     }
1086 }
1087
1088 fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1089                                               encoder: &mut CacheEncoder<'enc, 'a, 'tcx, E>,
1090                                               query_result_index: &mut EncodedQueryResultIndex)
1091                                               -> Result<(), E::Error>
1092     where Q: super::config::QueryDescription<'tcx>,
1093           E: 'enc + TyEncoder,
1094           Q::Value: Encodable,
1095 {
1096     let desc = &format!("encode_query_results for {}",
1097         unsafe { ::std::intrinsics::type_name::<Q>() });
1098
1099     time(tcx.sess, desc, || {
1100
1101     let map = Q::query_cache(tcx).borrow();
1102     assert!(map.active.is_empty());
1103     for (key, entry) in map.results.iter() {
1104         if Q::cache_on_disk(key.clone()) {
1105             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
1106
1107             // Record position of the cache entry
1108             query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
1109
1110             // Encode the type check tables with the SerializedDepNodeIndex
1111             // as tag.
1112             encoder.encode_tagged(dep_node, &entry.value)?;
1113         }
1114     }
1115
1116     Ok(())
1117     })
1118 }