Struct rustc_query_system::dep_graph::DepGraph
source · pub struct DepGraph<K: DepKind> {
data: Option<Lrc<DepGraphData<K>>>,
virtual_dep_node_index: Lrc<AtomicU32>,
}
Fields§
§data: Option<Lrc<DepGraphData<K>>>
§virtual_dep_node_index: Lrc<AtomicU32>
This field is used for assigning DepNodeIndices when running in
non-incremental mode. Even in non-incremental mode we make sure that
each task has a DepNodeIndex
that uniquely identifies it. This unique
ID is used for self-profiling.
Implementations§
source§impl<K: DepKind> DepGraph<K>
impl<K: DepKind> DepGraph<K>
pub fn new(
profiler: &SelfProfilerRef,
prev_graph: SerializedDepGraph<K>,
prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
encoder: FileEncoder,
record_graph: bool,
record_stats: bool
) -> DepGraph<K>
pub fn new_disabled() -> DepGraph<K>
sourcepub fn is_fully_enabled(&self) -> bool
pub fn is_fully_enabled(&self) -> bool
Returns true
if we are actually building the full dep-graph, and false
otherwise.
pub fn with_query(&self, f: impl Fn(&DepGraphQuery<K>))
pub fn assert_ignored(&self)
pub fn with_ignore<OP, R>(&self, op: OP) -> Rwhere
OP: FnOnce() -> R,
sourcepub fn with_query_deserialization<OP, R>(&self, op: OP) -> Rwhere
OP: FnOnce() -> R,
pub fn with_query_deserialization<OP, R>(&self, op: OP) -> Rwhere
OP: FnOnce() -> R,
Used to wrap the deserialization of a query result from disk,
This method enforces that no new DepNodes
are created during
query result deserialization.
Enforcing this makes the query dep graph simpler - all nodes must be created during the query execution, and should be created from inside the ‘body’ of a query (the implementation provided by a particular compiler crate).
Consider the case of three queries A
, B
, and C
, where
A
invokes B
and B
invokes C
:
A -> B -> C
Suppose that decoding the result of query B
required re-computing
the query C
. If we did not create a fresh TaskDeps
when
decoding B
, we would still be using the TaskDeps
for query A
(if we needed to re-execute A
). This would cause us to create
a new edge A -> C
. If this edge did not previously
exist in the DepGraph
, then we could end up with a different
DepGraph
at the end of compilation, even if there were no
meaningful changes to the overall program (e.g. a newline was added).
In addition, this edge might cause a subsequent compilation run
to try to force C
before marking other necessary nodes green. If
C
did not exist in the new compilation session, then we could
get an ICE. Normally, we would have tried (and failed) to mark
some other query green (e.g. item_children
) which was used
to obtain C
, which would prevent us from ever trying to force
a non-existent D
.
It might be possible to enforce that all DepNode
s read during
deserialization already exist in the previous DepGraph
. In
the above example, we would invoke D
during the deserialization
of B
. Since we correctly create a new TaskDeps
from the decoding
of B
, this would result in an edge B -> D
. If that edge already
existed (with the same DepPathHash
es), then it should be correct
to allow the invocation of the query to proceed during deserialization
of a query result. We would merely assert that the dep-graph fragment
that would have been added by invoking C
while decoding B
is equivalent to the dep-graph fragment that we already instantiated for B
(at the point where we successfully marked B as green).
However, this would require additional complexity in the query infrastructure, and is not currently needed by the decoding of any query results. Should the need arise in the future, we should consider extending the query system with this functionality.
sourcepub fn with_task<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
cx: Ctxt,
arg: A,
task: fn(_: Ctxt, _: A) -> R,
hash_result: Option<fn(_: &mut StableHashingContext<'_>, _: &R) -> Fingerprint>
) -> (R, DepNodeIndex)
pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
cx: Ctxt,
arg: A,
task: fn(_: Ctxt, _: A) -> R,
hash_result: Option<fn(_: &mut StableHashingContext<'_>, _: &R) -> Fingerprint>
) -> (R, DepNodeIndex)
Starts a new dep-graph task. Dep-graph tasks are specified
using a free function (task
) and not a closure – this
is intentional because we want to exercise tight control over
what state they have access to. In particular, we want to
prevent implicit ‘leaks’ of tracked state into the task (which
could then be read without generating correct edges in the
dep-graph – see the rustc dev guide for more details on
the dep-graph). To this end, the task function gets exactly two
pieces of state: the context cx
and an argument arg
. Both
of these bits of state must be of some type that implements
DepGraphSafe
and hence does not leak.
The choice of two arguments is not fundamental. One argument
would work just as well, since multiple values can be
collected using tuples. However, using two arguments works out
to be quite convenient, since it is common to need a context
(cx
) and some argument (e.g., a DefId
identifying what
item to process).
For cases where you need some other number of arguments:
- If you only need one argument, just use
()
for thearg
parameter. - If you need 3+ arguments, use a tuple for the
arg
parameter.
fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
cx: Ctxt,
arg: A,
task: fn(_: Ctxt, _: A) -> R,
hash_result: Option<fn(_: &mut StableHashingContext<'_>, _: &R) -> Fingerprint>
) -> (R, DepNodeIndex)
sourcepub fn with_anon_task<Tcx: DepContext<DepKind = K>, OP, R>(
&self,
cx: Tcx,
dep_kind: K,
op: OP
) -> (R, DepNodeIndex)where
OP: FnOnce() -> R,
pub fn with_anon_task<Tcx: DepContext<DepKind = K>, OP, R>(
&self,
cx: Tcx,
dep_kind: K,
op: OP
) -> (R, DepNodeIndex)where
OP: FnOnce() -> R,
Executes something within an “anonymous” task, that is, a task the
DepNode
of which is determined by the list of inputs it read from.
pub fn read_index(&self, dep_node_index: DepNodeIndex)
sourcepub fn with_feed_task<Ctxt: DepContext<DepKind = K>, A: Debug, R: Debug>(
&self,
node: DepNode<K>,
cx: Ctxt,
key: A,
result: &R,
hash_result: Option<fn(_: &mut StableHashingContext<'_>, _: &R) -> Fingerprint>
) -> DepNodeIndex
pub fn with_feed_task<Ctxt: DepContext<DepKind = K>, A: Debug, R: Debug>(
&self,
node: DepNode<K>,
cx: Ctxt,
key: A,
result: &R,
hash_result: Option<fn(_: &mut StableHashingContext<'_>, _: &R) -> Fingerprint>
) -> DepNodeIndex
Create a node when we force-feed a value into the query cache. This is used to remove cycles during type-checking const generic parameters.
As usual in the query system, we consider the current state of the calling query only depends on the list of dependencies up to now. As a consequence, the value that this query gives us can only depend on those dependencies too. Therefore, it is sound to use the current dependency set for the created node.
During replay, the order of the nodes is relevant in the dependency graph. So the unchanged replay will mark the caller query before trying to mark this one. If there is a change to report, the caller query will be re-executed before this one.
FIXME: If the code is changed enough for this node to be marked before requiring the caller’s node, we suppose that those changes will be enough to mark this node red and force a recomputation using the “normal” way.
pub fn dep_node_index_of(&self, dep_node: &DepNode<K>) -> DepNodeIndex
pub fn dep_node_index_of_opt(
&self,
dep_node: &DepNode<K>
) -> Option<DepNodeIndex>
pub fn dep_node_exists(&self, dep_node: &DepNode<K>) -> bool
pub fn prev_fingerprint_of(&self, dep_node: &DepNode<K>) -> Option<Fingerprint>
sourcepub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct>
pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct>
Checks whether a previous work product exists for v
and, if
so, return the path that leads to it. Used to skip doing work.
sourcepub fn previous_work_products(&self) -> &FxHashMap<WorkProductId, WorkProduct>
pub fn previous_work_products(&self) -> &FxHashMap<WorkProductId, WorkProduct>
Access the map of work-products created during the cached run. Only used during saving of the dep-graph.
pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode<K>)
pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode<K>) -> bool
pub fn register_dep_node_debug_str<F>(
&self,
dep_node: DepNode<K>,
debug_str_gen: F
)where
F: FnOnce() -> String,
pub fn dep_node_debug_str(&self, dep_node: DepNode<K>) -> Option<String>
fn node_color(&self, dep_node: &DepNode<K>) -> Option<DepNodeColor>
sourcepub fn try_mark_green<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
dep_node: &DepNode<K>
) -> Option<(SerializedDepNodeIndex, DepNodeIndex)>
pub fn try_mark_green<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
dep_node: &DepNode<K>
) -> Option<(SerializedDepNodeIndex, DepNodeIndex)>
Try to mark a node index for the node dep_node.
A node will have an index, when it’s already been marked green, or when we can mark it green. This function will mark the current task as a reader of the specified node, when a node index can be found for that node.
fn try_mark_parent_green<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
data: &DepGraphData<K>,
parent_dep_node_index: SerializedDepNodeIndex,
dep_node: &DepNode<K>
) -> Option<()>
sourcefn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
data: &DepGraphData<K>,
prev_dep_node_index: SerializedDepNodeIndex,
dep_node: &DepNode<K>
) -> Option<DepNodeIndex>
fn try_mark_previous_green<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
data: &DepGraphData<K>,
prev_dep_node_index: SerializedDepNodeIndex,
dep_node: &DepNode<K>
) -> Option<DepNodeIndex>
Try to mark a dep-node which existed in the previous compilation session as green.
sourcefn emit_side_effects<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
data: &DepGraphData<K>,
dep_node_index: DepNodeIndex,
side_effects: QuerySideEffects
)
fn emit_side_effects<Qcx: QueryContext<DepKind = K>>(
&self,
qcx: Qcx,
data: &DepGraphData<K>,
dep_node_index: DepNodeIndex,
side_effects: QuerySideEffects
)
Atomically emits some loaded diagnostics. This may be called concurrently on multiple threads for the same dep node.
sourcepub fn is_red(&self, dep_node: &DepNode<K>) -> bool
pub fn is_red(&self, dep_node: &DepNode<K>) -> bool
Returns true if the given node has been marked as red during the current compilation session. Used in various assertions
sourcepub fn is_green(&self, dep_node: &DepNode<K>) -> bool
pub fn is_green(&self, dep_node: &DepNode<K>) -> bool
Returns true if the given node has been marked as green during the current compilation session. Used in various assertions
sourcepub fn exec_cache_promotions<Tcx: DepContext<DepKind = K>>(&self, tcx: Tcx)
pub fn exec_cache_promotions<Tcx: DepContext<DepKind = K>>(&self, tcx: Tcx)
This method loads all on-disk cacheable query results into memory, so they can be written out to the new cache file again. Most query results will already be in memory but in the case where we marked something as green but then did not need the value, that value will never have been loaded from disk.
This method will only load queries that will end up in the disk cache. Other queries will not be executed.
pub fn print_incremental_info(&self)
pub fn encode(&self, profiler: &SelfProfilerRef) -> FileEncodeResult
pub(crate) fn next_virtual_depnode_index(&self) -> DepNodeIndex
Trait Implementations§
Auto Trait Implementations§
impl<K> !RefUnwindSafe for DepGraph<K>
impl<K> !Send for DepGraph<K>
impl<K> !Sync for DepGraph<K>
impl<K> Unpin for DepGraph<K>
impl<K> !UnwindSafe for DepGraph<K>
Blanket Implementations§
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference’s “Type Layout” chapter for details on type layout guarantees.
Size: 16 bytes