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

Returns true if we are actually building the full dep-graph, and false otherwise.

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 DepNodes 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 DepPathHashes), 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.

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 the arg parameter.
  • If you need 3+ arguments, use a tuple for the arg parameter.

Executes something within an “anonymous” task, that is, a task the DepNode of which is determined by the list of inputs it read from.

Checks whether a previous work product exists for v and, if so, return the path that leads to it. Used to skip doing work.

Access the map of work-products created during the cached run. Only used during saving of the dep-graph.

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.

Try to mark a dep-node which existed in the previous compilation session as green.

Atomically emits some loaded diagnostics. This may be called concurrently on multiple threads for the same dep node.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

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