-
Notifications
You must be signed in to change notification settings - Fork 696
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
Detect cycles in solver #3170
Detect cycles in solver #3170
Conversation
I reviewed the design of this with @edsko and looked at the core bit of the cycle detection code. We believe, but have not tested, that there is minimal performance impact since we only do the cycle detection when we would otherwise return an invalid solution, so in typical current cases this should happen at most once. Currently every place where the cycle check fails (which are the cases where it could go on to do more than one) the current solver just fails outright, which is not something we see often in practice. |
Build bot failures are due to missing import of |
and fix bug in qualityDeps
Imported |
Patches look good to me, but would be nice if @kosmikus could comment. |
Added Haddock comments as requested. |
|
||
type DetectCycles = Reader (ConflictSet QPN) | ||
|
||
-- | Find any reject any solutions that are cyclic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Find any reject any solutions that are cyclic
The first "any" should probably read "and".
@edsko Do you want this to go into 1.24 or do you think it can wait? |
@23Skidoo if I understand the issue correctly, this is needed to have |
I think it's quite important that this goes in, although it only addresses part of the problem. The other component is limiting the number of qualifiers. I won't have time to look at that until next week though, unfortunately. Maybe have a chat with @dcoutts, he's aware of the issues.
|
OK. Still would like to see a review from @kosmikus before merging, but it's probably not forthcoming. |
@23Skidoo Sorry. Will see what I can do. If there's no further comment from me until the end of the week, then it's unfortunately unlikely to happen the week after either ... But I'll try to have a look tomorrow. |
Given that the GHC 8 release has been delayed, 1.24 final won't be out until the end of this month most likely, so we have time. |
@23Skidoo I am going to merge this with minor modifications. Changes look good to me. I've also run a superficial test trying to install each package from Hackage on a clean package DB using ghc-7.10.3, and there seem to be no deviations in the results, and no significant deviations in the runtime or memory consumption. Note that in this test, there's most likely not a single case where cycles are actually detected, but at least this gives some amount of trust that we do not pay much for this in the common case. @dcoutts, @edsko In general, I think this PR could possibly be improved ever so slightly by not collecting what feels like redundant information just for the cycle check, but I'm not going to block this PR based on it. It's documented clearly enough, and seems minimally invasive to the rest, so I think it should hopefully be a clear relative improvement. |
@kosmikus Great, thanks! |
Also cherry-picked into 1.24. |
In #3170 we introduced a cycle check to the solver. This check is necessary to reject cycling solutions (which would previously have resulted in an internal error when we verify the install plan). However, this by itself is not sufficient. If we have a cycle through setup dependencies, the solver loops because it starts building an infinite tree. This is explained in detail in In this commit we just add some unit tests that provide a minimal example that exposes the bug.
In #3170 we introduced a cycle check to the solver. This check is necessary to reject cycling solutions (which would previously have resulted in an internal error when we verify the install plan). However, this by itself is not sufficient. If we have a cycle through setup dependencies, the solver loops because it starts building an infinite tree. This is explained in detail in In this commit we just add some unit tests that provide a minimal example that exposes the bug. (cherry picked from commit 37978a6)
(Only one commit in this PR; the first commit is really #3167.)
The solver currently does not attempt to detect cyclic solutions; for instance, if we have a package DB where A depends on B and B depends on A, the solver will happily return a "solution" where A and B are both installed; this will then subsequently lead to an internal error when we verify the derived install plan.
This wasn't a major deal until now because the package DB should not really contain cycles in the first place. However, as part of the work on qualified goals, this is becoming increasingly important. Even if we limit the number of qualifiers (#3160), if we want to allow a solution where, say (#1575)
it is important that the solver rejects a truly cyclic solution; but for that to work, it needs to be able to spot that it found a solution and try and come up with a different solution.
This PR adds another pass to the solver to detect and reject cycles (and construct the appropriate conflict set to make sure that when the solver backjumps it is able to make different choices that could potentially break the cycle). Since the cycle check is relatively expensive (linear in the size of the solution), we do this only once we have found a solution. This means that for most use cases the performance should not really be affected; after all, right now if the solver would have found a solution we would then result in internal error.
The PR also adds a few tests:
This PR is an important step towards solving #3160.