1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use self::thread::{DepGraphThreadData, DepMessage};
12 use middle::def_id::DefId;
15 use rustc_front::intravisit::Visitor;
24 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
26 // Represents the `Krate` as a whole (the `hir::Krate` value) (as
27 // distinct from the krate module). This is basically a hash of
28 // the entire krate, so if you read from `Krate` (e.g., by calling
29 // `tcx.map.krate()`), we will have to assume that any change
30 // means that you need to be recompiled. This is because the
31 // `Krate` value gives you access to all other items. To avoid
32 // this fate, do not call `tcx.map.krate()`; instead, prefer
33 // wrappers like `tcx.visit_all_items_in_krate()`. If there is no
34 // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
35 // access to the krate, but you must remember to add suitable
36 // edges yourself for the individual items that you read.
39 // Represents the HIR node with the given node-id
42 // Represents different phases in the compiler.
45 CoherenceCheckImpl(DefId),
46 CoherenceOverlapCheck(DefId),
47 CoherenceOverlapCheckSpecial(DefId),
48 CoherenceOrphanCheck(DefId),
51 TypeckItemType(DefId),
52 TypeckItemBody(DefId),
57 IntrinsicCheck(DefId),
59 MirMapConstruction(DefId),
68 TransCrateItem(DefId),
69 TransInlinedItem(DefId),
72 // Nodes representing bits of computed IR in the tcx. Each shared
73 // table in the tcx (or elsewhere) maps to one of these
74 // nodes. Often we map multiple tables to the same node if there
75 // is no point in distinguishing them (e.g., both the type and
76 // predicates for an item wind up in `ItemSignature`). Other
77 // times, such as `ImplItems` vs `TraitItemDefIds`, tables which
78 // might be mergable are kept distinct because the sets of def-ids
79 // to which they apply are disjoint, and hence we might as well
80 // have distinct labels for easier debugging.
81 ImplOrTraitItems(DefId),
84 TraitItemDefIds(DefId),
88 // The set of impls for a given trait. Ultimately, it would be
89 // nice to get more fine-grained here (e.g., to include a
90 // simplified type), but we can't do that until we restructure the
91 // HIR to distinguish the *header* of an impl from its body. This
92 // is because changes to the header may change the self-type of
93 // the impl and hence would require us to be more conservative
94 // than changes in the impl body.
97 // Nodes representing caches. To properly handle a true cache, we
98 // don't use a DepTrackingMap, but rather we push a task node.
99 // Otherwise the write into the map would be incorrectly
100 // attributed to the first task that happened to fill the cache,
101 // which would yield an overly conservative dep-graph.
108 pub struct DepGraph {
109 data: Rc<DepGraphThreadData>
113 pub fn new(enabled: bool) -> DepGraph {
115 data: Rc::new(DepGraphThreadData::new(enabled))
119 /// True if we are actually building a dep-graph. If this returns false,
120 /// then the other methods on this `DepGraph` will have no net effect.
122 pub fn enabled(&self) -> bool {
126 pub fn query(&self) -> DepGraphQuery {
130 pub fn in_ignore<'graph>(&'graph self) -> raii::IgnoreTask<'graph> {
131 raii::IgnoreTask::new(&self.data)
134 pub fn in_task<'graph>(&'graph self, key: DepNode) -> raii::DepTask<'graph> {
135 raii::DepTask::new(&self.data, key)
138 pub fn with_ignore<OP,R>(&self, op: OP) -> R
139 where OP: FnOnce() -> R
141 let _task = self.in_ignore();
145 pub fn with_task<OP,R>(&self, key: DepNode, op: OP) -> R
146 where OP: FnOnce() -> R
148 let _task = self.in_task(key);
152 pub fn read(&self, v: DepNode) {
153 self.data.enqueue(DepMessage::Read(v));
156 pub fn write(&self, v: DepNode) {
157 self.data.enqueue(DepMessage::Write(v));
161 pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
163 pub use self::query::DepGraphQuery;
165 /// Visit all the items in the krate in some order. When visiting a
166 /// particular item, first create a dep-node by calling `dep_node_fn`
167 /// and push that onto the dep-graph stack of tasks, and also create a
168 /// read edge from the corresponding AST node. This is used in
169 /// compiler passes to automatically record the item that they are
171 pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &ty::ctxt<'tcx>,
174 where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
176 struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> {
177 tcx: &'visit ty::ctxt<'tcx>,
178 dep_node_fn: &'visit mut F,
179 visitor: &'visit mut V
182 impl<'visit, 'tcx, F, V> Visitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
183 where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
185 fn visit_item(&mut self, i: &'tcx hir::Item) {
186 let item_def_id = self.tcx.map.local_def_id(i.id);
187 let task_id = (self.dep_node_fn)(item_def_id);
188 debug!("About to start task {:?}", task_id);
189 let _task = self.tcx.dep_graph.in_task(task_id);
190 self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
191 self.visitor.visit_item(i)
195 let krate = tcx.dep_graph.with_ignore(|| tcx.map.krate());
196 let mut tracking_visitor = TrackingVisitor {
198 dep_node_fn: &mut dep_node_fn,
201 krate.visit_all_items(&mut tracking_visitor)