pubgrub-rs / pubgrub

PubGrub version solving algorithm implemented in Rust
https://pubgrub-rs.github.io/pubgrub/pubgrub/
Mozilla Public License 2.0
337 stars 30 forks source link

Why do error messages start with no version? #155

Open Eh2406 opened 7 months ago

Eh2406 commented 7 months ago

I was looking at the error message created by the test case for #135. The case I was looking at was:

    let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();

    // root depends on foo...
    dependency_provider.add_dependencies("root", 1, vec![("foo", Range::full())]);

    for i in 1..6 {
        // foo depends on bar...
        dependency_provider.add_dependencies("foo", i as u32, vec![("bar", Range::full())]);
    }

which gives the error message:

Because there is no available version for bar and foo 1 depends on bar, foo 1 is forbidden.
And because there is no version of foo in <1 | >1, <2 | >2, <3 | >3, <4 | >4, <5 | >5, foo <2 | >2, <3 | >3, <4 | >4, <5 | >5 is forbidden. (1)

Because there is no available version for bar and foo 2 depends on bar, foo 2 is forbidden.
And because foo <2 | >2, <3 | >3, <4 | >4, <5 | >5 is forbidden (1), foo <3 | >3, <4 | >4, <5 | >5 is forbidden. (2)

Because there is no available version for bar and foo 3 depends on bar, foo 3 is forbidden.
And because foo <3 | >3, <4 | >4, <5 | >5 is forbidden (2), foo <4 | >4, <5 | >5 is forbidden. (3)

Because there is no available version for bar and foo 4 depends on bar, foo 4 is forbidden.
And because foo <4 | >4, <5 | >5 is forbidden (3), foo <5 | >5 is forbidden. (4)

Because there is no available version for bar and foo 5 depends on bar, foo 5 is forbidden.
And because foo <5 | >5 is forbidden (4), foo * is forbidden.
And because root 1 depends on foo, root 1 is forbidden.

The logical argument made by the current error message is correct, it's just confusing to my meat brain. The second point in the argument is that there is no version of foo in <1 | >1, <2 | >2, <3 | >3, <4 | >4, <5 | >5. Which is correct, but the error messages give me know context for why I would be interested in this range with all the holes in it. The actual answer is the each of those holes is going to be filled in by a argument further down, but I haven't read ahead to find that out yet. It seems like the argument would be much clearer if it started by the versions that it tried, and then explained that there were no versions left in the gaps. Something like:

Because there is no available version for bar and foo 5 depends on bar, foo 5 is forbidden. (1)

Because there is no available version for bar and foo 4 depends on bar, foo 4 is forbidden.
And because foo 5 is forbidden (1), foo 4 | 5 is forbidden. (2)

Because there is no available version for bar and foo 3 depends on bar, foo 3 is forbidden.
And because foo 4 | 5 is forbidden (2), foo 3 | 4 | 5 is forbidden. (3)

Because there is no available version for bar and foo 2 depends on bar, foo 2 is forbidden.
And because foo 3 | 4 | 5 is forbidden (3), foo 2 | 3 | 4 | 5 is forbidden. (4)

Because there is no available version for bar and foo 1 depends on bar, foo 1 is forbidden.
And because foo 2 | 3 | 4 | 5 is forbidden (4), foo 1 | 2 | 3 | 4 | 5 is forbidden.
And because there is no version of foo in <1 | >1, <2 | >2, <3 | >3, <4 | >4, <5 | >5 and root 1 depends on foo, root 1 is forbidden.

The change in order somewhat accidentally comes from https://github.com/pubgrub-rs/pubgrub/tree/slow_135

mpizenberg commented 7 months ago

I don't remember how the tree is generated so I won't be of much help.