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.
| Time to Start | Worker time | Duration | Time to finish | Idle | |
| Config | 53s | 1s | 1s | 55s | 53s |
| Eval | 1m00s | 12s | 12s | 1m12s | 4s |
| Build | 1m12s | 0s | 1m25s | 2m38s | 1m25s |
| Suite | 53s | 13s | 1m44s | 2m38s | 2m24s |