Description
Currently the solver does not try to do anything clever when there are cyclic dependencies in the package dependency graph. For example, if A depends on B and B depends on A, and we solve for A, the solver will simply return that we need to install A and B; cabal
will then subsequently fail with an internal error about in invalid install plan. Not great, but not a major problem either.
However, the problem gets worse when we have setup dependencies (or other kinds of qualified dependencies). Suppose package C has a setup dependency on D, and D depends (normally) on C, and we solve for C. Now the solver starts adding an infinite number goals:
C
C-setup.D
(*) C-setup.C
C-setup.C-setup.D
C-setup.C-setup.C
C-setup.C-setup.C-setup.D
...
and so calling, say, cabal new-build
will not terminate.
This might seem like a contrived situation, but it is not. To see how this might arise in practice, consider:
unbounded-delays
has a setup dependency onCabal
(at least, it does when using thenew-build
command;unbounded-delays
has a custom setup script without an explicit declaration of setup dependencies, sonew-build
adds an implicit setup dependency onCabal
)Cabal
, with the flag+tests
enabled, has a regular dependency ontasty
tasty
has a regular dependency on, you guessed it,unbounded-delays
Of course, the solver should instead pick Cabal -tests
, but it it picks + tests
first, it will go down an infinite path and never return; it won't notice that this solution cannot lead anywhere.
I'm working on a solution to this problem, and will hopefully submit a PR, but submitting the issue now so that you are aware that there is a problem.
By the by: The line marked (*)
looks odd, but it's morally correct; compare to the goals that we would get if D instead relied on E, which would have a setup dependency on F:
C
C-setup.D
(**) C-setup.E
(***) C-setup.E-setup.F
Line (**)
means that the version we pick for E when building C's setup script is independent of the version we pick elsewhere in the solution, which is correct. Similarly, line (***)
says that the version of F that we pick to build E's setup script, for the version of E that we we use to build C's setup script, is independent from all other uses of F.