1. 0.01 s $ /nix/store/vzx1mi9c0xfadmsm9dhd83d005cb1qs9-coreutils-9.8/bin/timeout --kill-after=15s 1800s /nix/store/99b1z08awpxj8b6mzggn59gp1shljnff-nix-2.34.5/bin/nix --extra-experimental-features nix-command --extra-experimental-features flakes --log-format raw-with-logs build --no-link git+https://github.com/sellout/flaky?ref=docs&rev=8c7bfa3513eda13324eafa66edfe5e3f921478b8#checks.x86_64-linux.formatter --print-build-logs
  2. 0.07 s warning: ignoring untrusted flake configuration setting 'allow-import-from-derivation'.
  3. 0.07 s Pass '--accept-flake-config' to trust it
  4. 0.07 s warning: ignoring untrusted flake configuration setting 'extra-experimental-features'.
  5. 0.07 s Pass '--accept-flake-config' to trust it
  6. 0.07 s warning: ignoring untrusted flake configuration setting 'extra-substituters'.
  7. 0.07 s Pass '--accept-flake-config' to trust it
  8. 0.07 s warning: ignoring untrusted flake configuration setting 'extra-trusted-public-keys'.
  9. 0.07 s Pass '--accept-flake-config' to trust it
  10. 0.07 s warning: ignoring untrusted flake configuration setting 'sandbox'.
  11. 0.07 s Pass '--accept-flake-config' to trust it
  12. 0.07 s warning: ignoring untrusted flake configuration setting 'use-registries'.
  13. 0.07 s Pass '--accept-flake-config' to trust it
  14. 0.44 s error (ignored): SQLite database '/var/cache/private/nix-ci-worker/eval-cache-v6/c35873f8e9899069a2a63794fcf3e3d02fb9ecc53b4857113133e9bf7944bae3.sqlite' is busy
  15. 2.26 s post-build-hook: Uploading paths from nix-ci to cachix cache "sellout" /nix/store/ym27pkkkqpacc3hwbh0xsfiry1f0yhbc-treefmt
  16. 2.68 s post-build-hook: Nothing to push - all store paths are already on Cachix.
  17. 2.70 s post-build-hook: Uploading paths from nix-ci to the NixCI cache /nix/store/ym27pkkkqpacc3hwbh0xsfiry1f0yhbc-treefmt
  18. 2.74 s post-build-hook: warning: 'warn-short-path-literals' is deprecated, use 'lint-short-path-literals = ignore' instead
  19. 2.77 s post-build-hook: copying 0 paths...
  20. 2.81 s post-build-hook: warning: 'warn-short-path-literals' is deprecated, use 'lint-short-path-literals = ignore' instead
  21. 3.80 s post-build-hook: copying 0 paths...
  22. 4.31 s treefmt v2.4.0traversed 66 files
  23. 4.31 s emitted 52 files for processing
  24. 4.31 s formatted 52 files (4 changed) in 332ms
  25. 4.32 s M docs/CONTRIBUTING.md
  26. 4.32 s M docs/CONTRIBUTING/haskell.md
  27. 4.32 s M docs/haskell-release-process.md
  28. 4.32 s M docs/haskell-strict-PVP.md
  29. 4.32 s diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
  30. 4.32 s index 2b499f5..5465a5d 100644
  31. 4.32 s --- a/docs/CONTRIBUTING.md
  32. 4.32 s +++ b/docs/CONTRIBUTING.md
  33. 4.32 s @@ -25,10 +25,10 @@ All contributions are welcome, we love improvements to docs and tests.
  34. 4.32 s ### terminology
  35. 4.32 s
  36. 4.32 s | generic | Haskell | Nix | Rust | versioned |
  37. 4.32 s -|------------|---------------|------------|-----------|-----------|
  38. 4.32 s -| repository | | | | ✔ |
  39. 4.32 s +| ---------- | ------------- | ---------- | --------- | --------- |
  40. 4.32 s +| repository | | | | ✔ |
  41. 4.32 s | project | Cabal project | flake | workspace | |
  42. 4.32 s -| package | Cabal package | derivation | crate | ✔ |
  43. 4.32 s +| package | Cabal package | derivation | crate | ✔ |
  44. 4.32 s | component | Cabal stanza | | | |
  45. 4.32 s
  46. 4.32 s There is usually one project per repository, but sometimes a project may be split across multiple repositories. It’s unlikely that more than one project would be in the same repository.
  47. 4.32 s diff --git a/docs/CONTRIBUTING/haskell.md b/docs/CONTRIBUTING/haskell.md
  48. 4.32 s index 963d786..4592132 100644
  49. 4.32 s --- a/docs/CONTRIBUTING/haskell.md
  50. 4.32 s +++ b/docs/CONTRIBUTING/haskell.md
  51. 4.32 s @@ -50,7 +50,7 @@ Documentation is very important, but it shouldn’t detract from good naming. Th
  52. 4.32 s
  53. 4.32 s Documentation is written using [Haddock](https://haskell-haddock.readthedocs.io/), and it’s helpful to add Doctest examples, as described in the “testing” section below.
  54. 4.32 s
  55. 4.32 s -__NB__: Haddock isn’t Markdown! But the similarities can make it easy to forget sometimes. Please try to review your doc changes using [`cabal haddock-project`](https://cabal.readthedocs.io/en/stable/cabal-commands.html#cabal-haddock-project) before submitting them.
  56. 4.32 s +**NB**: Haddock isn’t Markdown! But the similarities can make it easy to forget sometimes. Please try to review your doc changes using [`cabal haddock-project`](https://cabal.readthedocs.io/en/stable/cabal-commands.html#cabal-haddock-project) before submitting them.
  57. 4.32 s
  58. 4.32 s #### guidelines
  59. 4.32 s
  60. 4.32 s @@ -93,7 +93,7 @@ name foo
  61. 4.32 s library
  62. 4.32 s ```
  63. 4.32 s
  64. 4.32 s -``` cabal
  65. 4.32 s +```cabal
  66. 4.32 s name: foo-hedgehog
  67. 4.32 s
  68. 4.32 s library
  69. 4.32 s diff --git a/docs/haskell-release-process.md b/docs/haskell-release-process.md
  70. 4.32 s index c761703..e08874f 100644
  71. 4.32 s --- a/docs/haskell-release-process.md
  72. 4.32 s +++ b/docs/haskell-release-process.md
  73. 4.32 s @@ -20,7 +20,7 @@ Don’t lump documentation & testing improvements into a breaking change just be
  74. 4.32 s
  75. 4.32 s ### format the PR title as a CHANGELOG entry
  76. 4.32 s
  77. 4.32 s -__TODO__: How does this work when there are multiple packages?
  78. 4.32 s +**TODO**: How does this work when there are multiple packages?
  79. 4.32 s
  80. 4.32 s ## release updates
  81. 4.32 s
  82. 4.32 s @@ -37,7 +37,6 @@ In as far as the release is automated, the changes should be made in the merge c
  83. 4.32 s
  84. 4.32 s [^1]: This is delicate, because the CI build matrix doesn’t do a good job of solving for other versions of local packages.
  85. 4.32 s
  86. 4.32 s -
  87. 4.32 s ## Hackage info
  88. 4.32 s
  89. 4.32 s Hackage allows you to optionally tag a release as “preferred” or ”deprecated”.
  90. 4.32 s diff --git a/docs/haskell-strict-PVP.md b/docs/haskell-strict-PVP.md
  91. 4.32 s index fd77a77..a165ea2 100644
  92. 4.32 s --- a/docs/haskell-strict-PVP.md
  93. 4.32 s +++ b/docs/haskell-strict-PVP.md
  94. 4.32 s @@ -2,15 +2,15 @@
  95. 4.32 s
  96. 4.32 s This is a versioning system that’s compatible with [the Haskell Package Versioning Policy](https://pvp.haskell.org/), but tries to prevent more issues with dependencies.
  97. 4.32 s
  98. 4.32 s -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).
  99. 4.32 s +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).
  100. 4.32 s
  101. 4.32 s # terminology
  102. 4.32 s
  103. 4.32 s -- __bump__: this aligns with SemVer’s requirements, which are stricter than PVP here. “bumping” a component in a version means _incrementing_ that component while resetting all less-significant components to zero. (PVP doesn’t require resetting the less-significant components, but it’s certainly allowed and generally followed in practice.) __NB__: Because not all versions may be released, or may be unavailable for some reason, in practice it may appear as if the weaker requirements of PVP were followed (components increased instead of strictly incremented, and less significant components not reset).
  104. 4.32 s +- **bump**: this aligns with SemVer’s requirements, which are stricter than PVP here. “bumping” a component in a version means _incrementing_ that component while resetting all less-significant components to zero. (PVP doesn’t require resetting the less-significant components, but it’s certainly allowed and generally followed in practice.) **NB**: Because not all versions may be released, or may be unavailable for some reason, in practice it may appear as if the weaker requirements of PVP were followed (components increased instead of strictly incremented, and less significant components not reset).
  105. 4.32 s
  106. 4.32 s -- __change__: Some versioning documents talk about changing declarations, but any change to a type is an incompatible change, so we can see changes as simply a removal followed by an addition (with a conflicting name).
  107. 4.32 s +- **change**: Some versioning documents talk about changing declarations, but any change to a type is an incompatible change, so we can see changes as simply a removal followed by an addition (with a conflicting name).
  108. 4.32 s
  109. 4.32 s -- __fine-grained API tracking__: This is a term I’m coining (maybe there’s prior art) for actually looking at the full transitive API of a module (roughly, the interface file, but with some additions), and analyzing each individual change. It allows you to have narrower version bumps than is implied by dependency versions. __FIXME__: This needs a specification too (e.g., modified definitions aren’t apparent from an interface file, or, if they are, it’s not machine checkable whether they’re breaking changes – there should be a way to annotate these changes with how they affect the API, and if any annotations are missing, they can be inferred to be no more significant than the version bump)
  110. 4.32 s +- **fine-grained API tracking**: This is a term I’m coining (maybe there’s prior art) for actually looking at the full transitive API of a module (roughly, the interface file, but with some additions), and analyzing each individual change. It allows you to have narrower version bumps than is implied by dependency versions. **FIXME**: This needs a specification too (e.g., modified definitions aren’t apparent from an interface file, or, if they are, it’s not machine checkable whether they’re breaking changes – there should be a way to annotate these changes with how they affect the API, and if any annotations are missing, they can be inferred to be no more significant than the version bump)
  111. 4.32 s
  112. 4.32 s # summary of differences from PVP (non-normative)
  113. 4.32 s
  114. 4.32 s @@ -19,14 +19,14 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
  115. 4.32 s - Strict PVP defines a “patch” level, corresponding to the `D` component (PVP references but never defines a “patch” level);
  116. 4.32 s - removing any instance or adding an orphan instance requires an `A` bump instead of an increase in `A.B`;
  117. 4.32 s - incompatible license changes require an `A` bump (PVP has nothing to say on licensing);
  118. 4.32 s -- adding a module moved from another package only __MAY__ bump the major version (it’s “SHOULD” in PVP);
  119. 4.32 s +- adding a module moved from another package only **MAY** bump the major version (it’s “SHOULD” in PVP);
  120. 4.32 s - deprecation only increments `D`, not `A.B` (compatible, because this is only a “SHOULD” in PVP);
  121. 4.32 s
  122. 4.32 s # specification
  123. 4.32 s
  124. 4.32 s -A package that follows Strict PVP __SHOULD__ declare that it does so (__FIXME__: We need a machine-checkable place to specify this declaration). This allows dependencies of the package to make additional assumptions based on the package version.
  125. 4.32 s +A package that follows Strict PVP **SHOULD** declare that it does so (**FIXME**: We need a machine-checkable place to specify this declaration). This allows dependencies of the package to make additional assumptions based on the package version.
  126. 4.32 s
  127. 4.32 s -A package that follows Strict PVP __MAY__ use fine-grained API tracking of its dependencies to use less significant version bumps than may be implied by the dependency versions.
  128. 4.32 s +A package that follows Strict PVP **MAY** use fine-grained API tracking of its dependencies to use less significant version bumps than may be implied by the dependency versions.
  129. 4.32 s
  130. 4.32 s ## version numbers
  131. 4.32 s
  132. 4.32 s @@ -48,7 +48,7 @@ If your imports are [package-qualified](https://downloads.haskell.org/ghc/latest
  133. 4.32 s
  134. 4.32 s #### all non-package-local imports must be either qualified or have explicit import lists
  135. 4.32 s
  136. 4.32 s -__TODO__: Determine if `Prelude` really is [an exception to this rule](https://wiki.haskell.org/Import_modules_properly#Exception_from_the_rule) – is it true that `Prelude` is fixed going forward?
  137. 4.32 s +**TODO**: Determine if `Prelude` really is [an exception to this rule](https://wiki.haskell.org/Import_modules_properly#Exception_from_the_rule) – is it true that `Prelude` is fixed going forward?
  138. 4.32 s
  139. 4.32 s #### restriction of multiple imports with the same qualifier
  140. 4.32 s
  141. 4.32 s @@ -62,7 +62,7 @@ Because of the transitivity of instances, orphans make you sensitive to your dep
  142. 4.32 s
  143. 4.32 s > _suggestion_: Cross-reference orphans in the Cabal package files. Collect the class names and relevant types for any orphans you define. Add a comment above the relevant dependencies in the Cabal package file listing which classes and types come from each.
  144. 4.32 s
  145. 4.33 s -__NB__: Alternatively, adding _any_ instance[^2] could be considered a transitively-breaking change. Then orphans wouldn’t need to trigger API sensitivity. On the one hand, that seems easier to manage and orphans are often unavoidable. However, it seems odd to penalize definers of non-orphan instances because of orphans, and relegating orphans to their own packages mitigates API sensitivity better than it mitigates transitively-breaking changes.
  146. 4.33 s +**NB**: Alternatively, adding _any_ instance[^2] could be considered a transitively-breaking change. Then orphans wouldn’t need to trigger API sensitivity. On the one hand, that seems easier to manage and orphans are often unavoidable. However, it seems odd to penalize definers of non-orphan instances because of orphans, and relegating orphans to their own packages mitigates API sensitivity better than it mitigates transitively-breaking changes.
  147. 4.33 s
  148. 4.33 s [^2]: Adding an instance at the same time as its class or a relevant type would always be a minor change, since there’s no way for an orphan to exist before that point.
  149. 4.33 s
  150. 4.33 s @@ -101,7 +101,7 @@ readAndTryChar :: IO (Either Error Char)
  151. 4.33 s readAndTryChar = tryChar <$> readLn
  152. 4.33 s ```
  153. 4.33 s
  154. 4.33 s -In this example, a new release of `top` adds a case to `Error`. Since the `NewError` pattern is exported, this is a breaking change, and is accordingly reported as one. `middle` builds cleanly with the new version of `top`, so a new revision (non-breaking) is cut with wider dependency bounds.
  155. 4.33 s +In this example, a new release of `top` adds a case to `Error`. Since the `NewError` pattern is exported, this is a breaking change, and is accordingly reported as one. `middle` builds cleanly with the new version of `top`, so a new revision (non-breaking) is cut with wider dependency bounds.
  156. 4.33 s
  157. 4.33 s [__FIXME: This example doesn’t really cause an issue with Haskell, because in order to pattern match on the type, you need a dependency on the `top`, which will collapse the issue – this is more of a problem with languages that don’t enforce such things – ilke languages with dictionaries – but with dictionaries, you should _always_ verify the key exists, right? Even so, removing the key means you no longer have access to that info, so there is an unofficial distinction between records and dictionaries in those languages]
  158. 4.33 s
  159. 4.33 s @@ -152,19 +152,19 @@ This can happen due to syntactic changes that don’t otherwise affect the API (
  160. 4.33 s
  161. 4.33 s #### removing support for a compiler version
  162. 4.33 s
  163. 4.33 s -__TODO__: Can this be constrained at all? E.g., can changing from supporting GHC 9.10.1(+) to 9.10.2(+) be considered a patch change?
  164. 4.33 s +**TODO**: Can this be constrained at all? E.g., can changing from supporting GHC 9.10.1(+) to 9.10.2(+) be considered a patch change?
  165. 4.33 s
  166. 4.33 s #### restricting an existing dependency’s version range in any way
  167. 4.33 s
  168. 4.33 s Consumers have to contend not only with our version bounds, but also with those of other libraries. It’s possible that some dependency overlapped in a very narrow way, and even just restricting a particular patch version of a dependency could make it impossible to find a dependency solution.
  169. 4.33 s
  170. 4.33 s -__TODO__: Determine if this is actually a lesser change. For example, can we get the solver to always fall back to a previous version (even if deprecated) if this version’s dependencies don’t intersect? If so, this is a patch change.
  171. 4.33 s +**TODO**: Determine if this is actually a lesser change. For example, can we get the solver to always fall back to a previous version (even if deprecated) if this version’s dependencies don’t intersect? If so, this is a patch change.
  172. 4.33 s
  173. 4.33 s #### adding a dependency
  174. 4.33 s
  175. 4.33 s A new dependency may make it impossible to find a solution in the face of other packages’ dependency ranges.
  176. 4.33 s
  177. 4.33 s -__TODO__: This may be similar to the previous case – will the solver go back to an older (even if deprecated) version that doesn’t have the new dependency?
  178. 4.33 s +**TODO**: This may be similar to the previous case – will the solver go back to an older (even if deprecated) version that doesn’t have the new dependency?
  179. 4.33 s
  180. 4.33 s ### non-breaking changes (bumps `C`)
  181. 4.33 s
  182. 4.33 s @@ -176,7 +176,7 @@ This is also what PVP recommends. However, unlike in PVP, this is because we rec
  183. 4.33 s
  184. 4.33 s Haskell does type resolution independently of constraints. It then sees if the type that was resolved satisfies the constraints. So removing constraints doesn’t affect what type is resolved, therefore it can’t cause a resolution failure.
  185. 4.33 s
  186. 4.33 s -__FIXME__: I think this might not be true with [type variable defaulting](https://downloads.haskell.org/ghc/9.14.1/docs/users_guide/exts/type_defaulting.html). For example, if you weaken a constraint from `RealFloat` to `Num`, and a consumer is using `default (Natural, Double)`, the switch from resolving `Double` to resolving `Natural` can then introduce a runtime failure when they call `negate`. There are mechanisms to disable defaulting, like `default ()` or requiring `-Werror=type-defaults`, but those must be applied in the consumer, not the definer.
  187. 4.33 s +**FIXME**: I think this might not be true with [type variable defaulting](https://downloads.haskell.org/ghc/9.14.1/docs/users_guide/exts/type_defaulting.html). For example, if you weaken a constraint from `RealFloat` to `Num`, and a consumer is using `default (Natural, Double)`, the switch from resolving `Double` to resolving `Natural` can then introduce a runtime failure when they call `negate`. There are mechanisms to disable defaulting, like `default ()` or requiring `-Werror=type-defaults`, but those must be applied in the consumer, not the definer.
  188. 4.33 s
  189. 4.33 s ### other changes (bumps `D`)
  190. 4.33 s
  191. 4.33 s @@ -190,7 +190,7 @@ The most common cases of this are
  192. 4.33 s
  193. 4.33 s #### deprecation
  194. 4.33 s
  195. 4.33 s -**NB**: This case is _weaker_ than PVP (but allowed), which indicates that packages __SHOULD__ bump their major version when adding `deprecated` pragmas.
  196. 4.33 s +**NB**: This case is _weaker_ than PVP (but allowed), which indicates that packages **SHOULD** bump their major version when adding `deprecated` pragmas.
  197. 4.33 s
  198. 4.33 s We disagree with this because packages shouldn’t be _publishing_ with `-Werror`. The intent of deprecation is to indicate that some API _will_ change. To make that signal a major change itself defeats the purpose. You want people to start seeing that warning as soon as possible. The major change occurs when you actually remove the old API.
  199. 4.33 s
  200. 4.33 s @@ -202,16 +202,16 @@ Yes, in development, `-Werror` is often (and should be) used. However, that just
  201. 4.33 s
  202. 4.33 s This is incompatible with both PVP and SPVP. It requires that a security fix be no more significant than a minor change.
  203. 4.33 s
  204. 4.33 s -__TODO__: This section includes some things that are outside the scope of a versioning system, and should be listed as “_suggestion_”s.
  205. 4.33 s +**TODO**: This section includes some things that are outside the scope of a versioning system, and should be listed as “_suggestion_”s.
  206. 4.33 s
  207. 4.33 s -A security fix __SHOULD__ be made without breaking the API. However, if that’s not possible, the breaking change __MUST__ bump `C` and leave `A` and `B` unchanged.
  208. 4.33 s +A security fix **SHOULD** be made without breaking the API. However, if that’s not possible, the breaking change **MUST** bump `C` and leave `A` and `B` unchanged.
  209. 4.33 s
  210. 4.33 s -A security fix, even if breaking, __MUST__ not include any other breaking changes. A security fix __SHOULD__ not include any unrelated changes at all. Even trivial changes can impede analysis, and my have some subtle effect that undermines the release.
  211. 4.33 s +A security fix, even if breaking, **MUST** not include any other breaking changes. A security fix **SHOULD** not include any unrelated changes at all. Even trivial changes can impede analysis, and my have some subtle effect that undermines the release.
  212. 4.33 s
  213. 4.33 s -Whatever mechanisms are available __SHOULD__ be used to deprecate[^4] the affected releases even before the fix is available. Once a fix is available, affected versions __SHOULD__ be made unavailable.
  214. 4.33 s +Whatever mechanisms are available **SHOULD** be used to deprecate[^4] the affected releases even before the fix is available. Once a fix is available, affected versions **SHOULD** be made unavailable.
  215. 4.33 s
  216. 4.33 s [^4]: In this case, “deprecate” refers to something like the Hackage mechanism, where a deprecated release is only used if no other compatible release is available. This means that users will be downgraded where possible before a fix is even available.
  217. 4.33 s
  218. 4.33 s This helps ensure that security fixes are propagated quickly.
  219. 4.33 s
  220. 4.33 s -__NB__: There’s what looks like a catch-22 here, but I think it’s an illusion – if a particular major version has an older unaffected release, then the actual fixed release may introduce an unnecessary breakage. But … if the older version wasn’t affected, then the fix must have been possible without breaking _that part_ of the API. That is, any breaking fix __SHOULD__ only cause breakage to APIs that have already been deprecated.
  221. 4.33 s +**NB**: There’s what looks like a catch-22 here, but I think it’s an illusion – if a particular major version has an older unaffected release, then the actual fixed release may introduce an unnecessary breakage. But … if the older version wasn’t affected, then the fix must have been possible without breaking _that part_ of the API. That is, any breaking fix **SHOULD** only cause breakage to APIs that have already been deprecated.
  222. 4.35 s error: Cannot build '/nix/store/1g96wfp5i7zbxh8j4g3f13shzcic3zjx-treefmt-check.drv'.
  223. 4.35 s Reason: builder failed with exit code 1.
  224. 4.35 s Output paths:
  225. 4.35 s /nix/store/grav8ff6lvl87xh0a8kwqymw3ibpypa3-treefmt-check
  226. 4.35 s Last 200 log lines:
  227. 4.35 s > treefmt v2.4.0traversed 66 files
  228. 4.35 s > emitted 52 files for processing
  229. 4.35 s > formatted 52 files (4 changed) in 332ms
  230. 4.35 s > M docs/CONTRIBUTING.md
  231. 4.35 s > M docs/CONTRIBUTING/haskell.md
  232. 4.35 s > M docs/haskell-release-process.md
  233. 4.35 s > M docs/haskell-strict-PVP.md
  234. 4.35 s > diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
  235. 4.35 s > index 2b499f5..5465a5d 100644
  236. 4.35 s > --- a/docs/CONTRIBUTING.md
  237. 4.35 s > +++ b/docs/CONTRIBUTING.md
  238. 4.35 s > @@ -25,10 +25,10 @@ All contributions are welcome, we love improvements to docs and tests.
  239. 4.35 s > ### terminology
  240. 4.35 s >
  241. 4.35 s > | generic | Haskell | Nix | Rust | versioned |
  242. 4.35 s > -|------------|---------------|------------|-----------|-----------|
  243. 4.35 s > -| repository | | | | ✔ |
  244. 4.35 s > +| ---------- | ------------- | ---------- | --------- | --------- |
  245. 4.35 s > +| repository | | | | ✔ |
  246. 4.35 s > | project | Cabal project | flake | workspace | |
  247. 4.35 s > -| package | Cabal package | derivation | crate | ✔ |
  248. 4.35 s > +| package | Cabal package | derivation | crate | ✔ |
  249. 4.35 s > | component | Cabal stanza | | | |
  250. 4.35 s >
  251. 4.35 s > There is usually one project per repository, but sometimes a project may be split across multiple repositories. It’s unlikely that more than one project would be in the same repository.
  252. 4.35 s > diff --git a/docs/CONTRIBUTING/haskell.md b/docs/CONTRIBUTING/haskell.md
  253. 4.35 s > index 963d786..4592132 100644
  254. 4.35 s > --- a/docs/CONTRIBUTING/haskell.md
  255. 4.35 s > +++ b/docs/CONTRIBUTING/haskell.md
  256. 4.35 s > @@ -50,7 +50,7 @@ Documentation is very important, but it shouldn’t detract from good naming. Th
  257. 4.35 s >
  258. 4.35 s > Documentation is written using [Haddock](https://haskell-haddock.readthedocs.io/), and it’s helpful to add Doctest examples, as described in the “testing” section below.
  259. 4.35 s >
  260. 4.35 s > -__NB__: Haddock isn’t Markdown! But the similarities can make it easy to forget sometimes. Please try to review your doc changes using [`cabal haddock-project`](https://cabal.readthedocs.io/en/stable/cabal-commands.html#cabal-haddock-project) before submitting them.
  261. 4.35 s > +**NB**: Haddock isn’t Markdown! But the similarities can make it easy to forget sometimes. Please try to review your doc changes using [`cabal haddock-project`](https://cabal.readthedocs.io/en/stable/cabal-commands.html#cabal-haddock-project) before submitting them.
  262. 4.35 s >
  263. 4.35 s > #### guidelines
  264. 4.35 s >
  265. 4.35 s > @@ -93,7 +93,7 @@ name foo
  266. 4.35 s > library
  267. 4.35 s > ```
  268. 4.35 s >
  269. 4.35 s > -``` cabal
  270. 4.35 s > +```cabal
  271. 4.35 s > name: foo-hedgehog
  272. 4.35 s >
  273. 4.35 s > library
  274. 4.35 s > diff --git a/docs/haskell-release-process.md b/docs/haskell-release-process.md
  275. 4.35 s > index c761703..e08874f 100644
  276. 4.35 s > --- a/docs/haskell-release-process.md
  277. 4.35 s > +++ b/docs/haskell-release-process.md
  278. 4.35 s > @@ -20,7 +20,7 @@ Don’t lump documentation & testing improvements into a breaking change just be
  279. 4.35 s >
  280. 4.35 s > ### format the PR title as a CHANGELOG entry
  281. 4.35 s >
  282. 4.35 s > -__TODO__: How does this work when there are multiple packages?
  283. 4.35 s > +**TODO**: How does this work when there are multiple packages?
  284. 4.35 s >
  285. 4.35 s > ## release updates
  286. 4.35 s >
  287. 4.35 s > @@ -37,7 +37,6 @@ In as far as the release is automated, the changes should be made in the merge c
  288. 4.35 s >
  289. 4.35 s > [^1]: This is delicate, because the CI build matrix doesn’t do a good job of solving for other versions of local packages.
  290. 4.35 s >
  291. 4.35 s > -
  292. 4.35 s > ## Hackage info
  293. 4.35 s >
  294. 4.35 s > Hackage allows you to optionally tag a release as “preferred” or ”deprecated”.
  295. 4.35 s > diff --git a/docs/haskell-strict-PVP.md b/docs/haskell-strict-PVP.md
  296. 4.35 s > index fd77a77..a165ea2 100644
  297. 4.35 s > --- a/docs/haskell-strict-PVP.md
  298. 4.35 s > +++ b/docs/haskell-strict-PVP.md
  299. 4.35 s > @@ -2,15 +2,15 @@
  300. 4.35 s >
  301. 4.35 s > This is a versioning system that’s compatible with [the Haskell Package Versioning Policy](https://pvp.haskell.org/), but tries to prevent more issues with dependencies.
  302. 4.35 s >
  303. 4.35 s > -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).
  304. 4.35 s > +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119).
  305. 4.35 s >
  306. 4.35 s > # terminology
  307. 4.35 s >
  308. 4.35 s > -- __bump__: this aligns with SemVer’s requirements, which are stricter than PVP here. “bumping” a component in a version means _incrementing_ that component while resetting all less-significant components to zero. (PVP doesn’t require resetting the less-significant components, but it’s certainly allowed and generally followed in practice.) __NB__: Because not all versions may be released, or may be unavailable for some reason, in practice it may appear as if the weaker requirements of PVP were followed (components increased instead of strictly incremented, and less significant components not reset).
  309. 4.35 s > +- **bump**: this aligns with SemVer’s requirements, which are stricter than PVP here. “bumping” a component in a version means _incrementing_ that component while resetting all less-significant components to zero. (PVP doesn’t require resetting the less-significant components, but it’s certainly allowed and generally followed in practice.) **NB**: Because not all versions may be released, or may be unavailable for some reason, in practice it may appear as if the weaker requirements of PVP were followed (components increased instead of strictly incremented, and less significant components not reset).
  310. 4.35 s >
  311. 4.35 s > -- __change__: Some versioning documents talk about changing declarations, but any change to a type is an incompatible change, so we can see changes as simply a removal followed by an addition (with a conflicting name).
  312. 4.35 s > +- **change**: Some versioning documents talk about changing declarations, but any change to a type is an incompatible change, so we can see changes as simply a removal followed by an addition (with a conflicting name).
  313. 4.35 s >
  314. 4.35 s > -- __fine-grained API tracking__: This is a term I’m coining (maybe there’s prior art) for actually looking at the full transitive API of a module (roughly, the interface file, but with some additions), and analyzing each individual change. It allows you to have narrower version bumps than is implied by dependency versions. __FIXME__: This needs a specification too (e.g., modified definitions aren’t apparent from an interface file, or, if they are, it’s not machine checkable whether they’re breaking changes – there should be a way to annotate these changes with how they affect the API, and if any annotations are missing, they can be inferred to be no more significant than the version bump)
  315. 4.35 s > +- **fine-grained API tracking**: This is a term I’m coining (maybe there’s prior art) for actually looking at the full transitive API of a module (roughly, the interface file, but with some additions), and analyzing each individual change. It allows you to have narrower version bumps than is implied by dependency versions. **FIXME**: This needs a specification too (e.g., modified definitions aren’t apparent from an interface file, or, if they are, it’s not machine checkable whether they’re breaking changes – there should be a way to annotate these changes with how they affect the API, and if any annotations are missing, they can be inferred to be no more significant than the version bump)
  316. 4.35 s >
  317. 4.35 s > # summary of differences from PVP (non-normative)
  318. 4.35 s >
  319. 4.35 s > @@ -19,14 +19,14 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
  320. 4.35 s > - Strict PVP defines a “patch” level, corresponding to the `D` component (PVP references but never defines a “patch” level);
  321. 4.35 s > - removing any instance or adding an orphan instance requires an `A` bump instead of an increase in `A.B`;
  322. 4.35 s > - incompatible license changes require an `A` bump (PVP has nothing to say on licensing);
  323. 4.35 s > -- adding a module moved from another package only __MAY__ bump the major version (it’s “SHOULD” in PVP);
  324. 4.35 s > +- adding a module moved from another package only **MAY** bump the major version (it’s “SHOULD” in PVP);
  325. 4.35 s > - deprecation only increments `D`, not `A.B` (compatible, because this is only a “SHOULD” in PVP);
  326. 4.35 s >
  327. 4.35 s > # specification
  328. 4.35 s >
  329. 4.35 s > -A package that follows Strict PVP __SHOULD__ declare that it does so (__FIXME__: We need a machine-checkable place to specify this declaration). This allows dependencies of the package to make additional assumptions based on the package version.
  330. 4.35 s > +A package that follows Strict PVP **SHOULD** declare that it does so (**FIXME**: We need a machine-checkable place to specify this declaration). This allows dependencies of the package to make additional assumptions based on the package version.
  331. 4.35 s >
  332. 4.35 s > -A package that follows Strict PVP __MAY__ use fine-grained API tracking of its dependencies to use less significant version bumps than may be implied by the dependency versions.
  333. 4.35 s > +A package that follows Strict PVP **MAY** use fine-grained API tracking of its dependencies to use less significant version bumps than may be implied by the dependency versions.
  334. 4.35 s >
  335. 4.35 s > ## version numbers
  336. 4.35 s >
  337. 4.35 s > @@ -48,7 +48,7 @@ If your imports are [package-qualified](https://downloads.haskell.org/ghc/latest
  338. 4.35 s >
  339. 4.35 s > #### all non-package-local imports must be either qualified or have explicit import lists
  340. 4.35 s >
  341. 4.35 s > -__TODO__: Determine if `Prelude` really is [an exception to this rule](https://wiki.haskell.org/Import_modules_properly#Exception_from_the_rule) – is it true that `Prelude` is fixed going forward?
  342. 4.35 s > +**TODO**: Determine if `Prelude` really is [an exception to this rule](https://wiki.haskell.org/Import_modules_properly#Exception_from_the_rule) – is it true that `Prelude` is fixed going forward?
  343. 4.35 s >
  344. 4.35 s > #### restriction of multiple imports with the same qualifier
  345. 4.35 s >
  346. 4.35 s > @@ -62,7 +62,7 @@ Because of the transitivity of instances, orphans make you sensitive to your dep
  347. 4.35 s >
  348. 4.35 s > > _suggestion_: Cross-reference orphans in the Cabal package files. Collect the class names and relevant types for any orphans you define. Add a comment above the relevant dependencies in the Cabal package file listing which classes and types come from each.
  349. 4.35 s >
  350. 4.35 s > -__NB__: Alternatively, adding _any_ instance[^2] could be considered a transitively-breaking change. Then orphans wouldn’t need to trigger API sensitivity. On the one hand, that seems easier to manage and orphans are often unavoidable. However, it seems odd to penalize definers of non-orphan instances because of orphans, and relegating orphans to their own packages mitigates API sensitivity better than it mitigates transitively-breaking changes.
  351. 4.35 s > +**NB**: Alternatively, adding _any_ instance[^2] could be considered a transitively-breaking change. Then orphans wouldn’t need to trigger API sensitivity. On the one hand, that seems easier to manage and orphans are often unavoidable. However, it seems odd to penalize definers of non-orphan instances because of orphans, and relegating orphans to their own packages mitigates API sensitivity better than it mitigates transitively-breaking changes.
  352. 4.35 s >
  353. 4.35 s > [^2]: Adding an instance at the same time as its class or a relevant type would always be a minor change, since there’s no way for an orphan to exist before that point.
  354. 4.35 s >
  355. 4.35 s > @@ -101,7 +101,7 @@ readAndTryChar :: IO (Either Error Char)
  356. 4.35 s > readAndTryChar = tryChar <$> readLn
  357. 4.35 s > ```
  358. 4.35 s >
  359. 4.35 s > -In this example, a new release of `top` adds a case to `Error`. Since the `NewError` pattern is exported, this is a breaking change, and is accordingly reported as one. `middle` builds cleanly with the new version of `top`, so a new revision (non-breaking) is cut with wider dependency bounds.
  360. 4.35 s > +In this example, a new release of `top` adds a case to `Error`. Since the `NewError` pattern is exported, this is a breaking change, and is accordingly reported as one. `middle` builds cleanly with the new version of `top`, so a new revision (non-breaking) is cut with wider dependency bounds.
  361. 4.35 s >
  362. 4.35 s > [__FIXME: This example doesn’t really cause an issue with Haskell, because in order to pattern match on the type, you need a dependency on the `top`, which will collapse the issue – this is more of a problem with languages that don’t enforce such things – ilke languages with dictionaries – but with dictionaries, you should _always_ verify the key exists, right? Even so, removing the key means you no longer have access to that info, so there is an unofficial distinction between records and dictionaries in those languages]
  363. 4.35 s >
  364. 4.35 s > @@ -152,19 +152,19 @@ This can happen due to syntactic changes that don’t otherwise affect the API (
  365. 4.35 s >
  366. 4.35 s > #### removing support for a compiler version
  367. 4.35 s >
  368. 4.35 s > -__TODO__: Can this be constrained at all? E.g., can changing from supporting GHC 9.10.1(+) to 9.10.2(+) be considered a patch change?
  369. 4.35 s > +**TODO**: Can this be constrained at all? E.g., can changing from supporting GHC 9.10.1(+) to 9.10.2(+) be considered a patch change?
  370. 4.35 s >
  371. 4.35 s > #### restricting an existing dependency’s version range in any way
  372. 4.35 s >
  373. 4.35 s > Consumers have to contend not only with our version bounds, but also with those of other libraries. It’s possible that some dependency overlapped in a very narrow way, and even just restricting a particular patch version of a dependency could make it impossible to find a dependency solution.
  374. 4.35 s >
  375. 4.35 s > -__TODO__: Determine if this is actually a lesser change. For example, can we get the solver to always fall back to a previous version (even if deprecated) if this version’s dependencies don’t intersect? If so, this is a patch change.
  376. 4.35 s > +**TODO**: Determine if this is actually a lesser change. For example, can we get the solver to always fall back to a previous version (even if deprecated) if this version’s dependencies don’t intersect? If so, this is a patch change.
  377. 4.35 s >
  378. 4.35 s > #### adding a dependency
  379. 4.35 s >
  380. 4.35 s > A new dependency may make it impossible to find a solution in the face of other packages’ dependency ranges.
  381. 4.35 s >
  382. 4.35 s > -__TODO__: This may be similar to the previous case – will the solver go back to an older (even if deprecated) version that doesn’t have the new dependency?
  383. 4.35 s > +**TODO**: This may be similar to the previous case – will the solver go back to an older (even if deprecated) version that doesn’t have the new dependency?
  384. 4.35 s >
  385. 4.35 s > ### non-breaking changes (bumps `C`)
  386. 4.35 s >
  387. 4.35 s > @@ -176,7 +176,7 @@ This is also what PVP recommends. However, unlike in PVP, this is because we rec
  388. 4.35 s >
  389. 4.35 s > Haskell does type resolution independently of constraints. It then sees if the type that was resolved satisfies the constraints. So removing constraints doesn’t affect what type is resolved, therefore it can’t cause a resolution failure.
  390. 4.35 s >
  391. 4.35 s > -__FIXME__: I think this might not be true with [type variable defaulting](https://downloads.haskell.org/ghc/9.14.1/docs/users_guide/exts/type_defaulting.html). For example, if you weaken a constraint from `RealFloat` to `Num`, and a consumer is using `default (Natural, Double)`, the switch from resolving `Double` to resolving `Natural` can then introduce a runtime failure when they call `negate`. There are mechanisms to disable defaulting, like `default ()` or requiring `-Werror=type-defaults`, but those must be applied in the consumer, not the definer.
  392. 4.35 s > +**FIXME**: I think this might not be true with [type variable defaulting](https://downloads.haskell.org/ghc/9.14.1/docs/users_guide/exts/type_defaulting.html). For example, if you weaken a constraint from `RealFloat` to `Num`, and a consumer is using `default (Natural, Double)`, the switch from resolving `Double` to resolving `Natural` can then introduce a runtime failure when they call `negate`. There are mechanisms to disable defaulting, like `default ()` or requiring `-Werror=type-defaults`, but those must be applied in the consumer, not the definer.
  393. 4.35 s >
  394. 4.35 s > ### other changes (bumps `D`)
  395. 4.35 s >
  396. 4.35 s > @@ -190,7 +190,7 @@ The most common cases of this are
  397. 4.35 s >
  398. 4.35 s > #### deprecation
  399. 4.35 s >
  400. 4.35 s > -**NB**: This case is _weaker_ than PVP (but allowed), which indicates that packages __SHOULD__ bump their major version when adding `deprecated` pragmas.
  401. 4.35 s > +**NB**: This case is _weaker_ than PVP (but allowed), which indicates that packages **SHOULD** bump their major version when adding `deprecated` pragmas.
  402. 4.35 s >
  403. 4.35 s > We disagree with this because packages shouldn’t be _publishing_ with `-Werror`. The intent of deprecation is to indicate that some API _will_ change. To make that signal a major change itself defeats the purpose. You want people to start seeing that warning as soon as possible. The major change occurs when you actually remove the old API.
  404. 4.35 s >
  405. 4.35 s > @@ -202,16 +202,16 @@ Yes, in development, `-Werror` is often (and should be) used. However, that just
  406. 4.35 s >
  407. 4.35 s > This is incompatible with both PVP and SPVP. It requires that a security fix be no more significant than a minor change.
  408. 4.35 s >
  409. 4.35 s > -__TODO__: This section includes some things that are outside the scope of a versioning system, and should be listed as “_suggestion_”s.
  410. 4.35 s > +**TODO**: This section includes some things that are outside the scope of a versioning system, and should be listed as “_suggestion_”s.
  411. 4.35 s >
  412. 4.35 s > -A security fix __SHOULD__ be made without breaking the API. However, if that’s not possible, the breaking change __MUST__ bump `C` and leave `A` and `B` unchanged.
  413. 4.35 s > +A security fix **SHOULD** be made without breaking the API. However, if that’s not possible, the breaking change **MUST** bump `C` and leave `A` and `B` unchanged.
  414. 4.35 s >
  415. 4.35 s > -A security fix, even if breaking, __MUST__ not include any other breaking changes. A security fix __SHOULD__ not include any unrelated changes at all. Even trivial changes can impede analysis, and my have some subtle effect that undermines the release.
  416. 4.35 s > +A security fix, even if breaking, **MUST** not include any other breaking changes. A security fix **SHOULD** not include any unrelated changes at all. Even trivial changes can impede analysis, and my have some subtle effect that undermines the release.
  417. 4.35 s >
  418. 4.35 s > -Whatever mechanisms are available __SHOULD__ be used to deprecate[^4] the affected releases even before the fix is available. Once a fix is available, affected versions __SHOULD__ be made unavailable.
  419. 4.35 s > +Whatever mechanisms are available **SHOULD** be used to deprecate[^4] the affected releases even before the fix is available. Once a fix is available, affected versions **SHOULD** be made unavailable.
  420. 4.35 s >
  421. 4.35 s > [^4]: In this case, “deprecate” refers to something like the Hackage mechanism, where a deprecated release is only used if no other compatible release is available. This means that users will be downgraded where possible before a fix is even available.
  422. 4.35 s >
  423. 4.35 s > This helps ensure that security fixes are propagated quickly.
  424. 4.35 s >
  425. 4.35 s > -__NB__: There’s what looks like a catch-22 here, but I think it’s an illusion – if a particular major version has an older unaffected release, then the actual fixed release may introduce an unnecessary breakage. But … if the older version wasn’t affected, then the fix must have been possible without breaking _that part_ of the API. That is, any breaking fix __SHOULD__ only cause breakage to APIs that have already been deprecated.
  426. 4.35 s > +**NB**: There’s what looks like a catch-22 here, but I think it’s an illusion – if a particular major version has an older unaffected release, then the actual fixed release may introduce an unnecessary breakage. But … if the older version wasn’t affected, then the fix must have been possible without breaking _that part_ of the API. That is, any breaking fix **SHOULD** only cause breakage to APIs that have already been deprecated.
  427. 4.35 s For full logs, run:
  428. 4.35 s nix log /nix/store/1g96wfp5i7zbxh8j4g3f13shzcic3zjx-treefmt-check.drv