Description
I ran into this bug while debugging a flaky test case -
A.hs
is initially not an FOI
, so GetModIface A.hs
has two dependencies IsFileOfInterest A.hs
and GetModIfaceFromDiskAndIndex A.hs
. Then A.hs
is opened, turning it into an FOI
haskell-language-server/ghcide/src/Development/IDE/Core/Rules.hs
Lines 934 to 957 in dfd8f0b
At this point A.hs
should have dependencies IsFileOfInterest A.hs
, Typecheck A.hs
... (the IsFOI
branch). However, I was seeing GetModIfaceFromDiskAndIndex
still getting run for A.hs
.
Investigating further, it turns out to be the implementation of refresh
in hls-graph
:
It seems like it speculatively builds all the previous dependencies of the key even if they might have changed. This is wrong as rules can have side effects or require preconditions (GetModIfaceFromDiskAndIndex
has both). This also can lead to spurious diagnostics from these pseudo-dependencies.
We should instead build dependencies in the order that they occurred (which we currently do not maintain), and recompute with RunDependenciesChanged
if any of them are dirty, short circuiting the evaluation of later dependencies (since they might not be true dependencies). However, this might have a negative impact on performance.
In the above case, that would mean skipping GetModIfaceFromDiskAndIndex
after we discover that IsFOI
has changed.