Skip to content

Write a policy about the use of version bounds in Haskell packages #26

@michaelpj

Description

@michaelpj

This is a big topic. At the moment we mostly get by with the use of index-state to get consistent behaviour from the solver, but this is not a panacea. Different projects can use different index-states and there is no guarantee that newer ones will work. Moreover, errors are not obvious and can appear in distant upstream projects, a problem which gets more painful the deeper our dependency tree gets (consider the plight of Hydra). So I think some use of bounds is probably good.


Here's my proposal:

1. Dependencies on non-Cardano packages

a) Bounds that exclude known-broken versions

Often we know that certain versions won't work. Typically we get this information in one of two ways

  1. We bump our index state, which gets us foo-X+1 instead of foo-X
  2. Someone else did this and complains to us.

Then we have two options:

  1. Fix the errors for foo-X+1. Now we know that foo-X won't work, so adding a lower bound is cheap and correct.
  2. Defer fixing foo-X+1. Now we know that foo-X+1 won't work, so adding an upper bound is cheap and correct.

These are nice things to do: they give downstream consumers better errors

  • If you require foo >= X+1 and they either don't have it (old index-state) or can't have it (conflict), they'll get a solver error, instead of the solver happily picking foo-X and them getting an obscure compilation error in your package.
  • If you require foo < X+1 and they require it (conflict), again they'll get a solver error instead of picking foo-X+1 and getting an compilation error in your project.

b) Speculative upper bounds

It's somewhat common for people to add upper bounds that they don't know are broken, often on the next major version. I think we should not do this: this is one of the most common reasons to need allow-newer, and it's pretending to have information we don't have. This is maybe a point of contention.

2. Dependencies on Cardano packages

The arguments above also apply here, but we have additional information: namely that we have very little versioning discipline and essentially every release breaks things. That suggests that we could take a more aggressive policy: pin the major+minor version of any Cardano packages that you depend on (probably fine to let the patch version vary). i.e. do cardano-foo == x.y.z.* or similar.

This also means that updating to a new release of a Cardano package must be a conscious decision by the maintainer (because you have to change your version bounds). This is probably what we want!

3. Any component that isn't a library

Nobody else can depend on these, so who cares. You can probably just leave out the version bounds and rely on your local index-state for anyone who actually wants to use them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions