on_disk_cache.rs 36.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use errors::Diagnostic;
13
use hir;
14 15 16
use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId,
                  RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE};
use hir::map::definitions::DefPathHash;
17
use ich::{CachingCodemapView, Fingerprint};
18
use mir;
19 20
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
21
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
22
                      SpecializedDecoder, SpecializedEncoder,
23
                      UseSpecializedDecodable, UseSpecializedEncodable};
24
use session::{CrateDisambiguator, Session};
25 26
use std::cell::RefCell;
use std::mem;
27
use std::rc::Rc;
28
use syntax::ast::NodeId;
29
use syntax::codemap::{CodeMap, StableFilemapId};
30
use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap};
31
use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
32
use ty;
33
use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
34
use ty::context::TyCtxt;
35

36
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
37

38 39 40
const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;

41 42 43 44
const TAG_NO_EXPANSION_INFO: u8 = 0;
const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1;
const TAG_EXPANSION_INFO_INLINE: u8 = 2;

45 46 47
const TAG_VALID_SPAN: u8 = 0;
const TAG_INVALID_SPAN: u8 = 1;

48 49 50 51
/// `OnDiskCache` provides an interface to incr. comp. data cached from the
/// previous compilation session. This data will eventually include the results
/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
/// any diagnostics that have been emitted during a query.
52
pub struct OnDiskCache<'sess> {
53 54 55 56

    // The complete cache data in serialized form.
    serialized_data: Vec<u8>,

57 58 59 60
    // This field collects all Diagnostics emitted during the current
    // compilation session.
    current_diagnostics: RefCell<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,

61 62 63
    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
    cnum_map: RefCell<Option<IndexVec<CrateNum, Option<CrateNum>>>>,

64
    codemap: &'sess CodeMap,
65 66 67 68
    file_index_to_stable_id: FxHashMap<FileMapIndex, StableFilemapId>,

    // These two fields caches that are populated lazily during decoding.
    file_index_to_file: RefCell<FxHashMap<FileMapIndex, Rc<FileMap>>>,
69
    synthetic_expansion_infos: RefCell<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
70 71 72

    // A map from dep-node to the position of the cached query result in
    // `serialized_data`.
73
    query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
74 75 76 77

    // A map from dep-node to the position of any associated diagnostics in
    // `serialized_data`.
    prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
78 79
}

80
// This type is used only for (de-)serialization.
81
#[derive(RustcEncodable, RustcDecodable)]
82
struct Footer {
83
    file_index_to_stable_id: FxHashMap<FileMapIndex, StableFilemapId>,
84
    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
85 86
    query_result_index: EncodedQueryResultIndex,
    diagnostics_index: EncodedQueryResultIndex,
87 88
}

89
type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
90 91
type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
type EncodedDiagnostics = Vec<Diagnostic>;
92

93 94 95
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
struct FileMapIndex(u32);

96 97 98 99 100 101 102 103 104 105 106 107 108 109
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RustcEncodable, RustcDecodable)]
struct AbsoluteBytePos(u32);

impl AbsoluteBytePos {
    fn new(pos: usize) -> AbsoluteBytePos {
        debug_assert!(pos <= ::std::u32::MAX as usize);
        AbsoluteBytePos(pos as u32)
    }

    fn to_usize(self) -> usize {
        self.0 as usize
    }
}

110
impl<'sess> OnDiskCache<'sess> {
111
    /// Create a new OnDiskCache instance from the serialized data in `data`.
112
    pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> OnDiskCache<'sess> {
113 114
        debug_assert!(sess.opts.incremental.is_some());

115 116
        // Wrapping in a scope so we can borrow `data`
        let footer: Footer = {
117
            let mut decoder = opaque::Decoder::new(&data[..], start_pos);
118

119 120 121 122 123 124 125 126 127 128 129
            // Decode the *position* of the footer which can be found in the
            // last 8 bytes of the file.
            decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
            let query_result_index_pos = IntEncodedWithFixedSize::decode(&mut decoder)
                .expect("Error while trying to decode query result index position.")
                .0 as usize;

            // Decoder the file footer which contains all the lookup tables, etc.
            decoder.set_position(query_result_index_pos);
            decode_tagged(&mut decoder, TAG_FILE_FOOTER)
                .expect("Error while trying to decode query result index position.")
130 131 132
        };

        OnDiskCache {
133
            serialized_data: data,
134 135 136
            file_index_to_stable_id: footer.file_index_to_stable_id,
            file_index_to_file: RefCell::new(FxHashMap()),
            prev_cnums: footer.prev_cnums,
137
            cnum_map: RefCell::new(None),
138 139
            codemap: sess.codemap(),
            current_diagnostics: RefCell::new(FxHashMap()),
140 141 142
            query_result_index: footer.query_result_index.into_iter().collect(),
            prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
            synthetic_expansion_infos: RefCell::new(FxHashMap()),
143 144 145
        }
    }

146 147
    pub fn new_empty(codemap: &'sess CodeMap) -> OnDiskCache<'sess> {
        OnDiskCache {
148
            serialized_data: Vec::new(),
149 150
            file_index_to_stable_id: FxHashMap(),
            file_index_to_file: RefCell::new(FxHashMap()),
151 152
            prev_cnums: vec![],
            cnum_map: RefCell::new(None),
153 154
            codemap,
            current_diagnostics: RefCell::new(FxHashMap()),
155
            query_result_index: FxHashMap(),
156
            prev_diagnostics_index: FxHashMap(),
157
            synthetic_expansion_infos: RefCell::new(FxHashMap()),
158 159 160
        }
    }

161 162 163 164
    pub fn serialize<'a, 'tcx, E>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  encoder: &mut E)
                                  -> Result<(), E::Error>
165 166 167
        where E: ty_codec::TyEncoder
     {
        // Serializing the DepGraph should not modify it:
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
        tcx.dep_graph.with_ignore(|| {
            // Allocate FileMapIndices
            let (file_to_file_index, file_index_to_stable_id) = {
                let mut file_to_file_index = FxHashMap();
                let mut file_index_to_stable_id = FxHashMap();

                for (index, file) in tcx.sess.codemap().files().iter().enumerate() {
                    let index = FileMapIndex(index as u32);
                    let file_ptr: *const FileMap = &**file as *const _;
                    file_to_file_index.insert(file_ptr, index);
                    file_index_to_stable_id.insert(index, StableFilemapId::new(&file));
                }

                (file_to_file_index, file_index_to_stable_id)
            };

            let mut encoder = CacheEncoder {
                tcx,
                encoder,
                type_shorthands: FxHashMap(),
                predicate_shorthands: FxHashMap(),
                expn_info_shorthands: FxHashMap(),
                codemap: CachingCodemapView::new(tcx.sess.codemap()),
                file_to_file_index,
            };

            // Load everything into memory so we can write it out to the on-disk
            // cache. The vast majority of cacheable query results should already
            // be in memory, so this should be a cheap operation.
            tcx.dep_graph.exec_cache_promotions(tcx);

            // Encode query results
            let mut query_result_index = EncodedQueryResultIndex::new();

            {
                use ty::maps::queries::*;
                let enc = &mut encoder;
                let qri = &mut query_result_index;

                // Encode TypeckTables
                encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
                encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
                encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
                encode_query_results::<borrowck, _>(tcx, enc, qri)?;
                encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
                encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
                encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
                encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
                encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
                encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
                encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
                encode_query_results::<check_match, _>(tcx, enc, qri)?;
220 221
            }

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
            // Encode diagnostics
            let diagnostics_index = {
                let mut diagnostics_index = EncodedDiagnosticsIndex::new();

                for (dep_node_index, diagnostics) in self.current_diagnostics
                                                        .borrow()
                                                        .iter() {
                    let pos = AbsoluteBytePos::new(encoder.position());
                    // Let's make sure we get the expected type here:
                    let diagnostics: &EncodedDiagnostics = diagnostics;
                    let dep_node_index =
                        SerializedDepNodeIndex::new(dep_node_index.index());
                    encoder.encode_tagged(dep_node_index, diagnostics)?;
                    diagnostics_index.push((dep_node_index, pos));
                }

                diagnostics_index
            };

            let sorted_cnums = sorted_cnums_including_local_crate(tcx);
            let prev_cnums: Vec<_> = sorted_cnums.iter().map(|&cnum| {
                let crate_name = tcx.original_crate_name(cnum).as_str().to_string();
                let crate_disambiguator = tcx.crate_disambiguator(cnum);
                (cnum.as_u32(), crate_name, crate_disambiguator)
            }).collect();

            // Encode the file footer
            let footer_pos = encoder.position() as u64;
            encoder.encode_tagged(TAG_FILE_FOOTER, &Footer {
                file_index_to_stable_id,
                prev_cnums,
                query_result_index,
                diagnostics_index,
            })?;

            // Encode the position of the footer as the last 8 bytes of the
            // file so we know where to look for it.
            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;

            // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
            // of the footer must be the last thing in the data stream.

            return Ok(());

            fn sorted_cnums_including_local_crate(tcx: TyCtxt) -> Vec<CrateNum> {
                let mut cnums = vec![LOCAL_CRATE];
                cnums.extend_from_slice(&tcx.crates()[..]);
                cnums.sort_unstable();
                // Just to be sure...
                cnums.dedup();
                cnums
273
            }
274
        })
275 276
    }

277
    /// Load a diagnostic emitted during the previous compilation session.
278 279 280 281 282 283 284 285 286 287 288
    pub fn load_diagnostics<'a, 'tcx>(&self,
                                      tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      dep_node_index: SerializedDepNodeIndex)
                                      -> Vec<Diagnostic> {
        let diagnostics: Option<EncodedDiagnostics> = self.load_indexed(
            tcx,
            dep_node_index,
            &self.prev_diagnostics_index,
            "diagnostics");

        diagnostics.unwrap_or(Vec::new())
289 290
    }

291 292 293
    /// Store a diagnostic emitted during the current compilation session.
    /// Anything stored like this will be available via `load_diagnostics` in
    /// the next compilation session.
294 295 296 297 298 299 300 301
    pub fn store_diagnostics(&self,
                             dep_node_index: DepNodeIndex,
                             diagnostics: Vec<Diagnostic>) {
        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
        let prev = current_diagnostics.insert(dep_node_index, diagnostics);
        debug_assert!(prev.is_none());
    }

302 303
    /// Returns the cached query result if there is something in the cache for
    /// the given SerializedDepNodeIndex. Otherwise returns None.
304 305 306 307
    pub fn try_load_query_result<'tcx, T>(&self,
                                          tcx: TyCtxt<'_, 'tcx, 'tcx>,
                                          dep_node_index: SerializedDepNodeIndex)
                                          -> Option<T>
308 309
        where T: Decodable
    {
310 311 312 313
        self.load_indexed(tcx,
                          dep_node_index,
                          &self.query_result_index,
                          "query result")
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
    }

    /// Store a diagnostic emitted during computation of an anonymous query.
    /// Since many anonymous queries can share the same `DepNode`, we aggregate
    /// them -- as opposed to regular queries where we assume that there is a
    /// 1:1 relationship between query-key and `DepNode`.
    pub fn store_diagnostics_for_anon_node(&self,
                                           dep_node_index: DepNodeIndex,
                                           mut diagnostics: Vec<Diagnostic>) {
        let mut current_diagnostics = self.current_diagnostics.borrow_mut();

        let x = current_diagnostics.entry(dep_node_index).or_insert_with(|| {
            mem::replace(&mut diagnostics, Vec::new())
        });

        x.extend(diagnostics.into_iter());
    }

332 333 334 335 336 337 338
    fn load_indexed<'tcx, T>(&self,
                             tcx: TyCtxt<'_, 'tcx, 'tcx>,
                             dep_node_index: SerializedDepNodeIndex,
                             index: &FxHashMap<SerializedDepNodeIndex,
                                               AbsoluteBytePos>,
                             debug_tag: &'static str)
                             -> Option<T>
339 340 341 342 343 344 345
        where T: Decodable
    {
        let pos = if let Some(&pos) = index.get(&dep_node_index) {
            pos
        } else {
            return None
        };
346 347 348 349 350 351

        let mut cnum_map = self.cnum_map.borrow_mut();
        if cnum_map.is_none() {
            *cnum_map = Some(Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
        }

352
        let mut synthetic_expansion_infos = self.synthetic_expansion_infos.borrow_mut();
353
        let mut file_index_to_file = self.file_index_to_file.borrow_mut();
354

355
        let mut decoder = CacheDecoder {
356
            tcx,
357
            opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
358 359
            codemap: self.codemap,
            cnum_map: cnum_map.as_ref().unwrap(),
360 361 362
            file_index_to_file: &mut file_index_to_file,
            file_index_to_stable_id: &self.file_index_to_stable_id,
            synthetic_expansion_infos: &mut synthetic_expansion_infos,
363 364 365 366
        };

        match decode_tagged(&mut decoder, dep_node_index) {
            Ok(value) => {
367
                Some(value)
368 369
            }
            Err(e) => {
370
                bug!("Could not decode cached {}: {}", debug_tag, e)
371 372 373 374
            }
        }
    }

375 376 377 378 379 380 381 382
    // This function builds mapping from previous-session-CrateNum to
    // current-session-CrateNum. There might be CrateNums from the previous
    // Session that don't occur in the current one. For these, the mapping
    // maps to None.
    fn compute_cnum_map(tcx: TyCtxt,
                        prev_cnums: &[(u32, String, CrateDisambiguator)])
                        -> IndexVec<CrateNum, Option<CrateNum>>
    {
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
        tcx.dep_graph.with_ignore(|| {
            let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
                let crate_name = tcx.original_crate_name(cnum)
                                    .as_str()
                                    .to_string();
                let crate_disambiguator = tcx.crate_disambiguator(cnum);
                ((crate_name, crate_disambiguator), cnum)
            }).collect::<FxHashMap<_,_>>();

            let map_size = prev_cnums.iter()
                                    .map(|&(cnum, ..)| cnum)
                                    .max()
                                    .unwrap_or(0) + 1;
            let mut map = IndexVec::new();
            map.resize(map_size as usize, None);

            for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
                let key = (crate_name.clone(), crate_disambiguator);
                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
            }
403

404 405 406
            map[LOCAL_CRATE] = Some(LOCAL_CRATE);
            map
        })
407
    }
408 409
}

410 411 412

//- DECODING -------------------------------------------------------------------

413 414 415
/// A decoder that can read the incr. comp. cache. It is similar to the one
/// we use for crate metadata decoding in that it can rebase spans and
/// eventually will also handle things that contain `Ty` instances.
416
struct CacheDecoder<'a, 'tcx: 'a, 'x> {
417
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
418 419 420
    opaque: opaque::Decoder<'x>,
    codemap: &'x CodeMap,
    cnum_map: &'x IndexVec<CrateNum, Option<CrateNum>>,
421
    synthetic_expansion_infos: &'x mut FxHashMap<AbsoluteBytePos, SyntaxContext>,
422 423
    file_index_to_file: &'x mut FxHashMap<FileMapIndex, Rc<FileMap>>,
    file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
424 425
}

426
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
427 428 429 430 431 432 433 434 435 436 437 438 439
    fn file_index_to_file(&mut self, index: FileMapIndex) -> Rc<FileMap> {
        let CacheDecoder {
            ref mut file_index_to_file,
            ref file_index_to_stable_id,
            ref codemap,
            ..
        } = *self;

        file_index_to_file.entry(index).or_insert_with(|| {
            let stable_id = file_index_to_stable_id[&index];
            codemap.filemap_by_stable_id(stable_id)
                   .expect("Failed to lookup FileMap in new context.")
        }).clone()
440 441 442
    }
}

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
trait DecoderWithPosition: Decoder {
    fn position(&self) -> usize;
}

impl<'enc> DecoderWithPosition for opaque::Decoder<'enc> {
    fn position(&self) -> usize {
        self.position()
    }
}

impl<'a, 'tcx, 'x> DecoderWithPosition for CacheDecoder<'a, 'tcx, 'x> {
    fn position(&self) -> usize {
        self.opaque.position()
    }
}

459 460 461 462 463 464 465
// Decode something that was encoded with encode_tagged() and verify that the
// tag matches and the correct amount of bytes was read.
fn decode_tagged<'a, 'tcx, D, T, V>(decoder: &mut D,
                                    expected_tag: T)
                                    -> Result<V, D::Error>
    where T: Decodable + Eq + ::std::fmt::Debug,
          V: Decodable,
466
          D: DecoderWithPosition,
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
          'tcx: 'a,
{
    let start_pos = decoder.position();

    let actual_tag = T::decode(decoder)?;
    assert_eq!(actual_tag, expected_tag);
    let value = V::decode(decoder)?;
    let end_pos = decoder.position();

    let expected_len: u64 = Decodable::decode(decoder)?;
    assert_eq!((end_pos - start_pos) as u64, expected_len);

    Ok(value)
}


483 484 485 486
impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, 'x> {

    #[inline]
    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
487
        self.tcx
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    }

    #[inline]
    fn position(&self) -> usize {
        self.opaque.position()
    }

    #[inline]
    fn peek_byte(&self) -> u8 {
        self.opaque.data[self.opaque.position()]
    }

    fn cached_ty_for_shorthand<F>(&mut self,
                                  shorthand: usize,
                                  or_insert_with: F)
                                  -> Result<ty::Ty<'tcx>, Self::Error>
        where F: FnOnce(&mut Self) -> Result<ty::Ty<'tcx>, Self::Error>
    {
        let tcx = self.tcx();

        let cache_key = ty::CReaderCacheKey {
            cnum: RESERVED_FOR_INCR_COMP_CACHE,
            pos: shorthand,
        };

        if let Some(&ty) = tcx.rcache.borrow().get(&cache_key) {
            return Ok(ty);
        }

        let ty = or_insert_with(self)?;
        tcx.rcache.borrow_mut().insert(cache_key, ty);
        Ok(ty)
    }

    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
        where F: FnOnce(&mut Self) -> R
    {
        debug_assert!(pos < self.opaque.data.len());

        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
        let r = f(self);
        self.opaque = old_opaque;
        r
    }

    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
        self.cnum_map[cnum].unwrap_or_else(|| {
            bug!("Could not find new CrateNum for {:?}", cnum)
        })
    }
}

541 542
implement_ty_decoder!( CacheDecoder<'a, 'tcx, 'x> );

543
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
544
    fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
545 546 547 548 549 550
        let tag: u8 = Decodable::decode(self)?;

        if tag == TAG_INVALID_SPAN {
            return Ok(DUMMY_SP);
        } else {
            debug_assert_eq!(tag, TAG_VALID_SPAN);
551 552
        }

553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
        let file_lo_index = FileMapIndex::decode(self)?;
        let line_lo = usize::decode(self)?;
        let col_lo = BytePos::decode(self)?;
        let len = BytePos::decode(self)?;

        let file_lo = self.file_index_to_file(file_lo_index);
        let lo = file_lo.lines.borrow()[line_lo - 1] + col_lo;
        let hi = lo + len;

        let expn_info_tag = u8::decode(self)?;

        let ctxt = match expn_info_tag {
            TAG_NO_EXPANSION_INFO => {
                SyntaxContext::empty()
            }
            TAG_EXPANSION_INFO_INLINE => {
569
                let pos = AbsoluteBytePos::new(self.opaque.position());
570 571 572 573 574 575
                let expn_info: ExpnInfo = Decodable::decode(self)?;
                let ctxt = SyntaxContext::allocate_directly(expn_info);
                self.synthetic_expansion_infos.insert(pos, ctxt);
                ctxt
            }
            TAG_EXPANSION_INFO_SHORTHAND => {
576
                let pos = AbsoluteBytePos::decode(self)?;
577 578 579
                if let Some(ctxt) = self.synthetic_expansion_infos.get(&pos).cloned() {
                    ctxt
                } else {
580
                    let expn_info = self.with_position(pos.to_usize(), |this| {
581 582 583 584 585 586 587 588 589 590 591 592 593
                         ExpnInfo::decode(this)
                    })?;
                    let ctxt = SyntaxContext::allocate_directly(expn_info);
                    self.synthetic_expansion_infos.insert(pos, ctxt);
                    ctxt
                }
            }
            _ => {
                unreachable!()
            }
        };

        Ok(Span::new(lo, hi, ctxt))
594 595
    }
}
596

597 598 599 600 601 602 603 604 605 606 607 608 609 610
// This impl makes sure that we get a runtime error when we try decode a
// DefIndex that is not contained in a DefId. Such a case would be problematic
// because we would not know how to transform the DefIndex to the current
// context.
impl<'a, 'tcx, 'x> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx, 'x> {
    fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
        bug!("Trying to decode DefIndex outside the context of a DefId")
    }
}

// Both the CrateNum and the DefIndex of a DefId can change in between two
// compilation sessions. We use the DefPathHash, which is stable across
// sessions, to map the old DefId to the new one.
impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
611
    #[inline]
612
    fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
613 614
        // Load the DefPathHash which is was we encoded the DefId as.
        let def_path_hash = DefPathHash::decode(self)?;
615 616 617 618 619 620

        // Using the DefPathHash, we can lookup the new DefId
        Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
    }
}

621
impl<'a, 'tcx, 'x> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx, 'x> {
622
    #[inline]
623 624 625 626 627
    fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
        Ok(LocalDefId::from_def_id(DefId::decode(self)?))
    }
}

628 629
impl<'a, 'tcx, 'x> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx, 'x> {
    fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
630 631
        // Load the DefPathHash which is was we encoded the DefIndex as.
        let def_path_hash = DefPathHash::decode(self)?;
632 633 634 635 636 637 638

        // Use the DefPathHash to map to the current DefId.
        let def_id = self.tcx()
                         .def_path_hash_to_def_id
                         .as_ref()
                         .unwrap()[&def_path_hash];

639 640
        debug_assert!(def_id.is_local());

641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        // The ItemLocalId needs no remapping.
        let local_id = hir::ItemLocalId::decode(self)?;

        // Reconstruct the HirId and look up the corresponding NodeId in the
        // context of the current session.
        Ok(hir::HirId {
            owner: def_id.index,
            local_id
        })
    }
}

// NodeIds are not stable across compilation sessions, so we store them in their
// HirId representation. This allows use to map them to the current NodeId.
impl<'a, 'tcx, 'x> SpecializedDecoder<NodeId> for CacheDecoder<'a, 'tcx, 'x> {
656
    #[inline]
657 658 659 660 661 662
    fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
        let hir_id = hir::HirId::decode(self)?;
        Ok(self.tcx().hir.hir_to_node_id(hir_id))
    }
}

663 664 665 666 667 668
impl<'a, 'tcx, 'x> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx, 'x> {
    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
        Fingerprint::decode_opaque(&mut self.opaque)
    }
}

669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
impl<'a, 'tcx, 'x, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for CacheDecoder<'a, 'tcx, 'x> {
    #[inline]
    fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
        let discr = u8::decode(self)?;

        match discr {
            TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(mir::ClearCrossCrate::Clear),
            TAG_CLEAR_CROSS_CRATE_SET => {
                let val = T::decode(self)?;
                Ok(mir::ClearCrossCrate::Set(val))
            }
            _ => {
                unreachable!()
            }
        }
    }
}

688 689
//- ENCODING -------------------------------------------------------------------

690 691 692
struct CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder,
          'tcx: 'a,
693
{
694
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
695 696 697
    encoder: &'enc mut E,
    type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
    predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
698
    expn_info_shorthands: FxHashMap<Mark, AbsoluteBytePos>,
699 700
    codemap: CachingCodemapView<'tcx>,
    file_to_file_index: FxHashMap<*const FileMap, FileMapIndex>,
701 702
}

703
impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
704 705
    where E: 'enc + ty_codec::TyEncoder
{
706 707 708 709
    fn filemap_index(&mut self, filemap: Rc<FileMap>) -> FileMapIndex {
        self.file_to_file_index[&(&*filemap as *const FileMap)]
    }

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
    /// Encode something with additional information that allows to do some
    /// sanity checks when decoding the data again. This method will first
    /// encode the specified tag, then the given value, then the number of
    /// bytes taken up by tag and value. On decoding, we can then verify that
    /// we get the expected tag and read the expected number of bytes.
    fn encode_tagged<T: Encodable, V: Encodable>(&mut self,
                                                 tag: T,
                                                 value: &V)
                                                 -> Result<(), E::Error>
    {
        use ty::codec::TyEncoder;
        let start_pos = self.position();

        tag.encode(self)?;
        value.encode(self)?;

        let end_pos = self.position();
        ((end_pos - start_pos) as u64).encode(self)
    }
}

731 732 733 734
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder
{
    fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
735 736 737 738 739

        if *span == DUMMY_SP {
            return TAG_INVALID_SPAN.encode(self);
        }

740 741
        let span_data = span.data();

742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
        if span_data.hi < span_data.lo {
            return TAG_INVALID_SPAN.encode(self);
        }

        let (file_lo, line_lo, col_lo) = match self.codemap
                                                   .byte_pos_to_line_and_col(span_data.lo) {
            Some(pos) => pos,
            None => {
                return TAG_INVALID_SPAN.encode(self);
            }
        };

        if !file_lo.contains(span_data.hi) {
            return TAG_INVALID_SPAN.encode(self);
        }

        let len = span_data.hi - span_data.lo;

        let filemap_index = self.filemap_index(file_lo);

        TAG_VALID_SPAN.encode(self)?;
        filemap_index.encode(self)?;
        line_lo.encode(self)?;
        col_lo.encode(self)?;
        len.encode(self)?;
767 768 769 770 771 772 773 774 775 776 777 778

        if span_data.ctxt == SyntaxContext::empty() {
            TAG_NO_EXPANSION_INFO.encode(self)
        } else {
            let mark = span_data.ctxt.outer();

            if let Some(expn_info) = mark.expn_info() {
                if let Some(pos) = self.expn_info_shorthands.get(&mark).cloned() {
                    TAG_EXPANSION_INFO_SHORTHAND.encode(self)?;
                    pos.encode(self)
                } else {
                    TAG_EXPANSION_INFO_INLINE.encode(self)?;
779
                    let pos = AbsoluteBytePos::new(self.position());
780 781 782 783 784 785 786 787 788 789
                    self.expn_info_shorthands.insert(mark, pos);
                    expn_info.encode(self)
                }
            } else {
                TAG_NO_EXPANSION_INFO.encode(self)
            }
        }
    }
}

790
impl<'enc, 'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'enc, 'a, 'tcx, E>
791 792
    where E: 'enc + ty_codec::TyEncoder
{
793
    #[inline]
794 795 796 797 798
    fn position(&self) -> usize {
        self.encoder.position()
    }
}

799 800 801 802 803 804 805 806 807
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<CrateNum> for CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder
{
    #[inline]
    fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
        self.emit_u32(cnum.as_u32())
    }
}

808
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<ty::Ty<'tcx>> for CacheEncoder<'enc, 'a, 'tcx, E>
809 810
    where E: 'enc + ty_codec::TyEncoder
{
811
    #[inline]
812 813 814 815 816 817
    fn specialized_encode(&mut self, ty: &ty::Ty<'tcx>) -> Result<(), Self::Error> {
        ty_codec::encode_with_shorthand(self, ty,
            |encoder| &mut encoder.type_shorthands)
    }
}

818 819
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<ty::GenericPredicates<'tcx>>
    for CacheEncoder<'enc, 'a, 'tcx, E>
820 821
    where E: 'enc + ty_codec::TyEncoder
{
822
    #[inline]
823 824 825 826 827 828 829 830
    fn specialized_encode(&mut self,
                          predicates: &ty::GenericPredicates<'tcx>)
                          -> Result<(), Self::Error> {
        ty_codec::encode_predicates(self, predicates,
            |encoder| &mut encoder.predicate_shorthands)
    }
}

831
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<hir::HirId> for CacheEncoder<'enc, 'a, 'tcx, E>
832 833
    where E: 'enc + ty_codec::TyEncoder
{
834
    #[inline]
835 836 837 838 839 840
    fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> {
        let hir::HirId {
            owner,
            local_id,
        } = *id;

841 842 843
        let def_path_hash = self.tcx.hir.definitions().def_path_hash(owner);

        def_path_hash.encode(self)?;
844 845 846 847
        local_id.encode(self)
    }
}

848 849 850 851

impl<'enc, 'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder
{
852
    #[inline]
853 854 855 856 857 858 859 860 861
    fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> {
        let def_path_hash = self.tcx.def_path_hash(*id);
        def_path_hash.encode(self)
    }
}

impl<'enc, 'a, 'tcx, E> SpecializedEncoder<LocalDefId> for CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder
{
862
    #[inline]
863 864 865 866 867 868 869 870 871 872 873 874 875
    fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> {
        id.to_def_id().encode(self)
    }
}

impl<'enc, 'a, 'tcx, E> SpecializedEncoder<DefIndex> for CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder
{
    fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> {
        bug!("Encoding DefIndex without context.")
    }
}

876 877
// NodeIds are not stable across compilation sessions, so we store them in their
// HirId representation. This allows use to map them to the current NodeId.
878
impl<'enc, 'a, 'tcx, E> SpecializedEncoder<NodeId> for CacheEncoder<'enc, 'a, 'tcx, E>
879 880
    where E: 'enc + ty_codec::TyEncoder
{
881
    #[inline]
882
    fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> {
883
        let hir_id = self.tcx.hir.node_to_hir_id(*node_id);
884 885 886 887
        hir_id.encode(self)
    }
}

888 889 890 891 892 893 894 895
impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder<'enc>>
{
    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
        f.encode_opaque(&mut self.encoder)
    }
}

896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
impl<'enc, 'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>>
for CacheEncoder<'enc, 'a, 'tcx, E>
    where E: 'enc + ty_codec::TyEncoder,
          T: Encodable,
{
    #[inline]
    fn specialized_encode(&mut self,
                          val: &mir::ClearCrossCrate<T>)
                          -> Result<(), Self::Error> {
        match *val {
            mir::ClearCrossCrate::Clear => {
                TAG_CLEAR_CROSS_CRATE_CLEAR.encode(self)
            }
            mir::ClearCrossCrate::Set(ref val) => {
                TAG_CLEAR_CROSS_CRATE_SET.encode(self)?;
                val.encode(self)
            }
        }
    }
}

917 918 919 920 921 922 923 924
macro_rules! encoder_methods {
    ($($name:ident($ty:ty);)*) => {
        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
            self.encoder.$name(value)
        })*
    }
}

925
impl<'enc, 'a, 'tcx, E> Encoder for CacheEncoder<'enc, 'a, 'tcx, E>
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
    where E: 'enc + ty_codec::TyEncoder
{
    type Error = E::Error;

    fn emit_nil(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }

    encoder_methods! {
        emit_usize(usize);
        emit_u128(u128);
        emit_u64(u64);
        emit_u32(u32);
        emit_u16(u16);
        emit_u8(u8);

        emit_isize(isize);
        emit_i128(i128);
        emit_i64(i64);
        emit_i32(i32);
        emit_i16(i16);
        emit_i8(i8);

        emit_bool(bool);
        emit_f64(f64);
        emit_f32(f32);
        emit_char(char);
        emit_str(&str);
    }
}
956

957 958 959 960 961 962 963 964 965 966
// An integer that will always encode to 8 bytes.
struct IntEncodedWithFixedSize(u64);

impl IntEncodedWithFixedSize {
    pub const ENCODED_SIZE: usize = 8;
}

impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
impl UseSpecializedDecodable for IntEncodedWithFixedSize {}

967
impl<'enc> SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder<'enc> {
968 969 970 971 972 973 974 975 976 977 978
    fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
        let start_pos = self.position();
        for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
            ((x.0 >> i * 8) as u8).encode(self)?;
        }
        let end_pos = self.position();
        assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
        Ok(())
    }
}

979
impl<'enc> SpecializedDecoder<IntEncodedWithFixedSize> for opaque::Decoder<'enc> {
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
    fn specialized_decode(&mut self) -> Result<IntEncodedWithFixedSize, Self::Error> {
        let mut value: u64 = 0;
        let start_pos = self.position();

        for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
            let byte: u8 = Decodable::decode(self)?;
            value |= (byte as u64) << (i * 8);
        }

        let end_pos = self.position();
        assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);

        Ok(IntEncodedWithFixedSize(value))
    }
}
995

996 997 998 999
fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                              encoder: &mut CacheEncoder<'enc, 'a, 'tcx, E>,
                                              query_result_index: &mut EncodedQueryResultIndex)
                                              -> Result<(), E::Error>
1000
    where Q: super::plumbing::GetCacheInternal<'tcx>,
1001
          E: 'enc + TyEncoder,
1002 1003 1004 1005 1006 1007 1008
          Q::Value: Encodable,
{
    for (key, entry) in Q::get_cache_internal(tcx).map.iter() {
        if Q::cache_on_disk(key.clone()) {
            let dep_node = SerializedDepNodeIndex::new(entry.index.index());

            // Record position of the cache entry
1009
            query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
1010 1011 1012 1013 1014 1015 1016 1017 1018

            // Encode the type check tables with the SerializedDepNodeIndex
            // as tag.
            encoder.encode_tagged(dep_node, &entry.value)?;
        }
    }

    Ok(())
}