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