2016-03-28 17:37:34 -04:00
|
|
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2017-03-23 15:13:29 -04:00
|
|
|
use hir::def_id::CrateNum;
|
2016-03-28 17:37:34 -04:00
|
|
|
use std::fmt::Debug;
|
2016-07-21 12:33:23 -04:00
|
|
|
use std::sync::Arc;
|
2016-03-28 17:37:34 -04:00
|
|
|
|
2016-05-26 06:11:16 -04:00
|
|
|
macro_rules! try_opt {
|
|
|
|
($e:expr) => (
|
|
|
|
match $e {
|
|
|
|
Some(r) => r,
|
|
|
|
None => return None,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2016-08-05 20:00:20 -04:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
2016-03-28 17:37:34 -04:00
|
|
|
pub enum DepNode<D: Clone + Debug> {
|
|
|
|
// The `D` type is "how definitions are identified".
|
|
|
|
// During compilation, it is always `DefId`, but when serializing
|
|
|
|
// it is mapped to `DefPath`.
|
|
|
|
|
|
|
|
// Represents the `Krate` as a whole (the `hir::Krate` value) (as
|
|
|
|
// distinct from the krate module). This is basically a hash of
|
|
|
|
// the entire krate, so if you read from `Krate` (e.g., by calling
|
2017-01-26 02:41:06 +02:00
|
|
|
// `tcx.hir.krate()`), we will have to assume that any change
|
2016-03-28 17:37:34 -04:00
|
|
|
// means that you need to be recompiled. This is because the
|
|
|
|
// `Krate` value gives you access to all other items. To avoid
|
2017-01-26 02:41:06 +02:00
|
|
|
// this fate, do not call `tcx.hir.krate()`; instead, prefer
|
2016-03-28 17:37:34 -04:00
|
|
|
// wrappers like `tcx.visit_all_items_in_krate()`. If there is no
|
|
|
|
// suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
|
|
|
|
// access to the krate, but you must remember to add suitable
|
|
|
|
// edges yourself for the individual items that you read.
|
|
|
|
Krate,
|
|
|
|
|
|
|
|
// Represents the HIR node with the given node-id
|
|
|
|
Hir(D),
|
|
|
|
|
2016-11-24 19:42:07 +01:00
|
|
|
// Represents the body of a function or method. The def-id is that of the
|
|
|
|
// function/method.
|
2016-11-05 20:12:59 +01:00
|
|
|
HirBody(D),
|
|
|
|
|
2016-04-22 15:47:14 -04:00
|
|
|
// Represents the metadata for a given HIR node, typically found
|
|
|
|
// in an extern crate.
|
|
|
|
MetaData(D),
|
|
|
|
|
2016-07-21 12:33:23 -04:00
|
|
|
// Represents some artifact that we save to disk. Note that these
|
|
|
|
// do not have a def-id as part of their identifier.
|
|
|
|
WorkProduct(Arc<WorkProductId>),
|
|
|
|
|
2016-03-28 17:37:34 -04:00
|
|
|
// Represents different phases in the compiler.
|
2017-04-10 00:00:08 -07:00
|
|
|
RegionMaps(D),
|
2016-03-28 17:37:34 -04:00
|
|
|
Coherence,
|
|
|
|
Resolve,
|
2017-02-19 14:46:29 +02:00
|
|
|
CoherenceCheckTrait(D),
|
2016-03-28 17:37:34 -04:00
|
|
|
CoherenceCheckImpl(D),
|
|
|
|
CoherenceOverlapCheck(D),
|
|
|
|
CoherenceOverlapCheckSpecial(D),
|
|
|
|
Variance,
|
2017-03-23 15:13:29 -04:00
|
|
|
PrivacyAccessLevels(CrateNum),
|
2016-08-08 18:42:06 -04:00
|
|
|
|
|
|
|
// Represents the MIR for a fn; also used as the task node for
|
|
|
|
// things read/modify that MIR.
|
2017-02-28 12:32:54 -05:00
|
|
|
MirKrate,
|
2016-08-08 18:42:06 -04:00
|
|
|
Mir(D),
|
2017-02-08 18:31:03 +01:00
|
|
|
MirShim(Vec<D>),
|
2016-08-08 18:42:06 -04:00
|
|
|
|
2017-02-18 07:07:02 -05:00
|
|
|
BorrowCheckKrate,
|
2016-03-28 17:37:34 -04:00
|
|
|
BorrowCheck(D),
|
|
|
|
RvalueCheck(D),
|
|
|
|
Reachability,
|
2017-04-25 15:56:02 -04:00
|
|
|
MirKeys,
|
2016-03-28 17:37:34 -04:00
|
|
|
LateLintCheck,
|
|
|
|
TransCrateItem(D),
|
|
|
|
TransInlinedItem(D),
|
|
|
|
TransWriteMetadata,
|
2017-04-24 11:15:12 -04:00
|
|
|
CrateVariances,
|
2016-03-28 17:37:34 -04:00
|
|
|
|
|
|
|
// Nodes representing bits of computed IR in the tcx. Each shared
|
|
|
|
// table in the tcx (or elsewhere) maps to one of these
|
|
|
|
// nodes. Often we map multiple tables to the same node if there
|
|
|
|
// is no point in distinguishing them (e.g., both the type and
|
2016-09-19 23:49:01 +03:00
|
|
|
// predicates for an item wind up in `ItemSignature`).
|
2016-11-10 02:06:34 +02:00
|
|
|
AssociatedItems(D),
|
2016-03-28 17:37:34 -04:00
|
|
|
ItemSignature(D),
|
2017-04-24 11:15:12 -04:00
|
|
|
ItemVarianceConstraints(D),
|
|
|
|
ItemVariances(D),
|
2017-04-14 10:51:22 -04:00
|
|
|
IsForeignItem(D),
|
2017-02-11 19:26:13 +02:00
|
|
|
TypeParamPredicates((D, D)),
|
2016-04-14 15:49:39 +03:00
|
|
|
SizedConstraint(D),
|
2017-04-23 17:43:23 +03:00
|
|
|
DtorckConstraint(D),
|
2017-03-01 18:42:26 +02:00
|
|
|
AdtDestructor(D),
|
2016-11-10 02:06:34 +02:00
|
|
|
AssociatedItemDefIds(D),
|
2016-03-28 17:37:34 -04:00
|
|
|
InherentImpls(D),
|
2017-02-28 09:44:34 -05:00
|
|
|
TypeckBodiesKrate,
|
2017-01-25 16:24:00 -05:00
|
|
|
TypeckTables(D),
|
2017-01-28 06:34:07 -05:00
|
|
|
UsedTraitImports(D),
|
2017-04-18 23:38:15 +03:00
|
|
|
ConstEval(D),
|
2017-04-24 19:35:47 +03:00
|
|
|
SymbolName(D),
|
2016-03-28 17:37:34 -04:00
|
|
|
|
|
|
|
// The set of impls for a given trait. Ultimately, it would be
|
|
|
|
// nice to get more fine-grained here (e.g., to include a
|
|
|
|
// simplified type), but we can't do that until we restructure the
|
|
|
|
// HIR to distinguish the *header* of an impl from its body. This
|
|
|
|
// is because changes to the header may change the self-type of
|
|
|
|
// the impl and hence would require us to be more conservative
|
|
|
|
// than changes in the impl body.
|
|
|
|
TraitImpls(D),
|
|
|
|
|
|
|
|
// Nodes representing caches. To properly handle a true cache, we
|
|
|
|
// don't use a DepTrackingMap, but rather we push a task node.
|
|
|
|
// Otherwise the write into the map would be incorrectly
|
|
|
|
// attributed to the first task that happened to fill the cache,
|
|
|
|
// which would yield an overly conservative dep-graph.
|
|
|
|
TraitItems(D),
|
|
|
|
ReprHints(D),
|
2016-11-04 17:31:52 +11:00
|
|
|
|
|
|
|
// Trait selection cache is a little funny. Given a trait
|
|
|
|
// reference like `Foo: SomeTrait<Bar>`, there could be
|
|
|
|
// arbitrarily many def-ids to map on in there (e.g., `Foo`,
|
|
|
|
// `SomeTrait`, `Bar`). We could have a vector of them, but it
|
|
|
|
// requires heap-allocation, and trait sel in general can be a
|
|
|
|
// surprisingly hot path. So instead we pick two def-ids: the
|
|
|
|
// trait def-id, and the first def-id in the input types. If there
|
|
|
|
// is no def-id in the input types, then we use the trait def-id
|
|
|
|
// again. So for example:
|
|
|
|
//
|
|
|
|
// - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
|
|
|
// - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
|
|
|
// - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
|
|
|
|
// - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
|
|
|
|
// - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
|
|
|
|
// - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
|
|
|
// - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
|
|
|
// - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
|
|
|
// - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
|
|
|
|
//
|
|
|
|
// You can see that we map many trait refs to the same
|
|
|
|
// trait-select node. This is not a problem, it just means
|
|
|
|
// imprecision in our dep-graph tracking. The important thing is
|
|
|
|
// that for any given trait-ref, we always map to the **same**
|
|
|
|
// trait-select node.
|
|
|
|
TraitSelect { trait_def_id: D, input_def_id: D },
|
|
|
|
|
|
|
|
// For proj. cache, we just keep a list of all def-ids, since it is
|
|
|
|
// not a hotspot.
|
|
|
|
ProjectionCache { def_ids: Vec<D> },
|
2017-04-29 09:56:01 -05:00
|
|
|
|
|
|
|
DescribeDef(D),
|
|
|
|
DefSpan(D),
|
2016-03-28 17:37:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<D: Clone + Debug> DepNode<D> {
|
|
|
|
/// Used in testing
|
|
|
|
pub fn from_label_string(label: &str, data: D) -> Result<DepNode<D>, ()> {
|
|
|
|
macro_rules! check {
|
|
|
|
($($name:ident,)*) => {
|
|
|
|
match label {
|
|
|
|
$(stringify!($name) => Ok(DepNode::$name(data)),)*
|
|
|
|
_ => Err(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-23 11:57:27 -04:00
|
|
|
if label == "Krate" {
|
|
|
|
// special case
|
|
|
|
return Ok(DepNode::Krate);
|
|
|
|
}
|
|
|
|
|
2016-03-28 17:37:34 -04:00
|
|
|
check! {
|
|
|
|
BorrowCheck,
|
2016-07-27 14:36:21 -04:00
|
|
|
Hir,
|
2016-11-05 20:12:59 +01:00
|
|
|
HirBody,
|
2016-03-28 17:37:34 -04:00
|
|
|
TransCrateItem,
|
2016-11-10 02:06:34 +02:00
|
|
|
AssociatedItems,
|
2016-03-28 17:37:34 -04:00
|
|
|
ItemSignature,
|
2017-04-14 10:51:22 -04:00
|
|
|
IsForeignItem,
|
2016-11-10 02:06:34 +02:00
|
|
|
AssociatedItemDefIds,
|
2016-03-28 17:37:34 -04:00
|
|
|
InherentImpls,
|
2017-01-25 16:24:00 -05:00
|
|
|
TypeckTables,
|
2017-01-28 06:34:07 -05:00
|
|
|
UsedTraitImports,
|
2016-03-28 17:37:34 -04:00
|
|
|
TraitImpls,
|
|
|
|
ReprHints,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
|
|
|
|
where OP: FnMut(&D) -> Option<E>, E: Clone + Debug
|
|
|
|
{
|
|
|
|
use self::DepNode::*;
|
|
|
|
|
|
|
|
match *self {
|
|
|
|
Krate => Some(Krate),
|
2017-02-18 07:07:02 -05:00
|
|
|
BorrowCheckKrate => Some(BorrowCheckKrate),
|
2017-02-28 12:32:54 -05:00
|
|
|
MirKrate => Some(MirKrate),
|
2017-02-28 09:44:34 -05:00
|
|
|
TypeckBodiesKrate => Some(TypeckBodiesKrate),
|
2016-03-28 17:37:34 -04:00
|
|
|
Coherence => Some(Coherence),
|
2017-04-24 11:15:12 -04:00
|
|
|
CrateVariances => Some(CrateVariances),
|
2016-03-28 17:37:34 -04:00
|
|
|
Resolve => Some(Resolve),
|
|
|
|
Variance => Some(Variance),
|
2017-03-23 15:13:29 -04:00
|
|
|
PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
|
2016-03-28 17:37:34 -04:00
|
|
|
Reachability => Some(Reachability),
|
2017-04-25 15:56:02 -04:00
|
|
|
MirKeys => Some(MirKeys),
|
2016-03-28 17:37:34 -04:00
|
|
|
LateLintCheck => Some(LateLintCheck),
|
|
|
|
TransWriteMetadata => Some(TransWriteMetadata),
|
2016-07-21 12:33:23 -04:00
|
|
|
|
|
|
|
// work product names do not need to be mapped, because
|
|
|
|
// they are always absolute.
|
|
|
|
WorkProduct(ref id) => Some(WorkProduct(id.clone())),
|
|
|
|
|
2016-03-28 17:37:34 -04:00
|
|
|
Hir(ref d) => op(d).map(Hir),
|
2016-11-05 20:12:59 +01:00
|
|
|
HirBody(ref d) => op(d).map(HirBody),
|
2016-04-22 15:47:14 -04:00
|
|
|
MetaData(ref d) => op(d).map(MetaData),
|
2017-02-19 14:46:29 +02:00
|
|
|
CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait),
|
2016-03-28 17:37:34 -04:00
|
|
|
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
|
|
|
|
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
|
|
|
|
CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
|
2016-08-08 18:42:06 -04:00
|
|
|
Mir(ref d) => op(d).map(Mir),
|
2017-02-08 18:31:03 +01:00
|
|
|
MirShim(ref def_ids) => {
|
|
|
|
let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
|
|
|
|
def_ids.map(MirShim)
|
|
|
|
}
|
2016-03-28 17:37:34 -04:00
|
|
|
BorrowCheck(ref d) => op(d).map(BorrowCheck),
|
2017-04-10 00:00:08 -07:00
|
|
|
RegionMaps(ref d) => op(d).map(RegionMaps),
|
2016-03-28 17:37:34 -04:00
|
|
|
RvalueCheck(ref d) => op(d).map(RvalueCheck),
|
|
|
|
TransCrateItem(ref d) => op(d).map(TransCrateItem),
|
|
|
|
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
|
2016-11-10 02:06:34 +02:00
|
|
|
AssociatedItems(ref d) => op(d).map(AssociatedItems),
|
2016-03-28 17:37:34 -04:00
|
|
|
ItemSignature(ref d) => op(d).map(ItemSignature),
|
2017-04-24 11:15:12 -04:00
|
|
|
ItemVariances(ref d) => op(d).map(ItemVariances),
|
|
|
|
ItemVarianceConstraints(ref d) => op(d).map(ItemVarianceConstraints),
|
2017-04-14 10:51:22 -04:00
|
|
|
IsForeignItem(ref d) => op(d).map(IsForeignItem),
|
2017-02-11 19:26:13 +02:00
|
|
|
TypeParamPredicates((ref item, ref param)) => {
|
|
|
|
Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
|
|
|
|
}
|
2016-04-14 15:49:39 +03:00
|
|
|
SizedConstraint(ref d) => op(d).map(SizedConstraint),
|
2017-04-23 17:43:23 +03:00
|
|
|
DtorckConstraint(ref d) => op(d).map(DtorckConstraint),
|
2017-03-01 18:42:26 +02:00
|
|
|
AdtDestructor(ref d) => op(d).map(AdtDestructor),
|
2016-11-10 02:06:34 +02:00
|
|
|
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
|
2016-03-28 17:37:34 -04:00
|
|
|
InherentImpls(ref d) => op(d).map(InherentImpls),
|
2017-01-25 16:24:00 -05:00
|
|
|
TypeckTables(ref d) => op(d).map(TypeckTables),
|
2017-01-28 06:34:07 -05:00
|
|
|
UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
|
2017-04-18 23:38:15 +03:00
|
|
|
ConstEval(ref d) => op(d).map(ConstEval),
|
2017-04-24 19:35:47 +03:00
|
|
|
SymbolName(ref d) => op(d).map(SymbolName),
|
2016-03-28 17:37:34 -04:00
|
|
|
TraitImpls(ref d) => op(d).map(TraitImpls),
|
|
|
|
TraitItems(ref d) => op(d).map(TraitItems),
|
|
|
|
ReprHints(ref d) => op(d).map(ReprHints),
|
2016-11-04 17:31:52 +11:00
|
|
|
TraitSelect { ref trait_def_id, ref input_def_id } => {
|
|
|
|
op(trait_def_id).and_then(|trait_def_id| {
|
|
|
|
op(input_def_id).and_then(|input_def_id| {
|
|
|
|
Some(TraitSelect { trait_def_id: trait_def_id,
|
|
|
|
input_def_id: input_def_id })
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
ProjectionCache { ref def_ids } => {
|
|
|
|
let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
|
|
|
|
def_ids.map(|d| ProjectionCache { def_ids: d })
|
2016-05-26 06:11:16 -04:00
|
|
|
}
|
2017-04-29 11:04:55 -05:00
|
|
|
DescribeDef(ref d) => op(d).map(DescribeDef),
|
|
|
|
DefSpan(ref d) => op(d).map(DefSpan),
|
2016-03-28 17:37:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-21 12:33:23 -04:00
|
|
|
|
|
|
|
/// A "work product" corresponds to a `.o` (or other) file that we
|
|
|
|
/// save in between runs. These ids do not have a DefId but rather
|
|
|
|
/// some independent path or string that persists between runs without
|
|
|
|
/// the need to be mapped or unmapped. (This ensures we can serialize
|
|
|
|
/// them even in the absence of a tcx.)
|
2016-08-05 20:00:20 -04:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
2016-07-25 10:51:14 -04:00
|
|
|
pub struct WorkProductId(pub String);
|