mirror of https://github.com/astral-sh/uv
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
|
|
@ -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…
Reference in New Issue