Gabriella439 / turtle

Shell programming, Haskell style
BSD 3-Clause "New" or "Revised" License
943 stars 90 forks source link

Build against `optparse-applicative-0.18.1.0` #446

Closed ysangkok closed 1 year ago

ysangkok commented 1 year ago

Tested using cabal test. This should allow turtle to get back into Stackage.

Gabriella439 commented 1 year ago

thank you!!!

michaelpj commented 1 year ago

This unfortunately allows some non-working solutions:

I think the only solution here is to require the newer versions of both, otherwise it's quite likely that if a user accidentally gets an earlier version of one of them, they'll just get a compiler error. I can make a patch if that's okay.

michaelpj commented 1 year ago

The alternative would be to have a version of turtle-1.6 that built with the old versions, and then one that forces the new versions. I think the simplest way to do that would be to revert the recent revisions to relax the bounds and then make an new release with higher bounds. Not sure though.

ysangkok commented 1 year ago

I don't understand what "But optparse-applicative > 1.8 and ansi-wl-pprint < 1.0" means? I don't understand the conflict, I assume that there are unsatisfiable constraints?

michaelpj commented 1 year ago

Sorry, let me be clearer.

In the past, optparse-applicative used ansi-wl-pprint for prettyprinting. Users who used both libraries could therefore interoperate between them.

Recently, optparse-applicative started using prettyprinter. Even more recently, ansi-wl-pprint was updated to also use prettyprinter. Users who use the new versions of these libraries can interoperate between them.

What does not work is e.g. a new optparse-applicative and an old ansi-wl-pprint, because they use different prettyprinting libraries and cannot interoperate. Since neither depends on the other, this incompatibilty cannot be conveyed to cabal so cabal can freely choose such a build plan, and it will just result in errors at the use site.

turtles version bounds allow this case since this revision. For me, that meant that turtle stopped compiling, since cabal picked the bad build plan. Since it's a revision, I can't pin to a working version and have to use external constraints.

Hence my suggestion:

ysangkok commented 1 year ago

To me, it sounds best to just bump the lower bound of both as you previously suggested. Users with older versions can pull constraints from old Stackage snapshots.

michaelpj commented 1 year ago

Well, at the moment it's a landmine for cabal users. I would be fine with bumping the lower bounds again, I just think it's unfortunate to do this by revision as it potentially will break some people's build plans (as it would break mine, since I'm forced into the old ansi-wl-pprint!).

Gabriella439 commented 1 year ago

@michaelpj: Could you give me an example of the exact turtle build failure you're running into? That would help me better understand what's going on.

michaelpj commented 1 year ago

In turtle: cabal build --constraint 'ansi-wl-pprint < 1. This is allowed by the solver but do not build. If you have this constraint from elsewhere in the build plan your will get a build failure.

(I thought cabal build --constraint 'optparse-applicative < 0.18 would also break but it in fact doesn't!)

amesgen commented 1 year ago

Also just ran into this, reproducible example: Checkout current master (38a64c479af9ffdacb2bd6b83d2a821734918151) and run (I used GHC 9.2.8, but I think it shouldn't matter)

cabal build --index-state=2023-10-04T00:00:00Z --constraint='ansi-wl-pprint < 1'

You then get error messages like

src/Turtle/Options.hs:100:40: error:
    • Couldn't match type ‘Doc’
                     with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc
                             prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’
      Expected: Options.Applicative.Help.Pretty.Doc
        Actual: Doc
      NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’
            is defined in ‘Prettyprinter.Internal’
                in package ‘prettyprinter-1.7.1’
          ‘Doc’
            is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’
                in package ‘ansi-wl-pprint-0.6.9’
    • In the first argument of ‘Just’, namely ‘(getDescription desc)’
      In the first argument of ‘Opts.headerDoc’, namely
        ‘(Just (getDescription desc))’
      In the second argument of ‘Opts.info’, namely
        ‘(Opts.headerDoc (Just (getDescription desc)))’
    |
100 |                 (Opts.headerDoc (Just (getDescription desc)))
    |                                        ^^^^^^^^^^^^^^^^^^^
Full log ``` [ 1 of 10] Compiling Turtle.Internal ( src/Turtle/Internal.hs, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Internal.o, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Internal.dyn_o ) [ 2 of 10] Compiling Turtle.Line ( src/Turtle/Line.hs, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Line.o, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Line.dyn_o ) src/Turtle/Line.hs:67:3: warning: [-Wnoncanonical-monoid-instances] Noncanonical ‘(<>) = mappend’ definition detected in the instance declaration for ‘Semigroup Line’. Move definition from ‘mappend’ to ‘(<>)’ See also: https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/semigroup-monoid | 67 | (<>) = mappend | ^^^^^^^^^^^^^^ [ 3 of 10] Compiling Turtle.Format ( src/Turtle/Format.hs, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Format.o, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Format.dyn_o ) src/Turtle/Format.hs:72:1: warning: [-Wunused-imports] The import of ‘Data.Monoid’ is redundant except perhaps to import instances from ‘Data.Monoid’ To import instances alone, use: import Data.Monoid() | 72 | import Data.Monoid ((<>)) | ^^^^^^^^^^^^^^^^^^^^^^^^^ [ 4 of 10] Compiling Turtle.Options ( src/Turtle/Options.hs, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Options.o, /tmp/tmp.3fnNRBFySY/turtle/dist-newstyle/build/x86_64-linux/ghc-9.2.8/turtle-1.6.1/build/Turtle/Options.dyn_o ) src/Turtle/Options.hs:100:40: error: • Couldn't match type ‘Doc’ with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’ Expected: Options.Applicative.Help.Pretty.Doc Actual: Doc NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’ is defined in ‘Prettyprinter.Internal’ in package ‘prettyprinter-1.7.1’ ‘Doc’ is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’ in package ‘ansi-wl-pprint-0.6.9’ • In the first argument of ‘Just’, namely ‘(getDescription desc)’ In the first argument of ‘Opts.headerDoc’, namely ‘(Just (getDescription desc))’ In the second argument of ‘Opts.info’, namely ‘(Opts.headerDoc (Just (getDescription desc)))’ | 100 | (Opts.headerDoc (Just (getDescription desc))) | ^^^^^^^^^^^^^^^^^^^ src/Turtle/Options.hs:117:40: error: • Couldn't match type ‘Doc’ with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’ Expected: Options.Applicative.Help.Pretty.Doc Actual: Doc NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’ is defined in ‘Prettyprinter.Internal’ in package ‘prettyprinter-1.7.1’ ‘Doc’ is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’ in package ‘ansi-wl-pprint-0.6.9’ • In the first argument of ‘Just’, namely ‘(getHeader header)’ In the first argument of ‘Opts.headerDoc’, namely ‘(Just (getHeader header))’ In the first argument of ‘(<>)’, namely ‘Opts.headerDoc (Just (getHeader header))’ | 117 | (Opts.headerDoc (Just (getHeader header)) <> | ^^^^^^^^^^^^^^^^ src/Turtle/Options.hs:118:40: error: • Couldn't match type ‘Doc’ with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’ Expected: Options.Applicative.Help.Pretty.Doc Actual: Doc NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’ is defined in ‘Prettyprinter.Internal’ in package ‘prettyprinter-1.7.1’ ‘Doc’ is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’ in package ‘ansi-wl-pprint-0.6.9’ • In the first argument of ‘Just’, namely ‘(getFooter footer)’ In the first argument of ‘Opts.footerDoc’, namely ‘(Just (getFooter footer))’ In the first argument of ‘(<>)’, namely ‘Opts.footerDoc (Just (getFooter footer))’ | 118 | Opts.footerDoc (Just (getFooter footer)) <> | ^^^^^^^^^^^^^^^^ src/Turtle/Options.hs:119:42: error: • Couldn't match type ‘Doc’ with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’ Expected: Options.Applicative.Help.Pretty.Doc Actual: Doc NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’ is defined in ‘Prettyprinter.Internal’ in package ‘prettyprinter-1.7.1’ ‘Doc’ is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’ in package ‘ansi-wl-pprint-0.6.9’ • In the first argument of ‘Just’, namely ‘(getDescription desc)’ In the first argument of ‘Opts.progDescDoc’, namely ‘(Just (getDescription desc))’ In the second argument of ‘(<>)’, namely ‘Opts.progDescDoc (Just (getDescription desc))’ | 119 | Opts.progDescDoc (Just (getDescription desc))) | ^^^^^^^^^^^^^^^^^^^ src/Turtle/Options.hs:298:49: error: • Couldn't match type ‘Doc’ with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’ Expected: Options.Applicative.Help.Pretty.Doc Actual: Doc NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’ is defined in ‘Prettyprinter.Internal’ in package ‘prettyprinter-1.7.1’ ‘Doc’ is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’ in package ‘ansi-wl-pprint-0.6.9’ • In the first argument of ‘Just’, namely ‘(getDescription desc)’ In the first argument of ‘Opts.progDescDoc’, namely ‘(Just (getDescription desc))’ In the second argument of ‘Opts.info’, namely ‘(Opts.progDescDoc (Just (getDescription desc)))’ | 298 | info = Opts.info p (Opts.progDescDoc (Just (getDescription desc))) | ^^^^^^^^^^^^^^^^^^^ src/Turtle/Options.hs:309:51: error: • Couldn't match type ‘Doc’ with ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc prettyprinter-ansi-terminal-1.1.3:Prettyprinter.Render.Terminal.Internal.AnsiStyle’ Expected: Options.Applicative.Help.Pretty.Doc Actual: Doc NB: ‘prettyprinter-1.7.1:Prettyprinter.Internal.Doc’ is defined in ‘Prettyprinter.Internal’ in package ‘prettyprinter-1.7.1’ ‘Doc’ is defined in ‘Text.PrettyPrint.ANSI.Leijen.Internal’ in package ‘ansi-wl-pprint-0.6.9’ • In the first argument of ‘Just’, namely ‘(getDescription desc)’ In the first argument of ‘Opts.progDescDoc’, namely ‘(Just (getDescription desc))’ In the second argument of ‘Opts.info’, namely ‘(Opts.progDescDoc (Just (getDescription desc)))’ | 309 | (Opts.info p (Opts.progDescDoc (Just (getDescription desc)))) | ^^^^^^^^^^^^^^^^^^^ Error: cabal: Failed to build turtle-1.6.1. ```

In my case, adding --constraint='ansi-wl-pprint >= 1' did resolve the situation (note that the solver ended up chosing ansi-wl-pprint < 1 without any manual flag like in the reproducer above).

ysangkok commented 1 year ago

This might be a case for the Cabal team like e.g. @Mikolaj. I am not sure why Cabal tries the lower version of ansi-wl-pprint first. That seems odd when the newer version would work fine. Usually, when Cabal searches for versions, it starts with the highest one, at least judging from the error messages.

Mikolaj commented 1 year ago

That may be related to the fact that ansi-wl-pprint is not on Hackage, perhaps?

https://hackage.haskell.org/packages/search?terms=ansi-wl-pprint

E.g., if a package version is deprecated, cabal tries not to choose it when planning, but you can force it on commandline IIRC. Are there any deprecated versions around? Also, I'm quite surprised a package not on Hackage is solved for successfully. There must be some mechanism that permits that (or is the package hidden from the UI?). If you discover what it is, I'd be glad to learn.

amesgen commented 1 year ago

It is on Hackage, but as it is marked as deprecated as a whole (but all individual versions are not deprecated), it does not show up in the search: https://hackage.haskell.org/package/ansi-wl-pprint

Mikolaj commented 1 year ago

Oh, I see, thank you. I have no idea how cabal works with wholly deprecated package, but it should not pick a random version, for sure. Please feel free to open a cabal ticket, since this may indeed be a buggy corner case.

ysangkok commented 1 year ago

I have submitted #447, which I believe would address the problem. Please try it out @amesgen and @michaelpj .

amesgen commented 1 year ago

Thanks! BTW, I now understand why this occurs: I am running a cabal script in a Nix shell where ansi-wl-pprint-0.6.9 is preinstalled, and the Cabal solver always first tries to find a plan that includes installed packages, which is possible ATM, but will no longer be with #447.