break dep-graph into modules, parameterize DepNode
it is useful later to customize how change the type we use for reference items away from DefId
This commit is contained in:
parent
b1e68b9e2d
commit
a9b6205aff
15 changed files with 411 additions and 243 deletions
207
src/librustc/dep_graph/dep_node.rs
Normal file
207
src/librustc/dep_graph/dep_node.rs
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
|
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
|
||||||
|
// `tcx.map.krate()`), we will have to assume that any change
|
||||||
|
// means that you need to be recompiled. This is because the
|
||||||
|
// `Krate` value gives you access to all other items. To avoid
|
||||||
|
// this fate, do not call `tcx.map.krate()`; instead, prefer
|
||||||
|
// 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),
|
||||||
|
|
||||||
|
// Represents different phases in the compiler.
|
||||||
|
CrateReader,
|
||||||
|
CollectLanguageItems,
|
||||||
|
CheckStaticRecursion,
|
||||||
|
ResolveLifetimes,
|
||||||
|
RegionResolveCrate,
|
||||||
|
CheckLoops,
|
||||||
|
PluginRegistrar,
|
||||||
|
StabilityIndex,
|
||||||
|
CollectItem(D),
|
||||||
|
Coherence,
|
||||||
|
EffectCheck,
|
||||||
|
Liveness,
|
||||||
|
Resolve,
|
||||||
|
EntryPoint,
|
||||||
|
CheckEntryFn,
|
||||||
|
CoherenceCheckImpl(D),
|
||||||
|
CoherenceOverlapCheck(D),
|
||||||
|
CoherenceOverlapCheckSpecial(D),
|
||||||
|
CoherenceOverlapInherentCheck(D),
|
||||||
|
CoherenceOrphanCheck(D),
|
||||||
|
Variance,
|
||||||
|
WfCheck(D),
|
||||||
|
TypeckItemType(D),
|
||||||
|
TypeckItemBody(D),
|
||||||
|
Dropck,
|
||||||
|
DropckImpl(D),
|
||||||
|
CheckConst(D),
|
||||||
|
Privacy,
|
||||||
|
IntrinsicCheck(D),
|
||||||
|
MatchCheck(D),
|
||||||
|
MirMapConstruction(D),
|
||||||
|
MirTypeck(D),
|
||||||
|
BorrowCheck(D),
|
||||||
|
RvalueCheck(D),
|
||||||
|
Reachability,
|
||||||
|
DeadCheck,
|
||||||
|
StabilityCheck,
|
||||||
|
LateLintCheck,
|
||||||
|
IntrinsicUseCheck,
|
||||||
|
TransCrate,
|
||||||
|
TransCrateItem(D),
|
||||||
|
TransInlinedItem(D),
|
||||||
|
TransWriteMetadata,
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// predicates for an item wind up in `ItemSignature`). Other
|
||||||
|
// times, such as `ImplItems` vs `TraitItemDefIds`, tables which
|
||||||
|
// might be mergable are kept distinct because the sets of def-ids
|
||||||
|
// to which they apply are disjoint, and hence we might as well
|
||||||
|
// have distinct labels for easier debugging.
|
||||||
|
ImplOrTraitItems(D),
|
||||||
|
ItemSignature(D),
|
||||||
|
FieldTy(D),
|
||||||
|
TraitItemDefIds(D),
|
||||||
|
InherentImpls(D),
|
||||||
|
ImplItems(D),
|
||||||
|
|
||||||
|
// 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),
|
||||||
|
TraitSelect(D),
|
||||||
|
}
|
||||||
|
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check! {
|
||||||
|
CollectItem,
|
||||||
|
BorrowCheck,
|
||||||
|
TransCrateItem,
|
||||||
|
TypeckItemType,
|
||||||
|
TypeckItemBody,
|
||||||
|
ImplOrTraitItems,
|
||||||
|
ItemSignature,
|
||||||
|
FieldTy,
|
||||||
|
TraitItemDefIds,
|
||||||
|
InherentImpls,
|
||||||
|
ImplItems,
|
||||||
|
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),
|
||||||
|
CrateReader => Some(CrateReader),
|
||||||
|
CollectLanguageItems => Some(CollectLanguageItems),
|
||||||
|
CheckStaticRecursion => Some(CheckStaticRecursion),
|
||||||
|
ResolveLifetimes => Some(ResolveLifetimes),
|
||||||
|
RegionResolveCrate => Some(RegionResolveCrate),
|
||||||
|
CheckLoops => Some(CheckLoops),
|
||||||
|
PluginRegistrar => Some(PluginRegistrar),
|
||||||
|
StabilityIndex => Some(StabilityIndex),
|
||||||
|
Coherence => Some(Coherence),
|
||||||
|
EffectCheck => Some(EffectCheck),
|
||||||
|
Liveness => Some(Liveness),
|
||||||
|
Resolve => Some(Resolve),
|
||||||
|
EntryPoint => Some(EntryPoint),
|
||||||
|
CheckEntryFn => Some(CheckEntryFn),
|
||||||
|
Variance => Some(Variance),
|
||||||
|
Dropck => Some(Dropck),
|
||||||
|
Privacy => Some(Privacy),
|
||||||
|
Reachability => Some(Reachability),
|
||||||
|
DeadCheck => Some(DeadCheck),
|
||||||
|
StabilityCheck => Some(StabilityCheck),
|
||||||
|
LateLintCheck => Some(LateLintCheck),
|
||||||
|
IntrinsicUseCheck => Some(IntrinsicUseCheck),
|
||||||
|
TransCrate => Some(TransCrate),
|
||||||
|
TransWriteMetadata => Some(TransWriteMetadata),
|
||||||
|
Hir(ref d) => op(d).map(Hir),
|
||||||
|
CollectItem(ref d) => op(d).map(CollectItem),
|
||||||
|
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
|
||||||
|
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
|
||||||
|
CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
|
||||||
|
CoherenceOverlapInherentCheck(ref d) => op(d).map(CoherenceOverlapInherentCheck),
|
||||||
|
CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
|
||||||
|
WfCheck(ref d) => op(d).map(WfCheck),
|
||||||
|
TypeckItemType(ref d) => op(d).map(TypeckItemType),
|
||||||
|
TypeckItemBody(ref d) => op(d).map(TypeckItemBody),
|
||||||
|
DropckImpl(ref d) => op(d).map(DropckImpl),
|
||||||
|
CheckConst(ref d) => op(d).map(CheckConst),
|
||||||
|
IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
|
||||||
|
MatchCheck(ref d) => op(d).map(MatchCheck),
|
||||||
|
MirMapConstruction(ref d) => op(d).map(MirMapConstruction),
|
||||||
|
MirTypeck(ref d) => op(d).map(MirTypeck),
|
||||||
|
BorrowCheck(ref d) => op(d).map(BorrowCheck),
|
||||||
|
RvalueCheck(ref d) => op(d).map(RvalueCheck),
|
||||||
|
TransCrateItem(ref d) => op(d).map(TransCrateItem),
|
||||||
|
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
|
||||||
|
ImplOrTraitItems(ref d) => op(d).map(ImplOrTraitItems),
|
||||||
|
ItemSignature(ref d) => op(d).map(ItemSignature),
|
||||||
|
FieldTy(ref d) => op(d).map(FieldTy),
|
||||||
|
TraitItemDefIds(ref d) => op(d).map(TraitItemDefIds),
|
||||||
|
InherentImpls(ref d) => op(d).map(InherentImpls),
|
||||||
|
ImplItems(ref d) => op(d).map(ImplItems),
|
||||||
|
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||||
|
TraitItems(ref d) => op(d).map(TraitItems),
|
||||||
|
ReprHints(ref d) => op(d).map(ReprHints),
|
||||||
|
TraitSelect(ref d) => op(d).map(TraitSelect),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use hir::def_id::DefId;
|
||||||
use rustc_data_structures::fnv::FnvHashMap;
|
use rustc_data_structures::fnv::FnvHashMap;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
@ -29,7 +30,7 @@ pub struct DepTrackingMap<M: DepTrackingMapConfig> {
|
||||||
pub trait DepTrackingMapConfig {
|
pub trait DepTrackingMapConfig {
|
||||||
type Key: Eq + Hash + Clone;
|
type Key: Eq + Hash + Clone;
|
||||||
type Value: Clone;
|
type Value: Clone;
|
||||||
fn to_dep_node(key: &Self::Key) -> DepNode;
|
fn to_dep_node(key: &Self::Key) -> DepNode<DefId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
|
impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use rustc_data_structures::fnv::{FnvHashMap, FnvHashSet};
|
use rustc_data_structures::fnv::{FnvHashMap, FnvHashSet};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::hash::Hash;
|
||||||
use super::{DepGraphQuery, DepNode};
|
use super::{DepGraphQuery, DepNode};
|
||||||
|
|
||||||
pub struct DepGraphEdges {
|
pub struct DepGraphEdges<D: Clone + Debug + Eq + Hash> {
|
||||||
nodes: Vec<DepNode>,
|
nodes: Vec<DepNode<D>>,
|
||||||
indices: FnvHashMap<DepNode, IdIndex>,
|
indices: FnvHashMap<DepNode<D>, IdIndex>,
|
||||||
edges: FnvHashSet<(IdIndex, IdIndex)>,
|
edges: FnvHashSet<(IdIndex, IdIndex)>,
|
||||||
open_nodes: Vec<OpenNode>,
|
open_nodes: Vec<OpenNode>,
|
||||||
}
|
}
|
||||||
|
@ -40,8 +42,8 @@ enum OpenNode {
|
||||||
Ignore,
|
Ignore,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DepGraphEdges {
|
impl<D: Clone + Debug + Eq + Hash> DepGraphEdges<D> {
|
||||||
pub fn new() -> DepGraphEdges {
|
pub fn new() -> DepGraphEdges<D> {
|
||||||
DepGraphEdges {
|
DepGraphEdges {
|
||||||
nodes: vec![],
|
nodes: vec![],
|
||||||
indices: FnvHashMap(),
|
indices: FnvHashMap(),
|
||||||
|
@ -50,12 +52,12 @@ impl DepGraphEdges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id(&self, index: IdIndex) -> DepNode {
|
fn id(&self, index: IdIndex) -> DepNode<D> {
|
||||||
self.nodes[index.index()]
|
self.nodes[index.index()].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a node for `id` in the graph.
|
/// Creates a node for `id` in the graph.
|
||||||
fn make_node(&mut self, id: DepNode) -> IdIndex {
|
fn make_node(&mut self, id: DepNode<D>) -> IdIndex {
|
||||||
if let Some(&i) = self.indices.get(&id) {
|
if let Some(&i) = self.indices.get(&id) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +82,7 @@ impl DepGraphEdges {
|
||||||
assert_eq!(popped_node, OpenNode::Ignore);
|
assert_eq!(popped_node, OpenNode::Ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_task(&mut self, key: DepNode) {
|
pub fn push_task(&mut self, key: DepNode<D>) {
|
||||||
let top_node = self.current_node();
|
let top_node = self.current_node();
|
||||||
|
|
||||||
let new_node = self.make_node(key);
|
let new_node = self.make_node(key);
|
||||||
|
@ -93,7 +95,7 @@ impl DepGraphEdges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_task(&mut self, key: DepNode) {
|
pub fn pop_task(&mut self, key: DepNode<D>) {
|
||||||
let popped_node = self.open_nodes.pop().unwrap();
|
let popped_node = self.open_nodes.pop().unwrap();
|
||||||
assert_eq!(OpenNode::Node(self.indices[&key]), popped_node);
|
assert_eq!(OpenNode::Node(self.indices[&key]), popped_node);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +103,7 @@ impl DepGraphEdges {
|
||||||
/// Indicates that the current task `C` reads `v` by adding an
|
/// Indicates that the current task `C` reads `v` by adding an
|
||||||
/// edge from `v` to `C`. If there is no current task, panics. If
|
/// edge from `v` to `C`. If there is no current task, panics. If
|
||||||
/// you want to suppress this edge, use `ignore`.
|
/// you want to suppress this edge, use `ignore`.
|
||||||
pub fn read(&mut self, v: DepNode) {
|
pub fn read(&mut self, v: DepNode<D>) {
|
||||||
let source = self.make_node(v);
|
let source = self.make_node(v);
|
||||||
self.add_edge_from_current_node(|current| (source, current))
|
self.add_edge_from_current_node(|current| (source, current))
|
||||||
}
|
}
|
||||||
|
@ -109,7 +111,7 @@ impl DepGraphEdges {
|
||||||
/// Indicates that the current task `C` writes `v` by adding an
|
/// Indicates that the current task `C` writes `v` by adding an
|
||||||
/// edge from `C` to `v`. If there is no current task, panics. If
|
/// edge from `C` to `v`. If there is no current task, panics. If
|
||||||
/// you want to suppress this edge, use `ignore`.
|
/// you want to suppress this edge, use `ignore`.
|
||||||
pub fn write(&mut self, v: DepNode) {
|
pub fn write(&mut self, v: DepNode<D>) {
|
||||||
let target = self.make_node(v);
|
let target = self.make_node(v);
|
||||||
self.add_edge_from_current_node(|current| (current, target))
|
self.add_edge_from_current_node(|current| (current, target))
|
||||||
}
|
}
|
||||||
|
@ -153,7 +155,7 @@ impl DepGraphEdges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query(&self) -> DepGraphQuery {
|
pub fn query(&self) -> DepGraphQuery<D> {
|
||||||
let edges: Vec<_> = self.edges.iter()
|
let edges: Vec<_> = self.edges.iter()
|
||||||
.map(|&(i, j)| (self.id(i), self.id(j)))
|
.map(|&(i, j)| (self.id(i), self.id(j)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
71
src/librustc/dep_graph/graph.rs
Normal file
71
src/librustc/dep_graph/graph.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
use hir::def_id::DefId;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use super::dep_node::DepNode;
|
||||||
|
use super::query::DepGraphQuery;
|
||||||
|
use super::raii;
|
||||||
|
use super::thread::{DepGraphThreadData, DepMessage};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DepGraph {
|
||||||
|
data: Rc<DepGraphThreadData>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DepGraph {
|
||||||
|
pub fn new(enabled: bool) -> DepGraph {
|
||||||
|
DepGraph {
|
||||||
|
data: Rc::new(DepGraphThreadData::new(enabled))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// True if we are actually building a dep-graph. If this returns false,
|
||||||
|
/// then the other methods on this `DepGraph` will have no net effect.
|
||||||
|
#[inline]
|
||||||
|
pub fn enabled(&self) -> bool {
|
||||||
|
self.data.enabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn query(&self) -> DepGraphQuery<DefId> {
|
||||||
|
self.data.query()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn in_ignore<'graph>(&'graph self) -> raii::IgnoreTask<'graph> {
|
||||||
|
raii::IgnoreTask::new(&self.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn in_task<'graph>(&'graph self, key: DepNode<DefId>) -> raii::DepTask<'graph> {
|
||||||
|
raii::DepTask::new(&self.data, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_ignore<OP,R>(&self, op: OP) -> R
|
||||||
|
where OP: FnOnce() -> R
|
||||||
|
{
|
||||||
|
let _task = self.in_ignore();
|
||||||
|
op()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_task<OP,R>(&self, key: DepNode<DefId>, op: OP) -> R
|
||||||
|
where OP: FnOnce() -> R
|
||||||
|
{
|
||||||
|
let _task = self.in_task(key);
|
||||||
|
op()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&self, v: DepNode<DefId>) {
|
||||||
|
self.data.enqueue(DepMessage::Read(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self, v: DepNode<DefId>) {
|
||||||
|
self.data.enqueue(DepMessage::Write(v));
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,211 +8,17 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use self::thread::{DepGraphThreadData, DepMessage};
|
mod dep_node;
|
||||||
use hir::def_id::DefId;
|
|
||||||
use syntax::ast::NodeId;
|
|
||||||
use ty::TyCtxt;
|
|
||||||
use hir;
|
|
||||||
use hir::intravisit::Visitor;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
mod dep_tracking_map;
|
mod dep_tracking_map;
|
||||||
mod edges;
|
mod edges;
|
||||||
|
mod graph;
|
||||||
mod query;
|
mod query;
|
||||||
mod raii;
|
mod raii;
|
||||||
mod thread;
|
mod thread;
|
||||||
|
mod visit;
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
pub enum DepNode {
|
|
||||||
// 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
|
|
||||||
// `tcx.map.krate()`), we will have to assume that any change
|
|
||||||
// means that you need to be recompiled. This is because the
|
|
||||||
// `Krate` value gives you access to all other items. To avoid
|
|
||||||
// this fate, do not call `tcx.map.krate()`; instead, prefer
|
|
||||||
// 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(DefId),
|
|
||||||
|
|
||||||
// Represents different phases in the compiler.
|
|
||||||
CrateReader,
|
|
||||||
CollectLanguageItems,
|
|
||||||
CheckStaticRecursion,
|
|
||||||
ResolveLifetimes,
|
|
||||||
RegionResolveCrate,
|
|
||||||
CheckLoops,
|
|
||||||
PluginRegistrar,
|
|
||||||
StabilityIndex,
|
|
||||||
CollectItem(DefId),
|
|
||||||
Coherence,
|
|
||||||
EffectCheck,
|
|
||||||
Liveness,
|
|
||||||
Resolve,
|
|
||||||
EntryPoint,
|
|
||||||
CheckEntryFn,
|
|
||||||
CoherenceCheckImpl(DefId),
|
|
||||||
CoherenceOverlapCheck(DefId),
|
|
||||||
CoherenceOverlapCheckSpecial(DefId),
|
|
||||||
CoherenceOverlapInherentCheck(DefId),
|
|
||||||
CoherenceOrphanCheck(DefId),
|
|
||||||
Variance,
|
|
||||||
WfCheck(DefId),
|
|
||||||
TypeckItemType(DefId),
|
|
||||||
TypeckItemBody(DefId),
|
|
||||||
Dropck,
|
|
||||||
DropckImpl(DefId),
|
|
||||||
CheckConst(DefId),
|
|
||||||
Privacy,
|
|
||||||
IntrinsicCheck(DefId),
|
|
||||||
MatchCheck(DefId),
|
|
||||||
MirMapConstruction(DefId),
|
|
||||||
MirTypeck(NodeId),
|
|
||||||
BorrowCheck(DefId),
|
|
||||||
RvalueCheck(DefId),
|
|
||||||
Reachability,
|
|
||||||
DeadCheck,
|
|
||||||
StabilityCheck,
|
|
||||||
LateLintCheck,
|
|
||||||
IntrinsicUseCheck,
|
|
||||||
TransCrate,
|
|
||||||
TransCrateItem(DefId),
|
|
||||||
TransInlinedItem(DefId),
|
|
||||||
TransWriteMetadata,
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// predicates for an item wind up in `ItemSignature`). Other
|
|
||||||
// times, such as `ImplItems` vs `TraitItemDefIds`, tables which
|
|
||||||
// might be mergable are kept distinct because the sets of def-ids
|
|
||||||
// to which they apply are disjoint, and hence we might as well
|
|
||||||
// have distinct labels for easier debugging.
|
|
||||||
ImplOrTraitItems(DefId),
|
|
||||||
ItemSignature(DefId),
|
|
||||||
FieldTy(DefId),
|
|
||||||
TraitItemDefIds(DefId),
|
|
||||||
InherentImpls(DefId),
|
|
||||||
ImplItems(DefId),
|
|
||||||
|
|
||||||
// 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(DefId),
|
|
||||||
|
|
||||||
// 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(DefId),
|
|
||||||
ReprHints(DefId),
|
|
||||||
TraitSelect(DefId),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct DepGraph {
|
|
||||||
data: Rc<DepGraphThreadData>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DepGraph {
|
|
||||||
pub fn new(enabled: bool) -> DepGraph {
|
|
||||||
DepGraph {
|
|
||||||
data: Rc::new(DepGraphThreadData::new(enabled))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// True if we are actually building a dep-graph. If this returns false,
|
|
||||||
/// then the other methods on this `DepGraph` will have no net effect.
|
|
||||||
#[inline]
|
|
||||||
pub fn enabled(&self) -> bool {
|
|
||||||
self.data.enabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn query(&self) -> DepGraphQuery {
|
|
||||||
self.data.query()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn in_ignore<'graph>(&'graph self) -> raii::IgnoreTask<'graph> {
|
|
||||||
raii::IgnoreTask::new(&self.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn in_task<'graph>(&'graph self, key: DepNode) -> raii::DepTask<'graph> {
|
|
||||||
raii::DepTask::new(&self.data, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_ignore<OP,R>(&self, op: OP) -> R
|
|
||||||
where OP: FnOnce() -> R
|
|
||||||
{
|
|
||||||
let _task = self.in_ignore();
|
|
||||||
op()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_task<OP,R>(&self, key: DepNode, op: OP) -> R
|
|
||||||
where OP: FnOnce() -> R
|
|
||||||
{
|
|
||||||
let _task = self.in_task(key);
|
|
||||||
op()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(&self, v: DepNode) {
|
|
||||||
self.data.enqueue(DepMessage::Read(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(&self, v: DepNode) {
|
|
||||||
self.data.enqueue(DepMessage::Write(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
|
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
|
||||||
|
pub use self::dep_node::DepNode;
|
||||||
|
pub use self::graph::DepGraph;
|
||||||
pub use self::query::DepGraphQuery;
|
pub use self::query::DepGraphQuery;
|
||||||
|
pub use self::visit::visit_all_items_in_krate;
|
||||||
/// Visit all the items in the krate in some order. When visiting a
|
|
||||||
/// particular item, first create a dep-node by calling `dep_node_fn`
|
|
||||||
/// and push that onto the dep-graph stack of tasks, and also create a
|
|
||||||
/// read edge from the corresponding AST node. This is used in
|
|
||||||
/// compiler passes to automatically record the item that they are
|
|
||||||
/// working on.
|
|
||||||
pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &TyCtxt<'tcx>,
|
|
||||||
mut dep_node_fn: F,
|
|
||||||
visitor: &mut V)
|
|
||||||
where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
|
|
||||||
{
|
|
||||||
struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> {
|
|
||||||
tcx: &'visit TyCtxt<'tcx>,
|
|
||||||
dep_node_fn: &'visit mut F,
|
|
||||||
visitor: &'visit mut V
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'visit, 'tcx, F, V> Visitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
|
|
||||||
where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
|
|
||||||
{
|
|
||||||
fn visit_item(&mut self, i: &'tcx hir::Item) {
|
|
||||||
let item_def_id = self.tcx.map.local_def_id(i.id);
|
|
||||||
let task_id = (self.dep_node_fn)(item_def_id);
|
|
||||||
let _task = self.tcx.dep_graph.in_task(task_id);
|
|
||||||
debug!("Started task {:?}", task_id);
|
|
||||||
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
|
|
||||||
self.visitor.visit_item(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let krate = tcx.dep_graph.with_ignore(|| tcx.map.krate());
|
|
||||||
let mut tracking_visitor = TrackingVisitor {
|
|
||||||
tcx: tcx,
|
|
||||||
dep_node_fn: &mut dep_node_fn,
|
|
||||||
visitor: visitor
|
|
||||||
};
|
|
||||||
krate.visit_all_items(&mut tracking_visitor)
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,16 +10,20 @@
|
||||||
|
|
||||||
use rustc_data_structures::fnv::FnvHashMap;
|
use rustc_data_structures::fnv::FnvHashMap;
|
||||||
use rustc_data_structures::graph::{Graph, NodeIndex};
|
use rustc_data_structures::graph::{Graph, NodeIndex};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
use super::DepNode;
|
use super::DepNode;
|
||||||
|
|
||||||
pub struct DepGraphQuery {
|
pub struct DepGraphQuery<D: Clone + Debug + Hash + Eq> {
|
||||||
pub graph: Graph<DepNode, ()>,
|
pub graph: Graph<DepNode<D>, ()>,
|
||||||
pub indices: FnvHashMap<DepNode, NodeIndex>,
|
pub indices: FnvHashMap<DepNode<D>, NodeIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DepGraphQuery {
|
impl<D: Clone + Debug + Hash + Eq> DepGraphQuery<D> {
|
||||||
pub fn new(nodes: &[DepNode], edges: &[(DepNode, DepNode)]) -> DepGraphQuery {
|
pub fn new(nodes: &[DepNode<D>],
|
||||||
|
edges: &[(DepNode<D>, DepNode<D>)])
|
||||||
|
-> DepGraphQuery<D> {
|
||||||
let mut graph = Graph::new();
|
let mut graph = Graph::new();
|
||||||
let mut indices = FnvHashMap();
|
let mut indices = FnvHashMap();
|
||||||
for node in nodes {
|
for node in nodes {
|
||||||
|
@ -39,27 +43,43 @@ impl DepGraphQuery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nodes(&self) -> Vec<DepNode> {
|
pub fn contains_node(&self, node: &DepNode<D>) -> bool {
|
||||||
|
self.indices.contains_key(&node)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nodes(&self) -> Vec<DepNode<D>> {
|
||||||
self.graph.all_nodes()
|
self.graph.all_nodes()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|n| n.data.clone())
|
.map(|n| n.data.clone())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edges(&self) -> Vec<(DepNode,DepNode)> {
|
pub fn edges(&self) -> Vec<(DepNode<D>,DepNode<D>)> {
|
||||||
self.graph.all_edges()
|
self.graph.all_edges()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|edge| (edge.source(), edge.target()))
|
.map(|edge| (edge.source(), edge.target()))
|
||||||
.map(|(s, t)| (self.graph.node_data(s).clone(), self.graph.node_data(t).clone()))
|
.map(|(s, t)| (self.graph.node_data(s).clone(),
|
||||||
|
self.graph.node_data(t).clone()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All nodes reachable from `node`. In other words, things that
|
/// All nodes reachable from `node`. In other words, things that
|
||||||
/// will have to be recomputed if `node` changes.
|
/// will have to be recomputed if `node` changes.
|
||||||
pub fn dependents(&self, node: DepNode) -> Vec<DepNode> {
|
pub fn transitive_dependents(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
|
||||||
if let Some(&index) = self.indices.get(&node) {
|
if let Some(&index) = self.indices.get(&node) {
|
||||||
self.graph.depth_traverse(index)
|
self.graph.depth_traverse(index)
|
||||||
.map(|dependent_node| self.graph.node_data(dependent_node).clone())
|
.map(|s| self.graph.node_data(s).clone())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Just the outgoing edges from `node`.
|
||||||
|
pub fn immediate_dependents(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
|
||||||
|
if let Some(&index) = self.indices.get(&node) {
|
||||||
|
self.graph.successor_nodes(index)
|
||||||
|
.map(|s| self.graph.node_data(s).clone())
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
|
|
|
@ -8,16 +8,18 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use hir::def_id::DefId;
|
||||||
use super::DepNode;
|
use super::DepNode;
|
||||||
use super::thread::{DepGraphThreadData, DepMessage};
|
use super::thread::{DepGraphThreadData, DepMessage};
|
||||||
|
|
||||||
pub struct DepTask<'graph> {
|
pub struct DepTask<'graph> {
|
||||||
data: &'graph DepGraphThreadData,
|
data: &'graph DepGraphThreadData,
|
||||||
key: DepNode,
|
key: DepNode<DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'graph> DepTask<'graph> {
|
impl<'graph> DepTask<'graph> {
|
||||||
pub fn new(data: &'graph DepGraphThreadData, key: DepNode) -> DepTask<'graph> {
|
pub fn new(data: &'graph DepGraphThreadData, key: DepNode<DefId>)
|
||||||
|
-> DepTask<'graph> {
|
||||||
data.enqueue(DepMessage::PushTask(key));
|
data.enqueue(DepMessage::PushTask(key));
|
||||||
DepTask { data: data, key: key }
|
DepTask { data: data, key: key }
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
//! to accumulate more messages. This way we only ever have two vectors
|
//! to accumulate more messages. This way we only ever have two vectors
|
||||||
//! allocated (and both have a fairly large capacity).
|
//! allocated (and both have a fairly large capacity).
|
||||||
|
|
||||||
|
use hir::def_id::DefId;
|
||||||
use rustc_data_structures::veccell::VecCell;
|
use rustc_data_structures::veccell::VecCell;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::sync::mpsc::{self, Sender, Receiver};
|
use std::sync::mpsc::{self, Sender, Receiver};
|
||||||
|
@ -28,10 +29,10 @@ use super::DepNode;
|
||||||
use super::edges::DepGraphEdges;
|
use super::edges::DepGraphEdges;
|
||||||
|
|
||||||
pub enum DepMessage {
|
pub enum DepMessage {
|
||||||
Read(DepNode),
|
Read(DepNode<DefId>),
|
||||||
Write(DepNode),
|
Write(DepNode<DefId>),
|
||||||
PushTask(DepNode),
|
PushTask(DepNode<DefId>),
|
||||||
PopTask(DepNode),
|
PopTask(DepNode<DefId>),
|
||||||
PushIgnore,
|
PushIgnore,
|
||||||
PopIgnore,
|
PopIgnore,
|
||||||
Query,
|
Query,
|
||||||
|
@ -57,7 +58,7 @@ pub struct DepGraphThreadData {
|
||||||
swap_out: Sender<Vec<DepMessage>>,
|
swap_out: Sender<Vec<DepMessage>>,
|
||||||
|
|
||||||
// where to receive query results
|
// where to receive query results
|
||||||
query_in: Receiver<DepGraphQuery>,
|
query_in: Receiver<DepGraphQuery<DefId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const INITIAL_CAPACITY: usize = 2048;
|
const INITIAL_CAPACITY: usize = 2048;
|
||||||
|
@ -105,7 +106,7 @@ impl DepGraphThreadData {
|
||||||
self.swap_out.send(old_messages).unwrap();
|
self.swap_out.send(old_messages).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query(&self) -> DepGraphQuery {
|
pub fn query(&self) -> DepGraphQuery<DefId> {
|
||||||
assert!(self.enabled, "cannot query if dep graph construction not enabled");
|
assert!(self.enabled, "cannot query if dep graph construction not enabled");
|
||||||
self.enqueue(DepMessage::Query);
|
self.enqueue(DepMessage::Query);
|
||||||
self.swap();
|
self.swap();
|
||||||
|
@ -155,7 +156,7 @@ impl DepGraphThreadData {
|
||||||
/// Definition of the depgraph thread.
|
/// Definition of the depgraph thread.
|
||||||
pub fn main(swap_in: Receiver<Vec<DepMessage>>,
|
pub fn main(swap_in: Receiver<Vec<DepMessage>>,
|
||||||
swap_out: Sender<Vec<DepMessage>>,
|
swap_out: Sender<Vec<DepMessage>>,
|
||||||
query_out: Sender<DepGraphQuery>) {
|
query_out: Sender<DepGraphQuery<DefId>>) {
|
||||||
let mut edges = DepGraphEdges::new();
|
let mut edges = DepGraphEdges::new();
|
||||||
|
|
||||||
// the compiler thread always expects a fresh buffer to be
|
// the compiler thread always expects a fresh buffer to be
|
||||||
|
|
56
src/librustc/dep_graph/visit.rs
Normal file
56
src/librustc/dep_graph/visit.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
use hir::def_id::DefId;
|
||||||
|
use ty::TyCtxt;
|
||||||
|
use rustc_front::hir;
|
||||||
|
use rustc_front::intravisit::Visitor;
|
||||||
|
|
||||||
|
use super::dep_node::DepNode;
|
||||||
|
|
||||||
|
|
||||||
|
/// Visit all the items in the krate in some order. When visiting a
|
||||||
|
/// particular item, first create a dep-node by calling `dep_node_fn`
|
||||||
|
/// and push that onto the dep-graph stack of tasks, and also create a
|
||||||
|
/// read edge from the corresponding AST node. This is used in
|
||||||
|
/// compiler passes to automatically record the item that they are
|
||||||
|
/// working on.
|
||||||
|
pub fn visit_all_items_in_krate<'tcx,V,F>(tcx: &TyCtxt<'tcx>,
|
||||||
|
mut dep_node_fn: F,
|
||||||
|
visitor: &mut V)
|
||||||
|
where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
|
||||||
|
{
|
||||||
|
struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> {
|
||||||
|
tcx: &'visit TyCtxt<'tcx>,
|
||||||
|
dep_node_fn: &'visit mut F,
|
||||||
|
visitor: &'visit mut V
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'visit, 'tcx, F, V> Visitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
|
||||||
|
where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
|
||||||
|
{
|
||||||
|
fn visit_item(&mut self, i: &'tcx hir::Item) {
|
||||||
|
let item_def_id = self.tcx.map.local_def_id(i.id);
|
||||||
|
let task_id = (self.dep_node_fn)(item_def_id);
|
||||||
|
let _task = self.tcx.dep_graph.in_task(task_id);
|
||||||
|
debug!("Started task {:?}", task_id);
|
||||||
|
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
|
||||||
|
self.visitor.visit_item(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let krate = tcx.dep_graph.with_ignore(|| tcx.map.krate());
|
||||||
|
let mut tracking_visitor = TrackingVisitor {
|
||||||
|
tcx: tcx,
|
||||||
|
dep_node_fn: &mut dep_node_fn,
|
||||||
|
visitor: visitor
|
||||||
|
};
|
||||||
|
krate.visit_all_items(&mut tracking_visitor)
|
||||||
|
}
|
|
@ -208,7 +208,7 @@ impl<'ast> Map<'ast> {
|
||||||
self.dep_graph.read(self.dep_node(id));
|
self.dep_graph.read(self.dep_node(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dep_node(&self, id0: NodeId) -> DepNode {
|
fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
|
||||||
let map = self.map.borrow();
|
let map = self.map.borrow();
|
||||||
let mut id = id0;
|
let mut id = id0;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use dep_graph::DepNode;
|
use dep_graph::DepNode;
|
||||||
|
use hir::def_id::DefId;
|
||||||
use ty::{Ty, TyS};
|
use ty::{Ty, TyS};
|
||||||
use ty::tls;
|
use ty::tls;
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, dep_node: DepNode) -> Option<Ty<'tcx>> {
|
pub fn get(&self, dep_node: DepNode<DefId>) -> Option<Ty<'tcx>> {
|
||||||
tls::with(|tcx| tcx.dep_graph.read(dep_node));
|
tls::with(|tcx| tcx.dep_graph.read(dep_node));
|
||||||
self.untracked_get()
|
self.untracked_get()
|
||||||
}
|
}
|
||||||
|
@ -61,11 +62,11 @@ impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unwrap(&self, dep_node: DepNode) -> Ty<'tcx> {
|
pub fn unwrap(&self, dep_node: DepNode<DefId>) -> Ty<'tcx> {
|
||||||
self.get(dep_node).unwrap()
|
self.get(dep_node).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fulfill(&self, dep_node: DepNode, value: Ty<'lt>) {
|
pub fn fulfill(&self, dep_node: DepNode<DefId>, value: Ty<'lt>) {
|
||||||
tls::with(|tcx| tcx.dep_graph.write(dep_node));
|
tls::with(|tcx| tcx.dep_graph.write(dep_node));
|
||||||
|
|
||||||
// Invariant (A) is fulfilled, because by (B), every alias
|
// Invariant (A) is fulfilled, because by (B), every alias
|
||||||
|
|
|
@ -24,7 +24,7 @@ macro_rules! dep_map_ty {
|
||||||
impl<'tcx> DepTrackingMapConfig for $ty_name<'tcx> {
|
impl<'tcx> DepTrackingMapConfig for $ty_name<'tcx> {
|
||||||
type Key = $key;
|
type Key = $key;
|
||||||
type Value = $value;
|
type Value = $value;
|
||||||
fn to_dep_node(key: &$key) -> DepNode { DepNode::$node_name(*key) }
|
fn to_dep_node(key: &$key) -> DepNode<DefId> { DepNode::$node_name(*key) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -887,7 +887,7 @@ impl<'tcx> TraitPredicate<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the dep-node for selecting/evaluating this trait reference.
|
/// Creates the dep-node for selecting/evaluating this trait reference.
|
||||||
fn dep_node(&self) -> DepNode {
|
fn dep_node(&self) -> DepNode<DefId> {
|
||||||
DepNode::TraitSelect(self.def_id())
|
DepNode::TraitSelect(self.def_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,7 +906,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||||
self.0.def_id()
|
self.0.def_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dep_node(&self) -> DepNode {
|
pub fn dep_node(&self) -> DepNode<DefId> {
|
||||||
// ok to skip binder since depnode does not care about regions
|
// ok to skip binder since depnode does not care about regions
|
||||||
self.0.dep_node()
|
self.0.dep_node()
|
||||||
}
|
}
|
||||||
|
@ -2666,7 +2666,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn visit_all_items_in_krate<V,F>(&self,
|
pub fn visit_all_items_in_krate<V,F>(&self,
|
||||||
dep_node_fn: F,
|
dep_node_fn: F,
|
||||||
visitor: &mut V)
|
visitor: &mut V)
|
||||||
where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx>
|
where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
|
||||||
{
|
{
|
||||||
dep_graph::visit_all_items_in_krate(self, dep_node_fn, visitor);
|
dep_graph::visit_all_items_in_krate(self, dep_node_fn, visitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,7 +584,8 @@ impl<'tcx> MirPass<'tcx> for TypeckMir {
|
||||||
// broken MIR, so try not to report duplicate errors.
|
// broken MIR, so try not to report duplicate errors.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let _task = tcx.dep_graph.in_task(DepNode::MirTypeck(id));
|
let def_id = tcx.map.local_def_id(id);
|
||||||
|
let _task = tcx.dep_graph.in_task(DepNode::MirTypeck(def_id));
|
||||||
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
|
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
|
||||||
let infcx = infer::new_infer_ctxt(tcx,
|
let infcx = infer::new_infer_ctxt(tcx,
|
||||||
&tcx.tables,
|
&tcx.tables,
|
||||||
|
|
|
@ -179,7 +179,7 @@ pub struct TraitSelectionCache<'tcx> {
|
||||||
impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
|
impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
|
||||||
type Key = ty::PolyTraitRef<'tcx>;
|
type Key = ty::PolyTraitRef<'tcx>;
|
||||||
type Value = traits::Vtable<'tcx, ()>;
|
type Value = traits::Vtable<'tcx, ()>;
|
||||||
fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode {
|
fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> {
|
||||||
ty::tls::with(|tcx| {
|
ty::tls::with(|tcx| {
|
||||||
let lifted_key = tcx.lift(key).unwrap();
|
let lifted_key = tcx.lift(key).unwrap();
|
||||||
lifted_key.to_poly_trait_predicate().dep_node()
|
lifted_key.to_poly_trait_predicate().dep_node()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue