incr.comp.: Update fingerprint-based auto tests for red/green tracking. (original) (raw)

The incr. comp. system computes fingerprints (hashes) of various things and then uses these fingerprints to check if something has changed in comparison to the previous compilation session. The test cases in src/test/incremental/hashes test, at a fine-grained level, that various changes in the source code lead to changed fingerprints of various intermediate results.
Before red/green change tracking (implemented in #44901) the compiler only computed fingerprints for the inputs of a program (i.e. the HIR) and the things exported to crate metadata. With the new tracking system we also compute hashes for almost all intermediate results, but the test cases in src/test/incremental/hashes do not reflect that yet.

A given item is tested by attaching a #[rustc_clean] attribute to them for expressing the expectation that the item's fingerprint has not changed, or by attaching a #[rustc_dirty] attribute if the fingerprint should have changed. These attributes have two arguments:

So, for example, if we want to assert that the fingerprint of the optimized MIR of a given function foo has changed between the first and the second compilation session and has not changed between sessions 2 and 3, we can do so as follows:

#[cfg(cfail1)] fn foo() { // ... }

#[rustc_dirty(label="MirOptimized", cfg="cfail2")] #[rustc_clean(label="MirOptimized", cfg="cfail3")] #[cfg(not(cfail1))] fn foo() { // ... }

Since #45104 we also have a more concise way of expressing these assertions. The following snippet of code tests that all relevant results are clean, except for "MirOptimized". This obviates the need to exhaustively list all DepKinds that should be checked. The testing framework knows which are relevant for the item the #[rustc_clean] or #[rustc_dirty] attribute is attached to.

#[cfg(cfail1)] fn foo() { // ... }

#[rustc_clean(except="MirOptimized", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] #[cfg(not(cfail1))] fn foo() { // ... }

The #[cfg] attributes attached to the function specify which version gets compiled in which compilation session (see also #36674 for another description of how these tests work). The possible values for the label argument are those DepNode variants that have a single DefId argument.

At the time of writing, there are 134 kinds of dependency nodes and it would be overkill to test fingerprints for all of these. But, depending on the kind of item under test, there are a few key ones that we should verify:

Free-standing Functions and Methods

These represent executable code, so we want to test their MIR:

Callers will depend on the signature of these items, so we better test

And a big part of compilation (that we eventually want to cache) is type inference information:

For methods, we can also check

which is a bit misnamed and actually describes the ty::AssociatedItem descriptor of the method.

Struct, Enum, and Union Definitions

For these we should at least test

in addition to Hir and HirBody. Note that changing the type of a
field does not change the type of the struct or enum, but adding/removing
fields or changing a fields name or visibility does.

Struct/Enum/Unions Fields

Fields are kind of separate from their containers, as they can change independently from them. We should at least check

Trait Definitions

For these we'll want to check

(Trait) Impls

For impls we'll want to check

Associated Items

For associated items (types, constants, and methods) we should check

Test Files to Update

The existing tests can be found in the src/test/incremental/hashes directory. A description of how the tests were setup initially can be found in issue #36674. The basic testing strategy should stay the same -- the goal here is to add the #[rustc_dirty]/#[rustc_clean] attributes for the labels listed above. The test suite can be executed by running ./x.py test --stage 1 src/test/incremental.

If you come a across an instance where you are not sure if it should be dirty or clean, or the compiler produces a result that's different from your expectation, feel free to leave a comment below or ask on gitter or IRC.

If you want to take on updating a specific test file, leave a comment below and I'll mark it has taken.

Good luck! :)