]> git.lizzy.rs Git - rust.git/blob - src/librustc/dep_graph/dep_node.rs
Rollup merge of #40683 - nikomatsakis:incr-comp-coerce-unsized-info, r=eddyb
[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     CheckStaticRecursion,
61     ResolveLifetimes,
62     RegionResolveCrate,
63     CheckLoops,
64     PluginRegistrar,
65     StabilityIndex,
66     CollectItem(D),
67     CollectItemSig(D),
68     Coherence,
69     EffectCheck,
70     Liveness,
71     Resolve,
72     EntryPoint,
73     CheckEntryFn,
74     CoherenceCheckTrait(D),
75     CoherenceCheckImpl(D),
76     CoherenceOverlapCheck(D),
77     CoherenceOverlapCheckSpecial(D),
78     CoherenceOrphanCheck(D),
79     Variance,
80     WfCheck(D),
81     TypeckItemType(D),
82     UnusedTraitCheck,
83     CheckConst(D),
84     PrivacyAccessLevels(CrateNum),
85     IntrinsicCheck(D),
86     MatchCheck(D),
87
88     // Represents the MIR for a fn; also used as the task node for
89     // things read/modify that MIR.
90     MirKrate,
91     Mir(D),
92     MirShim(Vec<D>),
93
94     BorrowCheckKrate,
95     BorrowCheck(D),
96     RvalueCheck(D),
97     Reachability,
98     DeadCheck,
99     StabilityCheck(D),
100     LateLintCheck,
101     TransCrate,
102     TransCrateItem(D),
103     TransInlinedItem(D),
104     TransWriteMetadata,
105     LinkBinary,
106
107     // Nodes representing bits of computed IR in the tcx. Each shared
108     // table in the tcx (or elsewhere) maps to one of these
109     // nodes. Often we map multiple tables to the same node if there
110     // is no point in distinguishing them (e.g., both the type and
111     // predicates for an item wind up in `ItemSignature`).
112     AssociatedItems(D),
113     ItemSignature(D),
114     TypeParamPredicates((D, D)),
115     SizedConstraint(D),
116     AdtDestructor(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             UnusedTraitCheck => Some(UnusedTraitCheck),
233             PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
234             Reachability => Some(Reachability),
235             DeadCheck => Some(DeadCheck),
236             LateLintCheck => Some(LateLintCheck),
237             TransCrate => Some(TransCrate),
238             TransWriteMetadata => Some(TransWriteMetadata),
239             LinkBinary => Some(LinkBinary),
240
241             // work product names do not need to be mapped, because
242             // they are always absolute.
243             WorkProduct(ref id) => Some(WorkProduct(id.clone())),
244
245             Hir(ref d) => op(d).map(Hir),
246             HirBody(ref d) => op(d).map(HirBody),
247             MetaData(ref d) => op(d).map(MetaData),
248             CollectItem(ref d) => op(d).map(CollectItem),
249             CollectItemSig(ref d) => op(d).map(CollectItemSig),
250             CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait),
251             CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
252             CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
253             CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
254             CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
255             WfCheck(ref d) => op(d).map(WfCheck),
256             TypeckItemType(ref d) => op(d).map(TypeckItemType),
257             CheckConst(ref d) => op(d).map(CheckConst),
258             IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
259             MatchCheck(ref d) => op(d).map(MatchCheck),
260             Mir(ref d) => op(d).map(Mir),
261             MirShim(ref def_ids) => {
262                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
263                 def_ids.map(MirShim)
264             }
265             BorrowCheck(ref d) => op(d).map(BorrowCheck),
266             RvalueCheck(ref d) => op(d).map(RvalueCheck),
267             StabilityCheck(ref d) => op(d).map(StabilityCheck),
268             TransCrateItem(ref d) => op(d).map(TransCrateItem),
269             TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
270             AssociatedItems(ref d) => op(d).map(AssociatedItems),
271             ItemSignature(ref d) => op(d).map(ItemSignature),
272             TypeParamPredicates((ref item, ref param)) => {
273                 Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
274             }
275             SizedConstraint(ref d) => op(d).map(SizedConstraint),
276             AdtDestructor(ref d) => op(d).map(AdtDestructor),
277             AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
278             InherentImpls(ref d) => op(d).map(InherentImpls),
279             TypeckTables(ref d) => op(d).map(TypeckTables),
280             UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
281             MonomorphicConstEval(ref d) => op(d).map(MonomorphicConstEval),
282             TraitImpls(ref d) => op(d).map(TraitImpls),
283             TraitItems(ref d) => op(d).map(TraitItems),
284             ReprHints(ref d) => op(d).map(ReprHints),
285             TraitSelect { ref trait_def_id, ref input_def_id } => {
286                 op(trait_def_id).and_then(|trait_def_id| {
287                     op(input_def_id).and_then(|input_def_id| {
288                         Some(TraitSelect { trait_def_id: trait_def_id,
289                                            input_def_id: input_def_id })
290                     })
291                 })
292             }
293             ProjectionCache { ref def_ids } => {
294                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
295                 def_ids.map(|d| ProjectionCache { def_ids: d })
296             }
297         }
298     }
299 }
300
301 /// A "work product" corresponds to a `.o` (or other) file that we
302 /// save in between runs. These ids do not have a DefId but rather
303 /// some independent path or string that persists between runs without
304 /// the need to be mapped or unmapped. (This ensures we can serialize
305 /// them even in the absence of a tcx.)
306 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
307 pub struct WorkProductId(pub String);