]> git.lizzy.rs Git - rust.git/blob - src/librustc/dep_graph/dep_node.rs
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
[rust.git] / src / librustc / dep_graph / dep_node.rs
1 // Copyright 2014 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.
4 //
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.
10
11 use hir::def_id::CrateNum;
12 use std::fmt::Debug;
13 use std::sync::Arc;
14
15 macro_rules! try_opt {
16     ($e:expr) => (
17         match $e {
18             Some(r) => r,
19             None => return None,
20         }
21     )
22 }
23
24 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
25 pub enum DepNode<D: Clone + Debug> {
26     // The `D` type is "how definitions are identified".
27     // During compilation, it is always `DefId`, but when serializing
28     // it is mapped to `DefPath`.
29
30     // Represents the `Krate` as a whole (the `hir::Krate` value) (as
31     // distinct from the krate module). This is basically a hash of
32     // the entire krate, so if you read from `Krate` (e.g., by calling
33     // `tcx.hir.krate()`), we will have to assume that any change
34     // means that you need to be recompiled. This is because the
35     // `Krate` value gives you access to all other items. To avoid
36     // this fate, do not call `tcx.hir.krate()`; instead, prefer
37     // wrappers like `tcx.visit_all_items_in_krate()`.  If there is no
38     // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
39     // access to the krate, but you must remember to add suitable
40     // edges yourself for the individual items that you read.
41     Krate,
42
43     // Represents the HIR node with the given node-id
44     Hir(D),
45
46     // Represents the body of a function or method. The def-id is that of the
47     // function/method.
48     HirBody(D),
49
50     // Represents the metadata for a given HIR node, typically found
51     // in an extern crate.
52     MetaData(D),
53
54     // Represents some artifact that we save to disk. Note that these
55     // do not have a def-id as part of their identifier.
56     WorkProduct(Arc<WorkProductId>),
57
58     // Represents different phases in the compiler.
59     CollectLanguageItems,
60     ResolveLifetimes,
61     RegionResolveCrate,
62     PluginRegistrar,
63     StabilityIndex,
64     CollectItem(D),
65     CollectItemSig(D),
66     Coherence,
67     Resolve,
68     EntryPoint,
69     CheckEntryFn,
70     CoherenceCheckTrait(D),
71     CoherenceCheckImpl(D),
72     CoherenceOverlapCheck(D),
73     CoherenceOverlapCheckSpecial(D),
74     CoherenceOrphanCheck(D),
75     Variance,
76     WfCheck(D),
77     TypeckItemType(D),
78     UnusedTraitCheck,
79     CheckConst(D),
80     PrivacyAccessLevels(CrateNum),
81     IntrinsicCheck(D),
82     MatchCheck(D),
83
84     // Represents the MIR for a fn; also used as the task node for
85     // things read/modify that MIR.
86     MirKrate,
87     Mir(D),
88     MirShim(Vec<D>),
89
90     BorrowCheckKrate,
91     BorrowCheck(D),
92     RvalueCheck(D),
93     Reachability,
94     DeadCheck,
95     StabilityCheck(D),
96     LateLintCheck,
97     TransCrate,
98     TransCrateItem(D),
99     TransInlinedItem(D),
100     TransWriteMetadata,
101     LinkBinary,
102
103     // Nodes representing bits of computed IR in the tcx. Each shared
104     // table in the tcx (or elsewhere) maps to one of these
105     // nodes. Often we map multiple tables to the same node if there
106     // is no point in distinguishing them (e.g., both the type and
107     // predicates for an item wind up in `ItemSignature`).
108     AssociatedItems(D),
109     ItemSignature(D),
110     TypeParamPredicates((D, D)),
111     SizedConstraint(D),
112     AdtDestructor(D),
113     AssociatedItemDefIds(D),
114     InherentImpls(D),
115     TypeckBodiesKrate,
116     TypeckTables(D),
117     UsedTraitImports(D),
118     MonomorphicConstEval(D),
119
120     // The set of impls for a given trait. Ultimately, it would be
121     // nice to get more fine-grained here (e.g., to include a
122     // simplified type), but we can't do that until we restructure the
123     // HIR to distinguish the *header* of an impl from its body.  This
124     // is because changes to the header may change the self-type of
125     // the impl and hence would require us to be more conservative
126     // than changes in the impl body.
127     TraitImpls(D),
128
129     // Nodes representing caches. To properly handle a true cache, we
130     // don't use a DepTrackingMap, but rather we push a task node.
131     // Otherwise the write into the map would be incorrectly
132     // attributed to the first task that happened to fill the cache,
133     // which would yield an overly conservative dep-graph.
134     TraitItems(D),
135     ReprHints(D),
136
137     // Trait selection cache is a little funny. Given a trait
138     // reference like `Foo: SomeTrait<Bar>`, there could be
139     // arbitrarily many def-ids to map on in there (e.g., `Foo`,
140     // `SomeTrait`, `Bar`). We could have a vector of them, but it
141     // requires heap-allocation, and trait sel in general can be a
142     // surprisingly hot path. So instead we pick two def-ids: the
143     // trait def-id, and the first def-id in the input types. If there
144     // is no def-id in the input types, then we use the trait def-id
145     // again. So for example:
146     //
147     // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
148     // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
149     // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
150     // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
151     // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
152     // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
153     // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
154     // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
155     // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
156     //
157     // You can see that we map many trait refs to the same
158     // trait-select node.  This is not a problem, it just means
159     // imprecision in our dep-graph tracking.  The important thing is
160     // that for any given trait-ref, we always map to the **same**
161     // trait-select node.
162     TraitSelect { trait_def_id: D, input_def_id: D },
163
164     // For proj. cache, we just keep a list of all def-ids, since it is
165     // not a hotspot.
166     ProjectionCache { def_ids: Vec<D> },
167 }
168
169 impl<D: Clone + Debug> DepNode<D> {
170     /// Used in testing
171     pub fn from_label_string(label: &str, data: D) -> Result<DepNode<D>, ()> {
172         macro_rules! check {
173             ($($name:ident,)*) => {
174                 match label {
175                     $(stringify!($name) => Ok(DepNode::$name(data)),)*
176                     _ => Err(())
177                 }
178             }
179         }
180
181         if label == "Krate" {
182             // special case
183             return Ok(DepNode::Krate);
184         }
185
186         check! {
187             CollectItem,
188             BorrowCheck,
189             Hir,
190             HirBody,
191             TransCrateItem,
192             TypeckItemType,
193             AssociatedItems,
194             ItemSignature,
195             AssociatedItemDefIds,
196             InherentImpls,
197             TypeckTables,
198             UsedTraitImports,
199             TraitImpls,
200             ReprHints,
201         }
202     }
203
204     pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
205         where OP: FnMut(&D) -> Option<E>, E: Clone + Debug
206     {
207         use self::DepNode::*;
208
209         match *self {
210             Krate => Some(Krate),
211             BorrowCheckKrate => Some(BorrowCheckKrate),
212             MirKrate => Some(MirKrate),
213             TypeckBodiesKrate => Some(TypeckBodiesKrate),
214             CollectLanguageItems => Some(CollectLanguageItems),
215             ResolveLifetimes => Some(ResolveLifetimes),
216             RegionResolveCrate => Some(RegionResolveCrate),
217             PluginRegistrar => Some(PluginRegistrar),
218             StabilityIndex => Some(StabilityIndex),
219             Coherence => Some(Coherence),
220             Resolve => Some(Resolve),
221             EntryPoint => Some(EntryPoint),
222             CheckEntryFn => Some(CheckEntryFn),
223             Variance => Some(Variance),
224             UnusedTraitCheck => Some(UnusedTraitCheck),
225             PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
226             Reachability => Some(Reachability),
227             DeadCheck => Some(DeadCheck),
228             LateLintCheck => Some(LateLintCheck),
229             TransCrate => Some(TransCrate),
230             TransWriteMetadata => Some(TransWriteMetadata),
231             LinkBinary => Some(LinkBinary),
232
233             // work product names do not need to be mapped, because
234             // they are always absolute.
235             WorkProduct(ref id) => Some(WorkProduct(id.clone())),
236
237             Hir(ref d) => op(d).map(Hir),
238             HirBody(ref d) => op(d).map(HirBody),
239             MetaData(ref d) => op(d).map(MetaData),
240             CollectItem(ref d) => op(d).map(CollectItem),
241             CollectItemSig(ref d) => op(d).map(CollectItemSig),
242             CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait),
243             CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
244             CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
245             CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
246             CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
247             WfCheck(ref d) => op(d).map(WfCheck),
248             TypeckItemType(ref d) => op(d).map(TypeckItemType),
249             CheckConst(ref d) => op(d).map(CheckConst),
250             IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
251             MatchCheck(ref d) => op(d).map(MatchCheck),
252             Mir(ref d) => op(d).map(Mir),
253             MirShim(ref def_ids) => {
254                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
255                 def_ids.map(MirShim)
256             }
257             BorrowCheck(ref d) => op(d).map(BorrowCheck),
258             RvalueCheck(ref d) => op(d).map(RvalueCheck),
259             StabilityCheck(ref d) => op(d).map(StabilityCheck),
260             TransCrateItem(ref d) => op(d).map(TransCrateItem),
261             TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
262             AssociatedItems(ref d) => op(d).map(AssociatedItems),
263             ItemSignature(ref d) => op(d).map(ItemSignature),
264             TypeParamPredicates((ref item, ref param)) => {
265                 Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
266             }
267             SizedConstraint(ref d) => op(d).map(SizedConstraint),
268             AdtDestructor(ref d) => op(d).map(AdtDestructor),
269             AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
270             InherentImpls(ref d) => op(d).map(InherentImpls),
271             TypeckTables(ref d) => op(d).map(TypeckTables),
272             UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
273             MonomorphicConstEval(ref d) => op(d).map(MonomorphicConstEval),
274             TraitImpls(ref d) => op(d).map(TraitImpls),
275             TraitItems(ref d) => op(d).map(TraitItems),
276             ReprHints(ref d) => op(d).map(ReprHints),
277             TraitSelect { ref trait_def_id, ref input_def_id } => {
278                 op(trait_def_id).and_then(|trait_def_id| {
279                     op(input_def_id).and_then(|input_def_id| {
280                         Some(TraitSelect { trait_def_id: trait_def_id,
281                                            input_def_id: input_def_id })
282                     })
283                 })
284             }
285             ProjectionCache { ref def_ids } => {
286                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
287                 def_ids.map(|d| ProjectionCache { def_ids: d })
288             }
289         }
290     }
291 }
292
293 /// A "work product" corresponds to a `.o` (or other) file that we
294 /// save in between runs. These ids do not have a DefId but rather
295 /// some independent path or string that persists between runs without
296 /// the need to be mapped or unmapped. (This ensures we can serialize
297 /// them even in the absence of a tcx.)
298 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
299 pub struct WorkProductId(pub String);