Skip to content

Commit 876f691

Browse files
committed
Drop the requirement of specifying upper bounds
1 parent c633fe8 commit 876f691

3 files changed

Lines changed: 18 additions & 112 deletions

File tree

pvp-faq.md

Lines changed: 10 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -92,109 +92,21 @@ bound in the SemVer representation.
9292

9393
## Upper bounds
9494

95-
### Defining upper bounds requires to know the future, as you can't know whether a not yet released future version will contain a breaking change.
96-
97-
Of course, the PVP doesn't provide you with a way to know *for sure*
98-
when compatibility will break; however, the PVP tells you a *least
99-
upper bound up to which your package is guaranteed* (under certain
100-
conditions) to remain compatible.
101-
102-
Without the PVP contract, you'd be left with no choice but to
103-
constraint your package to versions of dependencies for which you have
104-
empirical "known to work" evidence for (or complete control over).
105-
106-
### Upper bounds can be inferred by running build bots to determine when breaking changes have been introduced in dependencies.
107-
108-
This assumes that compile-success is equivalent to semantic
109-
correctness. While it's true that a compile failure implies that a
110-
breakage has occurred, the inverse is not true in general.
111-
112-
There's been already a couple of incidents (see next Q) when popular
113-
packages changed their semantics without changing their type-signature
114-
and thereby caused problems in packages which didn't have proper
115-
PVP-mandated upper bounds in place.
116-
117-
Therefore leaving off upper bounds under the assumption that breakages
118-
will show in form of build-failures is a dangerous erroneous belief,
119-
as it can result in hard to detect/debug silent failures.
95+
### What is the intended meaning of upper bounds; is it "*not known* to be compatible" or rather "*known not* to be compatible"?
12096

121-
### What are some real-world examples of packages causing breakage due to semantic changes?
97+
In the case of *not known to be compabitle*, newer Cabal versions (since 2.0)
98+
support the caret operator (`^>=`), which is not part of the PVP spec yet.
12299

123-
In the major version `aeson-0.10`, the serialization of `Maybe`-values
124-
was deliberately changed in an incompatible way which caused packages
125-
not declaring an upper bound to be caught off guard. In `aeson-0.11`
126-
this was changed yet again.
100+
It is described in the [cabal documentation](https://cabal.readthedocs.io/en/stable/cabal-package.html#pkg-field-build-depends).
127101

128-
In `deepseq-1.4`, the default method implementation of `rnf` was
129-
changed from reducing to WHNF to generically deriving a NF-evaluating
130-
traversal. Code which assumed a default of `rnf x = seq x ()` could
131-
break if the new `rnf` implementation resulted in suddenly traversing
132-
a data structure which wasn't meant to be traversed beyond WHNF (like
133-
e.g. cyclic data structures).
102+
It allows tools to relax upper bounds more easily, where defensive bounds were put in place.
134103

135-
### What is the intended meaning of upper bounds; is it "*not known* to be compatible" or rather "*known not* to be compatible"?
104+
The spec so far does not make a clear decision on the meaning of upper bounds. Maintainers
105+
may choose to not use the caret operator if they are still using an older Cabal version.
106+
Likewise, maintainers may choose to not use any upper bounds if they have confidence in
107+
their CI automation to detect breakages early.
136108

137-
Note how confusingly similar the two variants sound; it's just a
138-
subtle difference in word order. Also note the use of the term
139-
"compatible" which is intended to emphasize *semantic API
140-
compatibility*, rather than merely successful compilation
141-
(i.e. there's no "it compiles, it works" property which holds in
142-
general for Haskell... yet).
143-
144-
The central idea of the PVP (and SemVer) is to serve as a contract to
145-
communicate API compatibility guarantees (NB: *not* to predict
146-
breakage!). To this end, the version number semantics are encoded in
147-
sophisticated rules for when exactly to increment the various
148-
components.
149-
150-
As such, it makes little sense to interpret the PVP mandated upper
151-
bounds as the stronger "known not to be compatible" (i.e. having
152-
evidence of incompatibility), as then one would almost never be able
153-
to declare upper bounds in the first place. This would greatly reduce
154-
the value of the PVP as well as make it difficult to justify the effort
155-
of following the complex formal rules for assigning version numbers in
156-
the first place.
157-
158-
Consequently, the PVP mandated upper bounds are intended to denote
159-
"not known (yet) to be compatible" bounds, i.e. the least upper bounds
160-
up to which API compatibility is guaranteed by the PVP contract. This
161-
may not be an ultimate guarantee, but without such upper bounds,
162-
there's no guarantee *at all* the next released version won't cause
163-
breakage.
164-
165-
Or put differently, the goal of PVP mandated upper bounds is to be
166-
conservative, but in the most liberal way possible.
167-
168-
### Packages like `base` almost never break my code on major version increments; does this make predicted upper bounds less useful?
169-
170-
`base` is an example for a large package with a huge exposed API,
171-
which is tracked as a whole by a single version number. Often, API
172-
consumers tend to use only a small fraction of the exposed API
173-
surface, and in the case of `base` this most often a very stable
174-
subset. However, `base` being so large typically changes in backward
175-
incompatible ways with each major GHC release, even though most
176-
programs are not affected.
177-
178-
So the problem here is that big monolithic packages are rather
179-
disadvantageous in the context of semantic versioning, whose goal is
180-
to formalize version numbers to the point of making predicting upper
181-
bounds feasible at all.
182-
183-
However, this doesn't detract from the usefulness of upper bounds;
184-
this just means that more cost is shifted from the single API provider
185-
to its many API consumers for such big monolithic packages.
186-
187-
Ideally, such big packages can be deconstructed into smaller modular
188-
packages which each focus on separate concerns. This way version
189-
numbers become more expressive as they cover a smaller API surface,
190-
and the risk for API consumers of running into a major version update
191-
because of changes in totally unrelated parts is reduced accordingly.
192-
193-
But this comes at a cost: Maintaining a carefully crafted set of
194-
focused packages is more costly to the maintainer compared to
195-
maintaining a single monolithic package, which comes at the expense of
196-
API consumers as they need to review major version updates more
197-
frequently for potential incompatibilities.
109+
However, in light of the caret operator, regular upper bounds shall mean *known not to be compabitle*.
198110

199111
## Hackage & Stackage
200112

v1.0/pvp-specification.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,10 @@ Dependencies in Cabal
182182

183183
When publishing a Cabal package, you **SHALL** ensure that your
184184
dependencies in the `build-depends` field are accurate. This means
185-
specifying not only lower bounds, but also upper bounds on every
186-
dependency.
187-
188-
At some point in the future, Hackage may refuse to accept packages that
189-
do not follow this convention. The aim is that before this happens, we
190-
will put in place tool support that makes it easier to follow the
191-
convention and less painful when dependencies are updated.
185+
at least specifying lower bounds. You **SHALL* at least specify upper
186+
bounds if there are known incompatibilities.
187+
It is **NOT REQUIRED** to set an upper bound if all currently known
188+
versions of a dependency are compatible, although it is **RECOMMENDED**.
192189

193190
To minimize breakage when new package versions are released, you can use
194191
dependencies that are insensitive to minor version changes (e.g.

v1.1/pvp-specification.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,10 @@ Dependencies in Cabal
185185

186186
When publishing a Cabal package, you **SHALL** ensure that your
187187
dependencies in the `build-depends` field are accurate. This means
188-
specifying not only lower bounds, but also upper bounds on every
189-
dependency.
190-
191-
At some point in the future, Hackage may refuse to accept packages that
192-
do not follow this convention. The aim is that before this happens, we
193-
will put in place tool support that makes it easier to follow the
194-
convention and less painful when dependencies are updated.
188+
at least specifying lower bounds. You **SHALL* at least specify upper
189+
bounds if there are known incompatibilities.
190+
It is **NOT REQUIRED** to set an upper bound if all currently known
191+
versions of a dependency are compatible, although it is **RECOMMENDED**.
195192

196193
To minimize breakage when new package versions are released, you can use
197194
dependencies that are insensitive to minor version changes (e.g.

0 commit comments

Comments
 (0)