83c105ba

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

Ask a field named after a project scalar for that scalar's type

HsNewtypeNotSynonym refuses a synonym for a domain scalar, and nothing refuses
the commoner shape: a field holding the primitive while the type that names it
sits unused in the same repository. A rule over that population has to decide
which Text is a domain scalar, and the obvious way is a word list of names, ids,
keys and hashes. That is a rule that fires on a name rather than on a type:
postBodyText, rowText and errorMessage are all text and all correctly typed, and
the list that excludes them is one somebody maintains against a corpus they
cannot see.

So the lexicon is the project's own newtypes. A field whose name ends in the
name of a scalar newtype the project defines, and whose type is that newtype's
underlying primitive, is a site that went without what the author had already
decided to write down. The finding is then not an opinion about domain-ness, and
the message can name the type to use. A project that has named nothing gets
nothing, which is the right incentive and also the rule's honest limit: it
cannot start the practice, only keep it.

Measured over src/ and app/ of six repositories, 2330 modules: forty-three
sites, nineteen in nix-ci, nineteen in centjes, four in smos and one here.
Sixteen of centjes's are Typst report inputs holding a Description that has
already been rendered. That is a rendering boundary, where the scalar genuinely
stops being the domain type, and it is the honest residue rather than a fault in
the matching. It is also what an author can say in one line and a checker
cannot, which puts the rule in bucket C: the site that declines carries an
[allow:HsScalarNewtypeUnused] with its reason, and the clean resource holds such
a site so that path is exercised rather than described.

Project tier, because the newtype and the site rarely share a module. Every
finding measured in nix-ci crosses a package boundary, so the resources are
whole repositories of two packages rather than single modules. Maybe, [] and
NonEmpty are read through, which was measured both ways round and adds three
findings in nix-ci that are all real. The one field of a scalar newtype is left
out whatever it is called, since unHostname is how Hostname is taken apart
rather than a site that declined it.

A rule that ships has to hold here, and the one site it finds is
ErrorDecl.errorDeclName, which held the name of a declaration as a Text while
this repository already defines DeclName for exactly that. DeclName rather than
TypeHead: a TypeHead is the head of an applied type with its arguments dropped,
deliberately lossy so that the obligation engine can ask whether a type is
tested at all, where this field is a declaration's own name, read off the same
tcdLName that every DeclName in the declaration list comes from.

The store format is bumped because the rule brings two tables. Without it, a
project run over package outputs written by an older build would find nothing
for this rule instead of saying why it cannot.
e2e-added-rule-is-rune2e-artifacts-are-reade2e-choices-are-found-beside-the-repositorye2e-cleane2e-dirty-package-is-judged-failinge2e-dirty-project-is-judged-failinge2e-dirty-report-is-readablee2e-disabled-rule-is-not-rune2e-incomplete-artifacts-are-a-failuree2e-judging-nothing-failse2e-named-packages-are-every-packagee2e-no-packages-is-judged-failinge2e-no-store-paths-in-findingse2e-paths-are-repository-relativee2e-withheld-facts-faile2e-wrong-source-mapping-is-a-complainthlint-checkhopinionpre-commitreleaseshellweeder-checkconfiguredevShelldefaultx86_64-linux