How should a package represent the fact that it does not support a particular GHC version?
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
Suppose I have a component C of a package P that does not build with GHC X, and I want to signal this to my users. There are a few ways of doing this:
1. Set `base` bounds that exclude the version of `base` that ships with that GHC
- Variant: bound some other non-reinstallable package
- Wart: this is sometimes semantically wrong, perhaps your package would build fine with that version of `base`, it's really _GHC_ that's the problem.
- UX: user gets a somewhat confusing solver error talking about `base` version compatibility
- Prevalence: very prevalent
2. Use a cabal file conditional on `impl(ghc)` and `buildable: False`
- UX: user gets a somewhat confusing solver error saying the component is not buildable (see https://github.com/haskell/cabal/issues/8905), in some circumstances cabal ignores the component entirely (e.g. when doing `cabal build all`).
- Wart: the nice UX is not transitive: if you have a package C2 that depends on C, then it also clearly "won't work on that GHC", but you just get solver errors and not the nice behaviour of ignoring the component
- Prevalence: I've only ever seen this at $WORK
3. Write in `tested-with`.
- Wart: this is pure metadata that does nothing.
- Wart: this is sometimes semantically wrong, it's too soft. Often it's not just that I "haven't tested with GHC X, so it might not work", I actively know that it _won't_ work with GHC X.
- UX: user gets no feedback at all, package just fails to compile or work or whatever
- Prevalence: occasionally used
None of these feel great to me. At the moment I think the `buildable: False` approach has the best UX, and it seems like the right way in principle, since it's a similar issue to "how should a package represent the fact that it does not support windows?". But it's still a bit unsatisfactory, and it's not widely used in the ecosystem.
This problem bites us quite a bit at work, since we have a lot of packages and they tend to gradually get support for new GHC versions. But our big package builder doesn't have a good way of knowing when a package isn't expected to work on a particular GHC so we have to have a big manual list of exceptions. It would be nice if this was more discernable from the package metadata.
It would be nice also if cabal recommended an approach. In particular, if we solved https://github.com/haskell/cabal/issues/8905 then I think promoting the `buildable: False` approach would be a strict improvement over setting `base` bounds, since it could give a better error to users. We're all used to interpreting solver errors mentioning `base` as GHC version conflicts, but it's a terrible UX.
The other idea I had is that maybe we could have some syntax to make this easy, e.g.: `supported-ghcs` on a component or at the top-level that implies the appropriate conditionals with nice messages.
Contributor guide
Research direction
Start by reading the alternatives in this issue and the linked issue #8905 about non-buildable components. Investigate how Cabal conditionals, buildable: False, tested-with, and package-level metadata currently behave; the work is done only when a clear, recommended representation for unsupported GHC versions and its user-facing behavior is agreed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100