Skip to content

Commit f3990fe

Browse files
committed
create a trait to ensure that data is tracked
Also write a comment explaining the system.
1 parent 00e699f commit f3990fe

File tree

2 files changed

+117
-22
lines changed

2 files changed

+117
-22
lines changed

src/librustc_metadata/encoder.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use rustc::hir::intravisit::Visitor;
5353
use rustc::hir::intravisit;
5454
use rustc::hir::map::DefKey;
5555

56-
use super::index_builder::{IndexBuilder, ItemContentBuilder, XRef};
56+
use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, XRef};
5757

5858
pub struct EncodeContext<'a, 'tcx: 'a> {
5959
pub diag: &'a Handler,
@@ -198,24 +198,23 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
198198

199199
impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> {
200200
fn encode_enum_variant_infos(&mut self,
201-
enum_did: DefId,
202-
vis: &hir::Visibility) {
201+
enum_did: DefId) {
203202
debug!("encode_enum_variant_info(enum_did={:?})", enum_did);
204203
let ecx = self.ecx();
205204
let def = ecx.tcx.lookup_adt_def(enum_did);
206205
self.encode_fields(enum_did);
207206
for (i, variant) in def.variants.iter().enumerate() {
208207
self.record(variant.did,
209208
ItemContentBuilder::encode_enum_variant_info,
210-
(enum_did, i, vis));
209+
(enum_did, i));
211210
}
212211
}
213212
}
214213

215214
impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
216215
fn encode_enum_variant_info(&mut self,
217-
(enum_did, index, vis):
218-
(DefId, usize, &hir::Visibility)) {
216+
(enum_did, index):
217+
(DefId, usize)) {
219218
let ecx = self.ecx;
220219
let def = ecx.tcx.lookup_adt_def(enum_did);
221220
let variant = &def.variants[index];
@@ -229,7 +228,10 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
229228
});
230229
encode_name(self.rbml_w, variant.name);
231230
self.encode_parent_item(enum_did);
232-
self.encode_visibility(vis);
231+
232+
let enum_id = ecx.tcx.map.as_local_node_id(enum_did).unwrap();
233+
let enum_vis = &ecx.tcx.map.expect_item(enum_id).vis;
234+
self.encode_visibility(enum_vis);
233235

234236
let attrs = ecx.tcx.get_attrs(vid);
235237
encode_attributes(self.rbml_w, &attrs);
@@ -294,8 +296,8 @@ fn encode_reexports(ecx: &EncodeContext,
294296

295297
impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
296298
fn encode_info_for_mod(&mut self,
297-
(md, attrs, id, name, vis):
298-
(&hir::Mod, &[ast::Attribute], NodeId, Name, &hir::Visibility)) {
299+
FromId(id, (md, attrs, name, vis)):
300+
FromId<(&hir::Mod, &[ast::Attribute], Name, &hir::Visibility)>) {
299301
let ecx = self.ecx();
300302

301303
encode_def_id_and_key(ecx, self.rbml_w, ecx.tcx.map.local_def_id(id));
@@ -936,7 +938,7 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
936938
self.encode_method_argument_names(&decl);
937939
}
938940
hir::ItemMod(ref m) => {
939-
self.encode_info_for_mod((m, &item.attrs, item.id, item.name, &item.vis));
941+
self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, item.name, &item.vis)));
940942
}
941943
hir::ItemForeignMod(ref fm) => {
942944
encode_def_id_and_key(ecx, self.rbml_w, def_id);
@@ -1166,7 +1168,7 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> {
11661168
// no sub-item recording needed in these cases
11671169
}
11681170
hir::ItemEnum(..) => {
1169-
self.encode_enum_variant_infos(def_id, &item.vis);
1171+
self.encode_enum_variant_infos(def_id);
11701172
}
11711173
hir::ItemStruct(ref struct_def, _) => {
11721174
self.encode_addl_struct_info(def_id, struct_def.id(), item);
@@ -1395,11 +1397,10 @@ fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
13951397
let mut index = IndexBuilder::new(ecx, rbml_w);
13961398
index.record(DefId::local(CRATE_DEF_INDEX),
13971399
ItemContentBuilder::encode_info_for_mod,
1398-
(&krate.module,
1399-
&[],
1400-
CRATE_NODE_ID,
1401-
syntax::parse::token::intern(&ecx.link_meta.crate_name),
1402-
&hir::Public));
1400+
FromId(CRATE_NODE_ID, (&krate.module,
1401+
&[],
1402+
syntax::parse::token::intern(&ecx.link_meta.crate_name),
1403+
&hir::Public)));
14031404
krate.visit_all_items(&mut EncodeVisitor {
14041405
index: &mut index,
14051406
});

src/librustc_metadata/index_builder.rs

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use encoder::EncodeContext;
1313
use index::IndexData;
1414
use rbml::writer::Encoder;
1515
use rustc::dep_graph::DepNode;
16+
use rustc::hir;
1617
use rustc::hir::def_id::DefId;
17-
use rustc::ty;
18+
use rustc::ty::{self, TyCtxt};
1819
use rustc_data_structures::fnv::FnvHashMap;
20+
use syntax::ast;
1921
use std::ops::{Deref, DerefMut};
2022

2123
/// Builder that can encode new items, adding them into the index.
@@ -51,21 +53,34 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> {
5153
}
5254
}
5355

54-
/// Records that `id` is being emitted at the current offset.
55-
/// This data is later used to construct the item index in the
56-
/// metadata so we can quickly find the data for a given item.
56+
/// Emit the data for a def-id to the metadata. The function to
57+
/// emit the data is `op`, and it will be given `data` as
58+
/// arguments. This `record` function will start/end an RBML tag
59+
/// and record the current offset for use in the index, calling
60+
/// `op` to generate the data in the RBML tag.
5761
///
58-
/// Returns a dep-graph task that you should keep live as long as
59-
/// the data for this item is being emitted.
62+
/// In addition, it will setup a dep-graph task to track what data
63+
/// `op` accesses to generate the metadata, which is later used by
64+
/// incremental compilation to compute a hash for the metadata and
65+
/// track changes.
66+
///
67+
/// The reason that `op` is a function pointer, and not a closure,
68+
/// is that we want to be able to completely track all data it has
69+
/// access to, so that we can be sure that `DATA: DepGraphRead`
70+
/// holds, and that it is therefore not gaining "secret" access to
71+
/// bits of HIR or other state that would not be trackd by the
72+
/// content system.
6073
pub fn record<DATA>(&mut self,
6174
id: DefId,
6275
op: fn(&mut ItemContentBuilder<'a, 'tcx, 'encoder>, DATA),
6376
data: DATA)
77+
where DATA: DepGraphRead
6478
{
6579
let position = self.rbml_w.mark_stable_position();
6680
self.items.record(id, position);
6781
let _task = self.ecx.tcx.dep_graph.in_task(DepNode::MetaData(id));
6882
self.rbml_w.start_tag(tag_items_data_item).unwrap();
83+
data.read(self.ecx.tcx);
6984
op(self, data);
7085
self.rbml_w.end_tag().unwrap();
7186
}
@@ -100,3 +115,82 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
100115
}
101116
}
102117

118+
/// Trait that registers reads for types that are tracked in the
119+
/// dep-graph. Mostly it is implemented for indices like DefId etc
120+
/// which do not need to register a read.
121+
pub trait DepGraphRead {
122+
fn read(&self, tcx: TyCtxt);
123+
}
124+
125+
impl DepGraphRead for usize {
126+
fn read(&self, _tcx: TyCtxt) { }
127+
}
128+
129+
impl DepGraphRead for DefId {
130+
fn read(&self, _tcx: TyCtxt) { }
131+
}
132+
133+
impl DepGraphRead for ast::NodeId {
134+
fn read(&self, _tcx: TyCtxt) { }
135+
}
136+
137+
impl<T> DepGraphRead for Option<T>
138+
where T: DepGraphRead
139+
{
140+
fn read(&self, tcx: TyCtxt) {
141+
match *self {
142+
Some(ref v) => v.read(tcx),
143+
None => (),
144+
}
145+
}
146+
}
147+
148+
impl<T> DepGraphRead for [T]
149+
where T: DepGraphRead
150+
{
151+
fn read(&self, tcx: TyCtxt) {
152+
for i in self {
153+
i.read(tcx);
154+
}
155+
}
156+
}
157+
158+
macro_rules! read_tuple {
159+
($($name:ident),*) => {
160+
impl<$($name),*> DepGraphRead for ($($name),*)
161+
where $($name: DepGraphRead),*
162+
{
163+
#[allow(non_snake_case)]
164+
fn read(&self, tcx: TyCtxt) {
165+
let &($(ref $name),*) = self;
166+
$($name.read(tcx);)*
167+
}
168+
}
169+
}
170+
}
171+
read_tuple!(A,B);
172+
read_tuple!(A,B,C);
173+
174+
macro_rules! read_hir {
175+
($t:ty) => {
176+
impl<'tcx> DepGraphRead for &'tcx $t {
177+
fn read(&self, tcx: TyCtxt) {
178+
tcx.map.read(self.id);
179+
}
180+
}
181+
}
182+
}
183+
read_hir!(hir::Item);
184+
read_hir!(hir::ImplItem);
185+
read_hir!(hir::TraitItem);
186+
read_hir!(hir::ForeignItem);
187+
188+
/// You can use `FromId(X, ...)` to indicate that `...` came from node
189+
/// `X`; so we will add a read from the suitable `Hir` node.
190+
pub struct FromId<T>(pub ast::NodeId, pub T);
191+
192+
impl<T> DepGraphRead for FromId<T> {
193+
fn read(&self, tcx: TyCtxt) {
194+
tcx.map.read(self.0);
195+
}
196+
}

0 commit comments

Comments
 (0)