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.
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 hir::def_id::CrateNum;
15 macro_rules! try_opt {
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`.
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.
43 /// Represents the HIR node with the given node-id
46 /// Represents the body of a function or method. The def-id is that of the
50 /// Represents the metadata for a given HIR node, typically found
51 /// in an extern crate.
54 /// Represents some piece of metadata global to its crate.
55 GlobalMetaData(D, GlobalMetaDataKind),
57 /// Represents some artifact that we save to disk. Note that these
58 /// do not have a def-id as part of their identifier.
59 WorkProduct(Arc<WorkProductId>),
61 // Represents different phases in the compiler.
65 CoherenceCheckTrait(D),
66 CoherenceCheckImpl(D),
67 CoherenceOverlapCheck(D),
68 CoherenceOverlapCheckSpecial(D),
70 PrivacyAccessLevels(CrateNum),
72 // Represents the MIR for a fn; also used as the task node for
73 // things read/modify that MIR.
88 // Nodes representing bits of computed IR in the tcx. Each shared
89 // table in the tcx (or elsewhere) maps to one of these
90 // nodes. Often we map multiple tables to the same node if there
91 // is no point in distinguishing them (e.g., both the type and
92 // predicates for an item wind up in `ItemSignature`).
95 ItemVarianceConstraints(D),
98 TypeParamPredicates((D, D)),
102 AssociatedItemDefIds(D),
109 SpecializationGraph(D),
117 /// The set of impls for a given trait. Ultimately, it would be
118 /// nice to get more fine-grained here (e.g., to include a
119 /// simplified type), but we can't do that until we restructure the
120 /// HIR to distinguish the *header* of an impl from its body. This
121 /// is because changes to the header may change the self-type of
122 /// the impl and hence would require us to be more conservative
123 /// than changes in the impl body.
128 // Nodes representing caches. To properly handle a true cache, we
129 // don't use a DepTrackingMap, but rather we push a task node.
130 // Otherwise the write into the map would be incorrectly
131 // attributed to the first task that happened to fill the cache,
132 // which would yield an overly conservative dep-graph.
136 /// Trait selection cache is a little funny. Given a trait
137 /// reference like `Foo: SomeTrait<Bar>`, there could be
138 /// arbitrarily many def-ids to map on in there (e.g., `Foo`,
139 /// `SomeTrait`, `Bar`). We could have a vector of them, but it
140 /// requires heap-allocation, and trait sel in general can be a
141 /// surprisingly hot path. So instead we pick two def-ids: the
142 /// trait def-id, and the first def-id in the input types. If there
143 /// is no def-id in the input types, then we use the trait def-id
144 /// again. So for example:
146 /// - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
147 /// - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
148 /// - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
149 /// - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
150 /// - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
151 /// - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
152 /// - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
153 /// - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
154 /// - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
156 /// You can see that we map many trait refs to the same
157 /// trait-select node. This is not a problem, it just means
158 /// imprecision in our dep-graph tracking. The important thing is
159 /// that for any given trait-ref, we always map to the **same**
160 /// trait-select node.
161 TraitSelect { trait_def_id: D, input_def_id: D },
163 /// For proj. cache, we just keep a list of all def-ids, since it is
165 ProjectionCache { def_ids: Vec<D> },
172 ItemBodyNestedBodies(D),
173 ConstIsRvaluePromotableToStatic(D),
182 impl<D: Clone + Debug> DepNode<D> {
184 pub fn from_label_string(label: &str, data: D) -> Result<DepNode<D>, ()> {
186 ($($name:ident,)*) => {
188 $(stringify!($name) => Ok(DepNode::$name(data)),)*
194 if label == "Krate" {
196 return Ok(DepNode::Krate);
208 AssociatedItemDefIds,
217 pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
218 where OP: FnMut(&D) -> Option<E>, E: Clone + Debug
220 use self::DepNode::*;
223 Krate => Some(Krate),
224 BorrowCheckKrate => Some(BorrowCheckKrate),
225 MirKrate => Some(MirKrate),
226 TypeckBodiesKrate => Some(TypeckBodiesKrate),
227 Coherence => Some(Coherence),
228 CrateVariances => Some(CrateVariances),
229 Resolve => Some(Resolve),
230 Variance => Some(Variance),
231 PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
232 Reachability => Some(Reachability),
233 MirKeys => Some(MirKeys),
234 LateLintCheck => Some(LateLintCheck),
235 TransWriteMetadata => Some(TransWriteMetadata),
237 // work product names do not need to be mapped, because
238 // they are always absolute.
239 WorkProduct(ref id) => Some(WorkProduct(id.clone())),
241 IsCopy(ref d) => op(d).map(IsCopy),
242 IsSized(ref d) => op(d).map(IsSized),
243 IsFreeze(ref d) => op(d).map(IsFreeze),
244 NeedsDrop(ref d) => op(d).map(NeedsDrop),
245 Layout(ref d) => op(d).map(Layout),
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 CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait),
250 CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
251 CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
252 CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
253 Mir(ref d) => op(d).map(Mir),
254 MirShim(ref def_ids) => {
255 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
258 BorrowCheck(ref d) => op(d).map(BorrowCheck),
259 RegionMaps(ref d) => op(d).map(RegionMaps),
260 RvalueCheck(ref d) => op(d).map(RvalueCheck),
261 TransCrateItem(ref d) => op(d).map(TransCrateItem),
262 AssociatedItems(ref d) => op(d).map(AssociatedItems),
263 ItemSignature(ref d) => op(d).map(ItemSignature),
264 ItemVariances(ref d) => op(d).map(ItemVariances),
265 ItemVarianceConstraints(ref d) => op(d).map(ItemVarianceConstraints),
266 IsForeignItem(ref d) => op(d).map(IsForeignItem),
267 TypeParamPredicates((ref item, ref param)) => {
268 Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
270 SizedConstraint(ref d) => op(d).map(SizedConstraint),
271 DtorckConstraint(ref d) => op(d).map(DtorckConstraint),
272 AdtDestructor(ref d) => op(d).map(AdtDestructor),
273 AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
274 InherentImpls(ref d) => op(d).map(InherentImpls),
275 TypeckTables(ref d) => op(d).map(TypeckTables),
276 UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
277 ConstEval(ref d) => op(d).map(ConstEval),
278 SymbolName(ref d) => op(d).map(SymbolName),
279 SpecializationGraph(ref d) => op(d).map(SpecializationGraph),
280 ObjectSafety(ref d) => op(d).map(ObjectSafety),
281 TraitImpls(ref d) => op(d).map(TraitImpls),
282 AllLocalTraitImpls => Some(AllLocalTraitImpls),
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 })
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 })
297 ParamEnv(ref d) => op(d).map(ParamEnv),
298 DescribeDef(ref d) => op(d).map(DescribeDef),
299 DefSpan(ref d) => op(d).map(DefSpan),
300 Stability(ref d) => op(d).map(Stability),
301 Deprecation(ref d) => op(d).map(Deprecation),
302 ItemAttrs(ref d) => op(d).map(ItemAttrs),
303 FnArgNames(ref d) => op(d).map(FnArgNames),
304 ImplParent(ref d) => op(d).map(ImplParent),
305 TraitOfItem(ref d) => op(d).map(TraitOfItem),
306 IsExportedSymbol(ref d) => op(d).map(IsExportedSymbol),
307 ItemBodyNestedBodies(ref d) => op(d).map(ItemBodyNestedBodies),
308 ConstIsRvaluePromotableToStatic(ref d) => op(d).map(ConstIsRvaluePromotableToStatic),
309 IsMirAvailable(ref d) => op(d).map(IsMirAvailable),
310 GlobalMetaData(ref d, kind) => op(d).map(|d| GlobalMetaData(d, kind)),
315 /// A "work product" corresponds to a `.o` (or other) file that we
316 /// save in between runs. These ids do not have a DefId but rather
317 /// some independent path or string that persists between runs without
318 /// the need to be mapped or unmapped. (This ensures we can serialize
319 /// them even in the absence of a tcx.)
320 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
321 pub struct WorkProductId(pub String);
323 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
324 pub enum GlobalMetaDataKind {
327 DylibDependencyFormats,