mpizenberg / elm-pubgrub

PubGrub version solving algorithm in elm
https://mpizenberg.github.io/elm-pubgrub/
BSD 3-Clause "New" or "Revised" License
6 stars 2 forks source link

Weird error report #9

Open mpizenberg opened 4 years ago

mpizenberg commented 4 years ago

Sometimes, the error reporting logic may not produce great results. I can add the examples in this thread.

Example 1:

Because foo 2.0.0 depends on bar 1.0.0 <= v < 2.0.0 and bar 1.0.0 <= v < 2.0.0 depends on foo 1.0.0 <= v < 2.0.0,  are incompatible.

This one is due to the following empty incompatibility:

Final incompatibility:
     <<<  derived from:
      foo: 2.0.0, bar: Not ( 1.0.0 <= v < 2.0.0 )  <<<  from dependency of foo at version 2.0.0
      bar: 1.0.0 <= v < 2.0.0, foo: Not ( 1.0.0 <= v < 2.0.0 )  <<<  from dependency of bar at version 1.0.0: ""

This is coming from an "offline" example where I did not provide the dependencies of foo 1.0.0:

    PubGrub.emptyCache
        -- Example performing conflict resolution
        -- https://github.com/dart-lang/pub/blob/master/doc/solver.md#performing-conflict-resolution
        |> PubGrub.cachePackageVersions
            [ ( "root", Version.one )
            , ( "foo", Version.one )
            , ( "foo", Version.two )
            , ( "bar", Version.one )
            ]
        |> PubGrub.cacheDependencies "root" Version.one [ ( "foo", Range.higherThan Version.one ) ]
        |> PubGrub.cacheDependencies "foo" Version.two [ ( "bar", Range.between Version.one Version.two ) ]
        -- |> PubGrub.cacheDependencies "foo" Version.one []
        |> PubGrub.cacheDependencies "bar" Version.one [ ( "foo", Range.between Version.one Version.two ) ]
        |> Init
mpizenberg commented 4 years ago

Now I have prevented the merge on "noVersion" incompatibilities and the same example still gives a weird result:

Final incompatibility:
     <<<  derived from:
(1)   foo: Not ( 1.0.0 <= v < 2.0.0 )  <<<  derived from:
         foo: 2.0.0, bar: Not ( 1.0.0 <= v < 2.0.0 )  <<<  from dependency of foo at version 2.0.0
         foo: Not ( 1.0.0 <= v < 2.0.0 ), bar: 1.0.0 <= v < 2.0.0  <<<  derived from:
            bar: 1.0.0, foo: Not ( 1.0.0 <= v < 2.0.0 )  <<<  from dependency of bar at version 1.0.0
            bar: 1.0.1 <= v < 2.0.0  <<<  no version
      foo: 1.0.0 <= v < 2.0.0  <<<  derived from:
         foo: 1.0.0  <<<  unavailable dependencies
         foo: 1.0.1 <= v < 2.0.0  <<<  no version: ""

The final incompatibility here is an empty one, which triggers a terminal case. But this happens because the top derivation here should have been foo not none and any term of this form is removed from the incompatibility to fix a previous bug (cf PR https://github.com/mpizenberg/elm-pubgrub/pull/5).

Now I'm wondering if the prior cause merging, consisting of union may not be correct. Here, the incompatibility in (1) should have been saying something like "foo 2 depends on foo 1 <= v < 2". But since an incompatibility can only contain one instance of a package (ranges are merged) this dependency cannot be expressed as an incompatibility, except directly saying "foo is forbidden" with something like foo any.

As regarding the final incompatibility, it is of the type foo not none but reduced to an empty incompatibility, where we lose the information that it is about the foo package. Maybe we should keep the not none terms in the incompatibilities but instead take this into account in the terminal cases of PubGrub algorithm to still successfully solve the example in PR #5.

PS: the incompatibility (1) is also available as a direct dependency of root, which would be clearer ...