Skip to content

Commit 15db165

Browse files
incr.comp.: Implement TyDecoder for on_disk_cache::CacheDecoder.
1 parent 3bd333c commit 15db165

File tree

3 files changed

+263
-13
lines changed

3 files changed

+263
-13
lines changed

src/librustc/hir/def_id.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ newtype_index!(CrateNum
3232

3333
/// A CrateNum value that indicates that something is wrong.
3434
const INVALID_CRATE = u32::MAX - 1,
35+
36+
/// A special CrateNum that we use for the tcx.rcache when decoding from
37+
/// the incr. comp. cache.
38+
const RESERVED_FOR_INCR_COMP_CACHE = u32::MAX - 2,
3539
});
3640

3741
impl CrateNum {

src/librustc/hir/mod.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use ty::AdtKind;
4545

4646
use rustc_data_structures::indexed_vec;
4747

48+
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
4849
use std::collections::BTreeMap;
4950
use std::fmt;
5051

@@ -85,13 +86,37 @@ pub mod svh;
8586
/// the local_id part of the HirId changing, which is a very useful property in
8687
/// incremental compilation where we have to persist things through changes to
8788
/// the code base.
88-
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
89-
RustcEncodable, RustcDecodable)]
89+
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
9090
pub struct HirId {
9191
pub owner: DefIndex,
9292
pub local_id: ItemLocalId,
9393
}
9494

95+
impl serialize::UseSpecializedEncodable for HirId {
96+
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
97+
let HirId {
98+
owner,
99+
local_id,
100+
} = *self;
101+
102+
owner.encode(s)?;
103+
local_id.encode(s)
104+
}
105+
}
106+
107+
impl serialize::UseSpecializedDecodable for HirId {
108+
fn default_decode<D: Decoder>(d: &mut D) -> Result<HirId, D::Error> {
109+
let owner = DefIndex::decode(d)?;
110+
let local_id = ItemLocalId::decode(d)?;
111+
112+
Ok(HirId {
113+
owner,
114+
local_id
115+
})
116+
}
117+
}
118+
119+
95120
/// An `ItemLocalId` uniquely identifies something within a given "item-like",
96121
/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
97122
/// guarantee that the numerical value of a given `ItemLocalId` corresponds to

src/librustc/ty/maps/on_disk_cache.rs

Lines changed: 232 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,29 @@
99
// except according to those terms.
1010

1111
use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
12-
use rustc_data_structures::fx::FxHashMap;
13-
use rustc_data_structures::indexed_vec::Idx;
1412
use errors::Diagnostic;
13+
use hir;
14+
use hir::def_id::{CrateNum, DefIndex, DefId, RESERVED_FOR_INCR_COMP_CACHE,
15+
LOCAL_CRATE};
16+
use hir::map::definitions::{Definitions, DefPathTable};
17+
use middle::const_val::ByteArray;
18+
use rustc_data_structures::fx::FxHashMap;
19+
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
1520
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
16-
SpecializedDecoder, SpecializedEncoder};
21+
SpecializedDecoder, SpecializedEncoder,
22+
UseSpecializedDecodable};
1723
use session::Session;
1824
use std::borrow::Cow;
1925
use std::cell::RefCell;
2026
use std::collections::BTreeMap;
2127
use std::mem;
28+
use syntax::ast::NodeId;
2229
use syntax::codemap::{CodeMap, StableFilemapId};
2330
use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
2431
use ty;
25-
use ty::codec::{self as ty_codec};
32+
use ty::codec::{self as ty_codec, TyDecoder};
2633
use ty::context::TyCtxt;
34+
use ty::subst::Substs;
2735

2836
/// `OnDiskCache` provides an interface to incr. comp. data cached from the
2937
/// previous compilation session. This data will eventually include the results
@@ -65,9 +73,12 @@ impl<'sess> OnDiskCache<'sess> {
6573

6674
let prev_diagnostics = {
6775
let mut decoder = CacheDecoder {
76+
tcx: None,
6877
opaque: decoder,
6978
codemap: sess.codemap(),
7079
prev_filemap_starts: &header.prev_filemap_starts,
80+
cnum_map: &IndexVec::new(),
81+
prev_def_path_tables: &Vec::new(),
7182
};
7283

7384
let prev_diagnostics: FxHashMap<_, _> = {
@@ -110,6 +121,7 @@ impl<'sess> OnDiskCache<'sess> {
110121
encoder,
111122
type_shorthands: FxHashMap(),
112123
predicate_shorthands: FxHashMap(),
124+
definitions: tcx.hir.definitions(),
113125
};
114126

115127
let prev_filemap_starts: BTreeMap<_, _> = self
@@ -174,13 +186,16 @@ impl<'sess> OnDiskCache<'sess> {
174186
/// A decoder that can read the incr. comp. cache. It is similar to the one
175187
/// we use for crate metadata decoding in that it can rebase spans and
176188
/// eventually will also handle things that contain `Ty` instances.
177-
struct CacheDecoder<'a> {
178-
opaque: opaque::Decoder<'a>,
179-
codemap: &'a CodeMap,
180-
prev_filemap_starts: &'a BTreeMap<BytePos, StableFilemapId>,
189+
struct CacheDecoder<'a, 'tcx: 'a, 'x> {
190+
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
191+
opaque: opaque::Decoder<'x>,
192+
codemap: &'x CodeMap,
193+
prev_filemap_starts: &'x BTreeMap<BytePos, StableFilemapId>,
194+
cnum_map: &'x IndexVec<CrateNum, Option<CrateNum>>,
195+
prev_def_path_tables: &'x Vec<DefPathTable>,
181196
}
182197

183-
impl<'a> CacheDecoder<'a> {
198+
impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
184199
fn find_filemap_prev_bytepos(&self,
185200
prev_bytepos: BytePos)
186201
-> Option<(BytePos, StableFilemapId)> {
@@ -200,7 +215,7 @@ macro_rules! decoder_methods {
200215
}
201216
}
202217

203-
impl<'sess> Decoder for CacheDecoder<'sess> {
218+
impl<'a, 'tcx, 'x> Decoder for CacheDecoder<'a, 'tcx, 'x> {
204219
type Error = String;
205220

206221
decoder_methods! {
@@ -232,7 +247,65 @@ impl<'sess> Decoder for CacheDecoder<'sess> {
232247
}
233248
}
234249

235-
impl<'a> SpecializedDecoder<Span> for CacheDecoder<'a> {
250+
impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, 'x> {
251+
252+
#[inline]
253+
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
254+
self.tcx.expect("missing TyCtxt in CacheDecoder")
255+
}
256+
257+
#[inline]
258+
fn position(&self) -> usize {
259+
self.opaque.position()
260+
}
261+
262+
#[inline]
263+
fn peek_byte(&self) -> u8 {
264+
self.opaque.data[self.opaque.position()]
265+
}
266+
267+
fn cached_ty_for_shorthand<F>(&mut self,
268+
shorthand: usize,
269+
or_insert_with: F)
270+
-> Result<ty::Ty<'tcx>, Self::Error>
271+
where F: FnOnce(&mut Self) -> Result<ty::Ty<'tcx>, Self::Error>
272+
{
273+
let tcx = self.tcx();
274+
275+
let cache_key = ty::CReaderCacheKey {
276+
cnum: RESERVED_FOR_INCR_COMP_CACHE,
277+
pos: shorthand,
278+
};
279+
280+
if let Some(&ty) = tcx.rcache.borrow().get(&cache_key) {
281+
return Ok(ty);
282+
}
283+
284+
let ty = or_insert_with(self)?;
285+
tcx.rcache.borrow_mut().insert(cache_key, ty);
286+
Ok(ty)
287+
}
288+
289+
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
290+
where F: FnOnce(&mut Self) -> R
291+
{
292+
debug_assert!(pos < self.opaque.data.len());
293+
294+
let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
295+
let old_opaque = mem::replace(&mut self.opaque, new_opaque);
296+
let r = f(self);
297+
self.opaque = old_opaque;
298+
r
299+
}
300+
301+
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
302+
self.cnum_map[cnum].unwrap_or_else(|| {
303+
bug!("Could not find new CrateNum for {:?}", cnum)
304+
})
305+
}
306+
}
307+
308+
impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
236309
fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
237310
let lo = BytePos::decode(self)?;
238311
let hi = BytePos::decode(self)?;
@@ -249,6 +322,142 @@ impl<'a> SpecializedDecoder<Span> for CacheDecoder<'a> {
249322
}
250323
}
251324

325+
impl<'a, 'tcx, 'x> SpecializedDecoder<CrateNum> for CacheDecoder<'a, 'tcx, 'x> {
326+
fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
327+
let cnum = CrateNum::from_u32(u32::decode(self)?);
328+
let mapped = self.map_encoded_cnum_to_current(cnum);
329+
Ok(mapped)
330+
}
331+
}
332+
333+
// This impl makes sure that we get a runtime error when we try decode a
334+
// DefIndex that is not contained in a DefId. Such a case would be problematic
335+
// because we would not know how to transform the DefIndex to the current
336+
// context.
337+
impl<'a, 'tcx, 'x> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx, 'x> {
338+
fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
339+
bug!("Trying to decode DefIndex outside the context of a DefId")
340+
}
341+
}
342+
343+
// Both the CrateNum and the DefIndex of a DefId can change in between two
344+
// compilation sessions. We use the DefPathHash, which is stable across
345+
// sessions, to map the old DefId to the new one.
346+
impl<'a, 'tcx, 'x> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx, 'x> {
347+
fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
348+
// Decode the unmapped CrateNum
349+
let prev_cnum = CrateNum::default_decode(self)?;
350+
351+
// Decode the unmapped DefIndex
352+
let def_index = DefIndex::default_decode(self)?;
353+
354+
// Unmapped CrateNum and DefIndex are valid keys for the *cached*
355+
// DefPathTables, so we use them to look up the DefPathHash.
356+
let def_path_hash = self.prev_def_path_tables[prev_cnum.index()]
357+
.def_path_hash(def_index);
358+
359+
// Using the DefPathHash, we can lookup the new DefId
360+
Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
361+
}
362+
}
363+
364+
impl<'a, 'tcx, 'x> SpecializedDecoder<hir::HirId> for CacheDecoder<'a, 'tcx, 'x> {
365+
fn specialized_decode(&mut self) -> Result<hir::HirId, Self::Error> {
366+
// Decode the unmapped DefIndex of the HirId.
367+
let def_index = DefIndex::default_decode(self)?;
368+
369+
// Use the unmapped DefIndex to look up the DefPathHash in the cached
370+
// DefPathTable. For HirIds we know that we always have to look in the
371+
// *local* DefPathTable.
372+
let def_path_hash = self.prev_def_path_tables[LOCAL_CRATE.index()]
373+
.def_path_hash(def_index);
374+
375+
// Use the DefPathHash to map to the current DefId.
376+
let def_id = self.tcx()
377+
.def_path_hash_to_def_id
378+
.as_ref()
379+
.unwrap()[&def_path_hash];
380+
381+
// The ItemLocalId needs no remapping.
382+
let local_id = hir::ItemLocalId::decode(self)?;
383+
384+
// Reconstruct the HirId and look up the corresponding NodeId in the
385+
// context of the current session.
386+
Ok(hir::HirId {
387+
owner: def_id.index,
388+
local_id
389+
})
390+
}
391+
}
392+
393+
// NodeIds are not stable across compilation sessions, so we store them in their
394+
// HirId representation. This allows use to map them to the current NodeId.
395+
impl<'a, 'tcx, 'x> SpecializedDecoder<NodeId> for CacheDecoder<'a, 'tcx, 'x> {
396+
fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
397+
let hir_id = hir::HirId::decode(self)?;
398+
Ok(self.tcx().hir.hir_to_node_id(hir_id))
399+
}
400+
}
401+
402+
impl<'a, 'tcx, 'x> SpecializedDecoder<ty::Ty<'tcx>> for CacheDecoder<'a, 'tcx, 'x> {
403+
fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
404+
ty_codec::decode_ty(self)
405+
}
406+
}
407+
408+
impl<'a, 'tcx, 'x> SpecializedDecoder<ty::GenericPredicates<'tcx>>
409+
for CacheDecoder<'a, 'tcx, 'x> {
410+
fn specialized_decode(&mut self) -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
411+
ty_codec::decode_predicates(self)
412+
}
413+
}
414+
415+
impl<'a, 'tcx, 'x> SpecializedDecoder<&'tcx Substs<'tcx>> for CacheDecoder<'a, 'tcx, 'x> {
416+
fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
417+
ty_codec::decode_substs(self)
418+
}
419+
}
420+
421+
impl<'a, 'tcx, 'x> SpecializedDecoder<ty::Region<'tcx>> for CacheDecoder<'a, 'tcx, 'x> {
422+
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
423+
ty_codec::decode_region(self)
424+
}
425+
}
426+
427+
impl<'a, 'tcx, 'x> SpecializedDecoder<&'tcx ty::Slice<ty::Ty<'tcx>>>
428+
for CacheDecoder<'a, 'tcx, 'x> {
429+
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<ty::Ty<'tcx>>, Self::Error> {
430+
ty_codec::decode_ty_slice(self)
431+
}
432+
}
433+
434+
impl<'a, 'tcx, 'x> SpecializedDecoder<&'tcx ty::AdtDef> for CacheDecoder<'a, 'tcx, 'x> {
435+
fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
436+
ty_codec::decode_adt_def(self)
437+
}
438+
}
439+
440+
impl<'a, 'tcx, 'x> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
441+
for CacheDecoder<'a, 'tcx, 'x> {
442+
fn specialized_decode(&mut self)
443+
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
444+
ty_codec::decode_existential_predicate_slice(self)
445+
}
446+
}
447+
448+
impl<'a, 'tcx, 'x> SpecializedDecoder<ByteArray<'tcx>> for CacheDecoder<'a, 'tcx, 'x> {
449+
fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
450+
ty_codec::decode_byte_array(self)
451+
}
452+
}
453+
454+
impl<'a, 'tcx, 'x> SpecializedDecoder<&'tcx ty::Const<'tcx>>
455+
for CacheDecoder<'a, 'tcx, 'x> {
456+
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
457+
ty_codec::decode_const(self)
458+
}
459+
}
460+
252461

253462
//- ENCODING -------------------------------------------------------------------
254463

@@ -258,6 +467,7 @@ struct CacheEncoder<'enc, 'tcx, E>
258467
encoder: &'enc mut E,
259468
type_shorthands: FxHashMap<ty::Ty<'tcx>, usize>,
260469
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
470+
definitions: &'enc Definitions,
261471
}
262472

263473
impl<'enc, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'enc, 'tcx, E>
@@ -289,6 +499,17 @@ impl<'enc, 'tcx, E> SpecializedEncoder<ty::GenericPredicates<'tcx>>
289499
}
290500
}
291501

502+
// NodeIds are not stable across compilation sessions, so we store them in their
503+
// HirId representation. This allows use to map them to the current NodeId.
504+
impl<'enc, 'tcx, E> SpecializedEncoder<NodeId> for CacheEncoder<'enc, 'tcx, E>
505+
where E: 'enc + ty_codec::TyEncoder
506+
{
507+
fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> {
508+
let hir_id = self.definitions.node_to_hir_id(*node_id);
509+
hir_id.encode(self)
510+
}
511+
}
512+
292513
macro_rules! encoder_methods {
293514
($($name:ident($ty:ty);)*) => {
294515
$(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {

0 commit comments

Comments
 (0)