uv-resolver: add support for incomplete markers

In some cases, it's possible for the marker expressions on conflicting
dependency specification to be disjoint but *incomplete*. That is, if
one unions the disjoint markers, the result is not the complete set of
marker environments possible. There may be some "gap" of marker
environments not covered by the markers.

This is a problem in practice because, before this commit, we only
created forks in the resolver for specific marker expressions. So if a
dependency happened to fall in a "gap," our resolver would never see it.

This commit fixes this by adding a new split covering the negation of
the union of all marker expressions in a set of forks for a specific
package.

Originally, I had planned on only creating this split when it was known
that the gap actually existed. That is, when the negation of the marker
expressions did *not* correspond to the empty set. After a lot of
thought, unfortunately, this (I believe) effectively boils down to 3SAT,
which is NP-complete.

Instead, what we do here is *always* create an extra split unless we can
definitively tell that it is empty. We look for a few cases, but
otherwise throw our hands up and potentially do wasted work.

This also updates the lock scenario tests to reflect the actual bug fix
here.
This commit is contained in:
Andrew Gallant 2024-07-12 11:55:40 -04:00 committed by Andrew Gallant
parent f36f2f41ac
commit 563507edba
4 changed files with 122 additions and 1 deletions

View file

@ -2515,6 +2515,12 @@ mod test {
neg("os_name == 'bar' or os_name == 'foo'"),
"os_name != 'bar' and os_name != 'foo'"
);
// Always true negates to always false!
assert_eq!(
neg("python_version >= '3.6' or python_version < '3.6'"),
"python_version < '3.6' and python_version >= '3.6'"
);
}
#[test]