Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require top-level build-depends when it occurs in all branches of a conditional #984

Open
andreasabel opened this issue Oct 23, 2021 · 9 comments

Comments

@andreasabel
Copy link
Member

andreasabel commented Oct 23, 2021

This is the companion issue of haskell/cabal#7768.

See e.g. jvranish/Lenses#3.
Currently hackage does not allow revision of conditionals, and it does not allow new build-depends in a revision.
In the situation (1)

build-depends: base
  , A
if cond
  build-depends: B >= 0.1 && < 0.4
else
  build-depends: B >= 0.2 && < 0.5

the constraints for B cannot be revised.
Thus, the better practice is to put a top-level B with extra constraints in the conditional (2):

build-depends: base
  , A
  , B >= 0.1 && < 0.5
if cond
  build-depends: B < 0.4
else
  build-depends: B >= 0.2

hackage uploads could be required to add a top-level build-depends if it appears in all branches. So (1) would be rejected, and a suggestion of adding B to the top-level dependencies could be given:

build-depends: base
  , A
  , B
if cond
  build-depends: B >= 0.1 && < 0.4
else
  build-depends: B >= 0.2 && < 0.5

Enforcing this discipline would help with revisions on hackage that tighten constraints.

@andreasabel andreasabel changed the title Encourage top-level build-depends when it occurs in all branches of a conditional Require top-level build-depends when it occurs in all branches of a conditional Oct 23, 2021
@andreasabel
Copy link
Member Author

andreasabel commented Feb 16, 2022

I think I was mistaken, content of conditionals can be revised. However, conditionals cannot be added or deleted.

The OP looks like this:

base (>=4 && <4.15)
    mtl (>=1.1)
    if impl(ghc)
        if impl(ghc>=8.0)
            template-haskell (>=2.11.0.0)
        else
            if impl(ghc>=7.10)
                template-haskell (>=2.10.0.0)
            else
                if impl(ghc>=6.12)
                    template-haskell (>=2.4)
                else
                    template-haskell (>=2.2 && <2.4)

Build with GHC 9.0 fails because of a change in template-haskell (see below).
A bound template-haskell < 2.17 would be necessary for the versions already released on hackage.

Such a bound cannot be added to an existing conditional in this case. We need a new conditional:

  if impl (ghc < 9.0)
    template-haskell (< 2.17)

If new conditionals could be added if they do not introduce new dependencies (proposal!), then the discipline

Require top-level build-depends when it occurs in all branches of a conditional

would help revisability.

@gbaz
Copy link
Contributor

gbaz commented Feb 16, 2022

The current policies for revisions and their motivations are described at: https://github.com/haskell-infra/hackage-trustees/blob/master/revisions-information.md

I believe the policies should allow us to add new conditionals that do not introduce dependencies (or flags!). If the codebase does not, I would be open to a PR permitting it, with a corresponding update to clarify this in the policies.

@andreasabel
Copy link
Member Author

A simpler example: To allow bytestring-0.11 just for GHC >= 8, I wanted to add to existing bytestring bounds the conditional bound

if !impl(ghc >=8.0) { build-depends: bytestring < 0.11 } 

as suggested in https://hackage.haskell.org/package/bytestring-0.11.0.0/changelog.
This was rejected. I had to upload a new version: https://hackage.haskell.org/package/xor-0.0.1.1.

Reconstruction of the case (not all faithful---no sensible revision):
Screenshot 2022-02-16 at 20 10 57

@gbaz
Copy link
Contributor

gbaz commented Feb 16, 2022

Good example. I'd be fine allowing this.

@phadej
Copy link
Contributor

phadej commented Feb 16, 2022

FWIW, adding of conditionals with build-depends which don't add new dependencies has already have been discussed, I don't remember whether my and Herbert discussions are recorded though. Maybe in hackage-cli repository.

The problem is that someone have to implement it. (And maybe specify it a bit more formally, to ensure that revisions can be undone).

The naive approach of testing all combinations wouldn't work well, as e.g. https://hackage.haskell.org/package/semigroups-0.20 or https://hackage.haskell.org/package/transformers-compat-0.7.1 have over dozen of conditionals, and these are legit use cases.

@gbaz
Copy link
Contributor

gbaz commented Feb 16, 2022

I think it would be fine to allow new conditionals to mention any dependencies which occur in any existing branch.

@phadej
Copy link
Contributor

phadej commented Feb 16, 2022

I forgot to mention that it would be good that specification is not only revertible but also transitive:

I can think of revision path like:

-- 1
build-depends: foo
-- 2
build-depends: foo

if someConditional
  build-depends: foo
-- 3
if someConditional
  build-depends: foo

That doesn't seem right. My concern is that revisions shouldn't add any new dependencies in any possible configurations, they just relax or tighten the constraints. If above is allowed (i.e. adding conditionals with dependencies which are not already there) then revisions could introduce new dependencies for some people.

There are flags which disable/enable/select between different things, like HsOpenSSL / tls. If revisions would allow to add tls-dependency to openssl-branch, it would make revision making a bit too powerful for my liking.

I would like the revision from 2 to 3 (and reverse) to be forbidden. 1 <-> 2 are fine.

@gbaz
Copy link
Contributor

gbaz commented Feb 16, 2022

Fair enough. A good first cut would then be that new conditionals can be added iff they only place constraints on dependencies already listed at the top level, which seems close to the original intent of this ticket.

@andreasabel
Copy link
Member Author

A good first cut would then be that new conditionals can be added iff they only place constraints on dependencies already listed at the top level,

Agreed. This should be coupled with the policy stated in the title

Require top-level build-depends when it occurs in all branches of a conditional.

cabal check could warn if the policy is violated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants