Add incremental compilation debugging subchapter
This commit is contained in:
parent
7dea4167cf
commit
e7ce4f411c
|
|
@ -13,6 +13,7 @@
|
||||||
- [Rustdoc](./rustdoc.md)
|
- [Rustdoc](./rustdoc.md)
|
||||||
- [Queries: demand-driven compilation](./query.md)
|
- [Queries: demand-driven compilation](./query.md)
|
||||||
- [Incremental compilation](./incremental-compilation.md)
|
- [Incremental compilation](./incremental-compilation.md)
|
||||||
|
- [Debugging and Testing](./incrcomp-debugging.md)
|
||||||
- [The parser](./the-parser.md)
|
- [The parser](./the-parser.md)
|
||||||
- [Macro expansion](./macro-expansion.md)
|
- [Macro expansion](./macro-expansion.md)
|
||||||
- [Name resolution](./name-resolution.md)
|
- [Name resolution](./name-resolution.md)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
# Debugging and Testing Dependencies
|
||||||
|
|
||||||
|
## Testing the dependency graph
|
||||||
|
|
||||||
|
There are various ways to write tests against the dependency graph.
|
||||||
|
The simplest mechanisms are the `#[rustc_if_this_changed]` and
|
||||||
|
`#[rustc_then_this_would_need]` annotations. These are used in compile-fail
|
||||||
|
tests to test whether the expected set of paths exist in the dependency graph.
|
||||||
|
As an example, see `src/test/compile-fail/dep-graph-caller-callee.rs`.
|
||||||
|
|
||||||
|
The idea is that you can annotate a test like:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[rustc_if_this_changed]
|
||||||
|
fn foo() { }
|
||||||
|
|
||||||
|
#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
|
||||||
|
fn bar() { foo(); }
|
||||||
|
|
||||||
|
#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
|
||||||
|
fn baz() { }
|
||||||
|
```
|
||||||
|
|
||||||
|
This will check whether there is a path in the dependency graph from `Hir(foo)`
|
||||||
|
to `TypeckTables(bar)`. An error is reported for each
|
||||||
|
`#[rustc_then_this_would_need]` annotation that indicates whether a path
|
||||||
|
exists. `//~ ERROR` annotations can then be used to test if a path is found (as
|
||||||
|
demonstrated above).
|
||||||
|
|
||||||
|
## Debugging the dependency graph
|
||||||
|
|
||||||
|
### Dumping the graph
|
||||||
|
|
||||||
|
The compiler is also capable of dumping the dependency graph for your
|
||||||
|
debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The
|
||||||
|
graph will be dumped to `dep_graph.{txt,dot}` in the current
|
||||||
|
directory. You can override the filename with the `RUST_DEP_GRAPH`
|
||||||
|
environment variable.
|
||||||
|
|
||||||
|
Frequently, though, the full dep graph is quite overwhelming and not
|
||||||
|
particularly helpful. Therefore, the compiler also allows you to filter
|
||||||
|
the graph. You can filter in three ways:
|
||||||
|
|
||||||
|
1. All edges originating in a particular set of nodes (usually a single node).
|
||||||
|
2. All edges reaching a particular set of nodes.
|
||||||
|
3. All edges that lie between given start and end nodes.
|
||||||
|
|
||||||
|
To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should
|
||||||
|
look like one of the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
source_filter // nodes originating from source_filter
|
||||||
|
-> target_filter // nodes that can reach target_filter
|
||||||
|
source_filter -> target_filter // nodes in between source_filter and target_filter
|
||||||
|
```
|
||||||
|
|
||||||
|
`source_filter` and `target_filter` are a `&`-separated list of strings.
|
||||||
|
A node is considered to match a filter if all of those strings appear in its
|
||||||
|
label. So, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
RUST_DEP_GRAPH_FILTER='-> TypeckTables'
|
||||||
|
```
|
||||||
|
|
||||||
|
would select the predecessors of all `TypeckTables` nodes. Usually though you
|
||||||
|
want the `TypeckTables` node for some particular fn, so you might write:
|
||||||
|
|
||||||
|
```
|
||||||
|
RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar'
|
||||||
|
```
|
||||||
|
|
||||||
|
This will select only the predecessors of `TypeckTables` nodes for functions with
|
||||||
|
`bar` in their name.
|
||||||
|
|
||||||
|
Perhaps you are finding that when you change `foo` you need to re-type-check `bar`,
|
||||||
|
but you don't think you should have to. In that case, you might do:
|
||||||
|
|
||||||
|
```
|
||||||
|
RUST_DEP_GRAPH_FILTER='Hir & foo -> TypeckTables & bar'
|
||||||
|
```
|
||||||
|
|
||||||
|
This will dump out all the nodes that lead from `Hir(foo)` to
|
||||||
|
`TypeckTables(bar)`, from which you can (hopefully) see the source
|
||||||
|
of the erroneous edge.
|
||||||
|
|
||||||
|
### Tracking down incorrect edges
|
||||||
|
|
||||||
|
Sometimes, after you dump the dependency graph, you will find some
|
||||||
|
path that should not exist, but you will not be quite sure how it came
|
||||||
|
to be. **When the compiler is built with debug assertions,** it can
|
||||||
|
help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE`
|
||||||
|
environment variable to a filter. Every edge created in the dep-graph
|
||||||
|
will be tested against that filter -- if it matches, a `bug!` is
|
||||||
|
reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`).
|
||||||
|
|
||||||
|
The syntax for these filters is the same as described in the previous
|
||||||
|
section. However, note that this filter is applied to every **edge**
|
||||||
|
and doesn't handle longer paths in the graph, unlike the previous
|
||||||
|
section.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
You find that there is a path from the `Hir` of `foo` to the type
|
||||||
|
check of `bar` and you don't think there should be. You dump the
|
||||||
|
dep-graph as described in the previous section and open `dep-graph.txt`
|
||||||
|
to see something like:
|
||||||
|
|
||||||
|
Hir(foo) -> Collect(bar)
|
||||||
|
Collect(bar) -> TypeckTables(bar)
|
||||||
|
|
||||||
|
That first edge looks suspicious to you. So you set
|
||||||
|
`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and
|
||||||
|
then observe the backtrace. Voila, bug fixed!
|
||||||
Loading…
Reference in New Issue