By: Tom Sydney Kerckhove <syd@cs-syd.eu>
Typed paths, so a path that names nothing cannot be built packageFactsDir serialised as hopinion/. because a package directory was joined out of two strings, and it was then handed to wholeFileSpan, which wants a file. Both mistakes are now type errors. RelPath wraps Path Rel File. SourceRoot carries Path Abs Dir and Maybe (Path Rel Dir), where Nothing is a repository whose paths are already relative to it rather than an empty string that gets joined in anyway. Discovery, module resolution and the stray-file walk all work in typed paths, and the one place that turns what a person typed into a path the tool can join is the command layer, where the IO to resolve it belongs. packageFactsDir becomes packageFactsCabal. A package has no single file, so the no-gen-package abstention used to point at a directory; it points at the cabal file now, which is both a real file and where a reader would look for the gen package that is not there. Zero-width spans are widened to their line at render time, which is where the line length is known. A whole-file span used to render as a marker with nothing under it, sitting in a committed golden looking broken. The refactor found a bug the typing did not: walking a source directory a cabal file declares and the tree does not have used to be an exception rather than an empty answer, which killed the run on sydtest. There is a resource and a test for it now, and the test fails without the guard. factsForFile splits into itself and factsForSource, so the ormolu invariance test can ask what a reformatted module attaches to without writing it to a temporary file first. TemplateHaskell joins the hlint allowlist for path's mkRelFile, which is how a path literal is checked at compile time rather than parsed at runtime and hoped about.