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.

Total

8s

Created Started Finished

Time to Start Worker time Duration Time to finish Idle
Config 0s 0s 0s 0s 0s
Eval 0s 7s 7s 8s 0s
Build 7s 0s 0s 8s 0s
Suite 0s 8s 8s 8s 0s

Timeline

Config Eval Build
0s