Are we all on the same page what we want? My understanding so far is:
- We want packages to properly follow PVP so we get some sensible build plans.
- We do not want to constantly work with package upgrade churn.
- We do want to permit exposure of less stable/internal parts so that you can reach into the module if you must without having to fork/source-repository-package, … it.
- Packages themselves of course can use any of their internal modules freely (after all PVP applies at the package level, and we should be able to assume that the package is internally consistent).
So for PVP compliance internal modules should not be exposed. At the same time dealing with a too restrictive surface of a library (as you only expose the interface you are happy to PVP version), yet providing the internal modules currently serves as a form of escape hatch, should you need something that isn’t in the PVP versioned exposed API. This to me is basically something we should track with metadata: I expose this, even though I don’t want to bother with providing a stable API for this and this does not follow any PVP versioning, if you need to use it, feel free to but, proceed at your own risk.
We have this informal convention thing with .Internal
modules right now.
Hence again, I think we should be able to have GHC support something like {-# INTERNAL #-}
markers to attach this metadata to the bindings. This could be picked up by haddock, and we could have some logic to enforce that INTERNAL tagged bindings do not leak out of module unless explicitly permitted.
This would allow us to get the benefits of the PVP, while still allowing for the practical escape hatch. (And similar to the ghc base library discussion, one would expect that usage of internal bindings would hopefully spur some petitioning for making those internal bindings part of the public API).
This would also allow automated tools (to inform PVP bounds) to ignore INTERNAL marked symbols. The alternative is to just not expose INTERNAL symbols, and then just have people fork/source-repository-package dependnecie they need ITNERNAL symbols from (which imo is pretty bad and cumbersome UX), especially if you are in the exploratory phase. Passing some -permit-internal
or -Wno-internal
. Would allow to just sidestep this temporarily.
At the same time it would allow you to compile with -Werror -Winternal
or (-prohibit-internal
), to make sure you don’t have any of these cross-package internal leakage, that would likely result in painful breakage (not caught, contained by the PVP).
The other view I guess is to solve this at the package level, don’t have Internal or other modules. Stick them into a separate package, and version that with PVP as well. This would basically mean we enforce PVP across all packages, and the exposure of internal components thus forces the existence of -internal packages, as they have to be PVP compliant as well.
Thus I believe the contention(?) might be between:
- adding metadata to top-level bindings, and
- increasing package granularity to permit rigorous pvp versioning?