]> git.lizzy.rs Git - rust.git/blob - src/librustc/dep_graph/dep_node.rs
Auto merge of #39304 - jrmuizel:drop-flags, r=steveklabnik
[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     CoherenceCheckImpl(D),
74     CoherenceOverlapCheck(D),
75     CoherenceOverlapCheckSpecial(D),
76     CoherenceOverlapInherentCheck(D),
77     CoherenceOrphanCheck(D),
78     Variance,
79     WfCheck(D),
80     TypeckItemType(D),
81     Dropck,
82     DropckImpl(D),
83     UnusedTraitCheck,
84     CheckConst(D),
85     Privacy,
86     IntrinsicCheck(D),
87     MatchCheck(D),
88
89     // Represents the MIR for a fn; also used as the task node for
90     // things read/modify that MIR.
91     Mir(D),
92
93     BorrowCheck(D),
94     RvalueCheck(D),
95     Reachability,
96     DeadCheck,
97     StabilityCheck(D),
98     LateLintCheck,
99     TransCrate,
100     TransCrateItem(D),
101     TransInlinedItem(D),
102     TransWriteMetadata,
103     LinkBinary,
104
105     // Nodes representing bits of computed IR in the tcx. Each shared
106     // table in the tcx (or elsewhere) maps to one of these
107     // nodes. Often we map multiple tables to the same node if there
108     // is no point in distinguishing them (e.g., both the type and
109     // predicates for an item wind up in `ItemSignature`).
110     AssociatedItems(D),
111     ItemSignature(D),
112     SizedConstraint(D),
113     AssociatedItemDefIds(D),
114     InherentImpls(D),
115     TypeckTables(D),
116     UsedTraitImports(D),
117
118     // The set of impls for a given trait. Ultimately, it would be
119     // nice to get more fine-grained here (e.g., to include a
120     // simplified type), but we can't do that until we restructure the
121     // HIR to distinguish the *header* of an impl from its body.  This
122     // is because changes to the header may change the self-type of
123     // the impl and hence would require us to be more conservative
124     // than changes in the impl body.
125     TraitImpls(D),
126
127     // Nodes representing caches. To properly handle a true cache, we
128     // don't use a DepTrackingMap, but rather we push a task node.
129     // Otherwise the write into the map would be incorrectly
130     // attributed to the first task that happened to fill the cache,
131     // which would yield an overly conservative dep-graph.
132     TraitItems(D),
133     ReprHints(D),
134
135     // Trait selection cache is a little funny. Given a trait
136     // reference like `Foo: SomeTrait<Bar>`, there could be
137     // arbitrarily many def-ids to map on in there (e.g., `Foo`,
138     // `SomeTrait`, `Bar`). We could have a vector of them, but it
139     // requires heap-allocation, and trait sel in general can be a
140     // surprisingly hot path. So instead we pick two def-ids: the
141     // trait def-id, and the first def-id in the input types. If there
142     // is no def-id in the input types, then we use the trait def-id
143     // again. So for example:
144     //
145     // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
146     // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
147     // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
148     // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
149     // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
150     // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
151     // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
152     // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
153     // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
154     //
155     // You can see that we map many trait refs to the same
156     // trait-select node.  This is not a problem, it just means
157     // imprecision in our dep-graph tracking.  The important thing is
158     // that for any given trait-ref, we always map to the **same**
159     // trait-select node.
160     TraitSelect { trait_def_id: D, input_def_id: D },
161
162     // For proj. cache, we just keep a list of all def-ids, since it is
163     // not a hotspot.
164     ProjectionCache { def_ids: Vec<D> },
165 }
166
167 impl<D: Clone + Debug> DepNode<D> {
168     /// Used in testing
169     pub fn from_label_string(label: &str, data: D) -> Result<DepNode<D>, ()> {
170         macro_rules! check {
171             ($($name:ident,)*) => {
172                 match label {
173                     $(stringify!($name) => Ok(DepNode::$name(data)),)*
174                     _ => Err(())
175                 }
176             }
177         }
178
179         if label == "Krate" {
180             // special case
181             return Ok(DepNode::Krate);
182         }
183
184         check! {
185             CollectItem,
186             BorrowCheck,
187             Hir,
188             HirBody,
189             TransCrateItem,
190             TypeckItemType,
191             AssociatedItems,
192             ItemSignature,
193             AssociatedItemDefIds,
194             InherentImpls,
195             TypeckTables,
196             UsedTraitImports,
197             TraitImpls,
198             ReprHints,
199         }
200     }
201
202     pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
203         where OP: FnMut(&D) -> Option<E>, E: Clone + Debug
204     {
205         use self::DepNode::*;
206
207         match *self {
208             Krate => Some(Krate),
209             CollectLanguageItems => Some(CollectLanguageItems),
210             CheckStaticRecursion => Some(CheckStaticRecursion),
211             ResolveLifetimes => Some(ResolveLifetimes),
212             RegionResolveCrate => Some(RegionResolveCrate),
213             CheckLoops => Some(CheckLoops),
214             PluginRegistrar => Some(PluginRegistrar),
215             StabilityIndex => Some(StabilityIndex),
216             Coherence => Some(Coherence),
217             EffectCheck => Some(EffectCheck),
218             Liveness => Some(Liveness),
219             Resolve => Some(Resolve),
220             EntryPoint => Some(EntryPoint),
221             CheckEntryFn => Some(CheckEntryFn),
222             Variance => Some(Variance),
223             Dropck => Some(Dropck),
224             UnusedTraitCheck => Some(UnusedTraitCheck),
225             Privacy => Some(Privacy),
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             CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
243             CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
244             CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
245             CoherenceOverlapInherentCheck(ref d) => op(d).map(CoherenceOverlapInherentCheck),
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             DropckImpl(ref d) => op(d).map(DropckImpl),
250             CheckConst(ref d) => op(d).map(CheckConst),
251             IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
252             MatchCheck(ref d) => op(d).map(MatchCheck),
253             Mir(ref d) => op(d).map(Mir),
254             BorrowCheck(ref d) => op(d).map(BorrowCheck),
255             RvalueCheck(ref d) => op(d).map(RvalueCheck),
256             StabilityCheck(ref d) => op(d).map(StabilityCheck),
257             TransCrateItem(ref d) => op(d).map(TransCrateItem),
258             TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
259             AssociatedItems(ref d) => op(d).map(AssociatedItems),
260             ItemSignature(ref d) => op(d).map(ItemSignature),
261             SizedConstraint(ref d) => op(d).map(SizedConstraint),
262             AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
263             InherentImpls(ref d) => op(d).map(InherentImpls),
264             TypeckTables(ref d) => op(d).map(TypeckTables),
265             UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
266             TraitImpls(ref d) => op(d).map(TraitImpls),
267             TraitItems(ref d) => op(d).map(TraitItems),
268             ReprHints(ref d) => op(d).map(ReprHints),
269             TraitSelect { ref trait_def_id, ref input_def_id } => {
270                 op(trait_def_id).and_then(|trait_def_id| {
271                     op(input_def_id).and_then(|input_def_id| {
272                         Some(TraitSelect { trait_def_id: trait_def_id,
273                                            input_def_id: input_def_id })
274                     })
275                 })
276             }
277             ProjectionCache { ref def_ids } => {
278                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
279                 def_ids.map(|d| ProjectionCache { def_ids: d })
280             }
281         }
282     }
283 }
284
285 /// A "work product" corresponds to a `.o` (or other) file that we
286 /// save in between runs. These ids do not have a DefId but rather
287 /// some independent path or string that persists between runs without
288 /// the need to be mapped or unmapped. (This ensures we can serialize
289 /// them even in the absence of a tcx.)
290 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
291 pub struct WorkProductId(pub String);
292