ffd889c7

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

A rule that sees a whole package

Stacked on the suppression PR. Adds HsGenValidInGenPackage from
haskell-style.md, which is the first rule that cannot answer from one module,
and with it the fact store that lets a rule see further.

A database rather than a file of records, because what a rule above the module
level does with facts is join them. One table per fact, owned by the rule that
writes it, so a rule brings its own schema the way it brings its own check. The
envelope never learns what is in that table, which is why adding a rule adds no
case to it: a package rule is a migration, what it writes out of one module,
and the query it answers with.

A fact is a row rather than a keyed entry. Two instances in one module are two
facts, and there is nothing to key them on that is not invented.

The rule's constructor is also its level, so nothing can disagree with it, and
each level judges exactly the suppressions naming its own rules. That is what
keeps unused-suppression detection sound without a global pass over the
repository.

Still one process, so the store has nowhere to go and nothing crosses a process
boundary yet. Nothing reads what the compiler wrote down. weeder removed seven
store queries on the way in that only a project rule would want, and the
package check's signature does not take the compiler's answers because this
rule has no use for them.

Where a store lives is a type rather than a path, because SQLite's word for
having no file at all is a file name that is not one, and a magic string is a
state a type can rule out. ChoicesFileError carries the file beside what is
wrong with it, so the error stays typed until the boundary that turns it into
something a report holds.

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 1m51s 1s 1s 1m52s 1m51s
Eval 2m13s 15s 15s 2m28s 20s
Build 2m28s 0s 0s 2m28s 0s
Suite 1m51s 16s 37s 2m28s 2m12s

Timeline

0s2m20s