mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-02 15:01:16 +00:00
uv-resolver: fix bug in marker disjointness checking
I found this while testing the tracking of marker expressions across resolver forks. Namely, given sys_platform == 'darwin' and implementation_name == 'pypy' And: sys_platform == 'bar' or implementation_name == 'foo' These should be disjoint, but the disjointness checker was reporting them as overlapping. I fixed this by giving handling of disjunctions higher precedence than conjunctions, although I am not 100% confident that this is correct for all cases.
This commit is contained in:
parent
407f1e370b
commit
dbb12bcfe4
1 changed files with 13 additions and 4 deletions
|
@ -18,14 +18,14 @@ use pubgrub::range::Range as PubGrubRange;
|
||||||
pub(crate) fn is_disjoint(first: &MarkerTree, second: &MarkerTree) -> bool {
|
pub(crate) fn is_disjoint(first: &MarkerTree, second: &MarkerTree) -> bool {
|
||||||
let (expr1, expr2) = match (first, second) {
|
let (expr1, expr2) = match (first, second) {
|
||||||
(MarkerTree::Expression(expr1), MarkerTree::Expression(expr2)) => (expr1, expr2),
|
(MarkerTree::Expression(expr1), MarkerTree::Expression(expr2)) => (expr1, expr2),
|
||||||
// `And` expressions are disjoint if any clause is disjoint.
|
|
||||||
(other, MarkerTree::And(exprs)) | (MarkerTree::And(exprs), other) => {
|
|
||||||
return exprs.iter().any(|tree1| is_disjoint(tree1, other))
|
|
||||||
}
|
|
||||||
// `Or` expressions are disjoint if all clauses are disjoint.
|
// `Or` expressions are disjoint if all clauses are disjoint.
|
||||||
(other, MarkerTree::Or(exprs)) | (MarkerTree::Or(exprs), other) => {
|
(other, MarkerTree::Or(exprs)) | (MarkerTree::Or(exprs), other) => {
|
||||||
return exprs.iter().all(|tree1| is_disjoint(tree1, other))
|
return exprs.iter().all(|tree1| is_disjoint(tree1, other))
|
||||||
}
|
}
|
||||||
|
// `And` expressions are disjoint if any clause is disjoint.
|
||||||
|
(other, MarkerTree::And(exprs)) | (MarkerTree::And(exprs), other) => {
|
||||||
|
return exprs.iter().any(|tree1| is_disjoint(tree1, other));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match (expr1, expr2) {
|
match (expr1, expr2) {
|
||||||
|
@ -529,6 +529,15 @@ mod tests {
|
||||||
"os_name == 'a' or platform_version == '1'",
|
"os_name == 'a' or platform_version == '1'",
|
||||||
"os_name == 'a' or platform_version == '2'"
|
"os_name == 'a' or platform_version == '2'"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
assert!(is_disjoint(
|
||||||
|
"sys_platform == 'darwin' and implementation_name == 'pypy'",
|
||||||
|
"sys_platform == 'bar' or implementation_name == 'foo'",
|
||||||
|
));
|
||||||
|
assert!(is_disjoint(
|
||||||
|
"sys_platform == 'bar' or implementation_name == 'foo'",
|
||||||
|
"sys_platform == 'darwin' and implementation_name == 'pypy'",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_version_bounds_disjointness(version: &str) {
|
fn test_version_bounds_disjointness(version: &str) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue