8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ //! Builder types for generating the "item data" section of the
12
+ //! metadata. This section winds up looking like this:
13
+ //!
14
+ //! ```
15
+ //! <common::data> // big list of item-like things...
16
+ //! <common::data_item> // ...for most def-ids, there is an entry.
17
+ //! </common::data_item>
18
+ //! </common::data>
19
+ //! ```
20
+ //!
21
+ //! As we generate this listing, we collect the offset of each
22
+ //! `data_item` entry and store it in an index. Then, when we load the
23
+ //! metadata, we can skip right to the metadata for a particular item.
24
+ //!
25
+ //! In addition to the offset, we need to track the data that was used
26
+ //! to generate the contents of each `data_item`. This is so that we
27
+ //! can figure out which HIR nodes contributors to that data for
28
+ //! incremental compilation purposes.
29
+ //!
30
+ //! The `IndexBuilder` facilitates with both of these. It is created
31
+ //! with an RBML encoder isntance (`rbml_w`) along with an
32
+ //! `EncodingContext` (`ecx`), which it encapsulates. It has one main
33
+ //! method, `record()`. You invoke `record` like so to create a new
34
+ //! `data_item` element in the list:
35
+ //!
36
+ //! ```
37
+ //! index.record(some_def_id, callback_fn, data)
38
+ //! ```
39
+ //!
40
+ //! What record will do is to (a) record the current offset, (b) emit
41
+ //! the `common::data_item` tag, and then call `callback_fn` with the
42
+ //! given data as well as an `ItemContentBuilder`. Once `callback_fn`
43
+ //! returns, the `common::data_item` tag will be closed.
44
+ //!
45
+ //! The `ItemContentBuilder` is another type that just offers access
46
+ //! to the `ecx` and `rbml_w` that were given in, as well as
47
+ //! maintaining a list of `xref` instances, which are used to extract
48
+ //! common data so it is not re-serialized.
49
+ //!
50
+ //! `ItemContentBuilder` is a distinct type which does not offer the
51
+ //! `record` method, so that we can ensure that `common::data_item` elements
52
+ //! are never nested.
53
+ //!
54
+ //! In addition, while the `callback_fn` is executing, we will push a
55
+ //! task `MetaData(some_def_id)`, which can then observe the
56
+ //! reads/writes that occur in the task. For this reason, the `data`
57
+ //! argument that is given to the `callback_fn` must implement the
58
+ //! trait `DepGraphRead`, which indicates how to register reads on the
59
+ //! data in this new task (note that many types of data, such as
60
+ //! `DefId`, do not currently require any reads to be registered,
61
+ //! since they are not derived from a HIR node). This is also why we
62
+ //! give a callback fn, rather than taking a closure: it allows us to
63
+ //! easily control precisely what data is given to that fn.
64
+
11
65
use common:: tag_items_data_item;
12
66
use encoder:: EncodeContext ;
13
67
use index:: IndexData ;
@@ -18,7 +72,6 @@ use rustc::hir::def_id::DefId;
18
72
use rustc:: ty:: { self , TyCtxt } ;
19
73
use rustc_data_structures:: fnv:: FnvHashMap ;
20
74
use syntax:: ast;
21
- use std:: ops:: { Deref , DerefMut } ;
22
75
23
76
/// Builder that can encode new items, adding them into the index.
24
77
/// Item encoding cannot be nested.
@@ -53,6 +106,10 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> {
53
106
}
54
107
}
55
108
109
+ pub fn ecx ( & self ) -> & ' a EncodeContext < ' a , ' tcx > {
110
+ self . builder . ecx ( )
111
+ }
112
+
56
113
/// Emit the data for a def-id to the metadata. The function to
57
114
/// emit the data is `op`, and it will be given `data` as
58
115
/// arguments. This `record` function will start/end an RBML tag
@@ -76,34 +133,20 @@ impl<'a, 'tcx, 'encoder> IndexBuilder<'a, 'tcx, 'encoder> {
76
133
data : DATA )
77
134
where DATA : DepGraphRead
78
135
{
79
- let position = self . rbml_w . mark_stable_position ( ) ;
136
+ let position = self . builder . rbml_w . mark_stable_position ( ) ;
80
137
self . items . record ( id, position) ;
81
- let _task = self . ecx . tcx . dep_graph . in_task ( DepNode :: MetaData ( id) ) ;
82
- self . rbml_w . start_tag ( tag_items_data_item) . unwrap ( ) ;
83
- data. read ( self . ecx . tcx ) ;
84
- op ( self , data) ;
85
- self . rbml_w . end_tag ( ) . unwrap ( ) ;
138
+ let _task = self . ecx ( ) . tcx . dep_graph . in_task ( DepNode :: MetaData ( id) ) ;
139
+ self . builder . rbml_w . start_tag ( tag_items_data_item) . unwrap ( ) ;
140
+ data. read ( self . ecx ( ) . tcx ) ;
141
+ op ( & mut self . builder , data) ;
142
+ self . builder . rbml_w . end_tag ( ) . unwrap ( ) ;
86
143
}
87
144
88
145
pub fn into_fields ( self ) -> ( IndexData , FnvHashMap < XRef < ' tcx > , u32 > ) {
89
146
( self . items , self . builder . xrefs )
90
147
}
91
148
}
92
149
93
- impl < ' a , ' tcx , ' encoder > Deref for IndexBuilder < ' a , ' tcx , ' encoder > {
94
- type Target = ItemContentBuilder < ' a , ' tcx , ' encoder > ;
95
-
96
- fn deref ( & self ) -> & Self :: Target {
97
- & self . builder
98
- }
99
- }
100
-
101
- impl < ' a , ' tcx , ' encoder > DerefMut for IndexBuilder < ' a , ' tcx , ' encoder > {
102
- fn deref_mut ( & mut self ) -> & mut Self :: Target {
103
- & mut self . builder
104
- }
105
- }
106
-
107
150
impl < ' a , ' tcx , ' encoder > ItemContentBuilder < ' a , ' tcx , ' encoder > {
108
151
pub fn ecx ( & self ) -> & ' a EncodeContext < ' a , ' tcx > {
109
152
self . ecx
@@ -115,9 +158,10 @@ impl<'a, 'tcx, 'encoder> ItemContentBuilder<'a, 'tcx, 'encoder> {
115
158
}
116
159
}
117
160
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.
161
+ /// Trait used for data that can be passed from outside a dep-graph
162
+ /// task. The data must either be of some safe type, such as a
163
+ /// `DefId` index, or implement the `read` method so that it can add
164
+ /// a read of whatever dep-graph nodes are appropriate.
121
165
pub trait DepGraphRead {
122
166
fn read ( & self , tcx : TyCtxt ) ;
123
167
}
@@ -185,8 +229,10 @@ read_hir!(hir::ImplItem);
185
229
read_hir ! ( hir:: TraitItem ) ;
186
230
read_hir ! ( hir:: ForeignItem ) ;
187
231
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.
232
+ /// Newtype that can be used to package up misc data extracted from a
233
+ /// HIR node that doesn't carry its own id. This will allow an
234
+ /// arbitrary `T` to be passed in, but register a read on the given
235
+ /// node-id.
190
236
pub struct FromId < T > ( pub ast:: NodeId , pub T ) ;
191
237
192
238
impl < T > DepGraphRead for FromId < T > {
0 commit comments