use rustc::hir::intravisit;
use rustc::hir::map::DefKey;
-use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, XRef};
+use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef};
pub struct EncodeContext<'a, 'tcx: 'a> {
pub diag: &'a Handler,
for (i, variant) in def.variants.iter().enumerate() {
self.record(variant.did,
ItemContentBuilder::encode_enum_variant_info,
- (enum_did, i));
+ (enum_did, Untracked(i)));
}
}
}
impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
+ /// Encode data for the given variant of the given ADT. The
+ /// index of the variant is untracked: this is ok because we
+ /// will have to lookup the adt-def by its id, and that gives us
+ /// the right to access any information in the adt-def (including,
+ /// e.g., the length of the various vectors).
fn encode_enum_variant_info(&mut self,
- (enum_did, index):
- (DefId, usize)) {
+ (enum_did, Untracked(index)):
+ (DefId, Untracked<usize>)) {
let ecx = self.ecx;
let def = ecx.tcx.lookup_adt_def(enum_did);
let variant = &def.variants[index];
for (field_index, field) in variant.fields.iter().enumerate() {
self.record(field.did,
ItemContentBuilder::encode_field,
- (adt_def_id, variant_index, field_index));
+ (adt_def_id, Untracked((variant_index, field_index))));
}
}
}
}
impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
+ /// Encode data for the given field of the given variant of the
+ /// given ADT. The indices of the variant/field are untracked:
+ /// this is ok because we will have to lookup the adt-def by its
+ /// id, and that gives us the right to access any information in
+ /// the adt-def (including, e.g., the length of the various
+ /// vectors).
fn encode_field(&mut self,
- (adt_def_id, variant_index, field_index):
- (DefId, usize, usize)) {
+ (adt_def_id, Untracked((variant_index, field_index))):
+ (DefId, Untracked<(usize, usize)>)) {
let ecx = self.ecx();
let def = ecx.tcx.lookup_adt_def(adt_def_id);
let variant = &def.variants[variant_index];
//!
//! In addition to the offset, we need to track the data that was used
//! to generate the contents of each `data_item`. This is so that we
-//! can figure out which HIR nodes contributors to that data for
+//! can figure out which HIR nodes contributed to that data for
//! incremental compilation purposes.
//!
-//! The `IndexBuilder` facilitates with both of these. It is created
+//! The `IndexBuilder` facilitates both of these. It is created
//! with an RBML encoder isntance (`rbml_w`) along with an
//! `EncodingContext` (`ecx`), which it encapsulates. It has one main
//! method, `record()`. You invoke `record` like so to create a new
fn read(&self, tcx: TyCtxt);
}
-impl DepGraphRead for usize {
- fn read(&self, _tcx: TyCtxt) { }
-}
-
impl DepGraphRead for DefId {
fn read(&self, _tcx: TyCtxt) { }
}
read_hir!(hir::TraitItem);
read_hir!(hir::ForeignItem);
+/// Leaks access to a value of type T without any tracking. This is
+/// suitable for ambiguous types like `usize`, which *could* represent
+/// tracked data (e.g., if you read it out of a HIR node) or might not
+/// (e.g., if it's an index). Adding in an `Untracked` is an
+/// assertion, essentially, that the data does not need to be tracked
+/// (or that read edges will be added by some other way).
+///
+/// A good idea is to add to each use of `Untracked` an explanation of
+/// why this value is ok.
+pub struct Untracked<T>(pub T);
+
+impl<T> DepGraphRead for Untracked<T> {
+ fn read(&self, _tcx: TyCtxt) { }
+}
+
/// Newtype that can be used to package up misc data extracted from a
/// HIR node that doesn't carry its own id. This will allow an
/// arbitrary `T` to be passed in, but register a read on the given