Skip to content

Commit c2059ee

Browse files
committed
Fix redundant enumeration of all package versions in some resolver errors
1 parent 16e5bd7 commit c2059ee

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

crates/uv-resolver/src/error.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ impl std::fmt::Display for NoSolutionError {
336336
}
337337

338338
collapse_unavailable_versions(&mut tree);
339+
collapse_redundant_no_versions(&mut tree);
339340
collapse_redundant_depends_on_no_versions(&mut tree);
340341

341342
if should_display_tree {
@@ -422,6 +423,62 @@ fn display_tree_inner(
422423
}
423424
}
424425

426+
fn collapse_redundant_no_versions(
427+
tree: &mut DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>,
428+
) {
429+
match tree {
430+
DerivationTree::External(_) => {}
431+
DerivationTree::Derived(derived) => {
432+
match (
433+
Arc::make_mut(&mut derived.cause1),
434+
Arc::make_mut(&mut derived.cause2),
435+
) {
436+
// If we have a node for a package with no versions...
437+
(
438+
DerivationTree::External(External::NoVersions(package, versions)),
439+
ref mut other,
440+
)
441+
| (
442+
ref mut other,
443+
DerivationTree::External(External::NoVersions(package, versions)),
444+
) => {
445+
// First, always recursively visit the other side of the tree
446+
collapse_redundant_no_versions(other);
447+
448+
let DerivationTree::Derived(derived) = other else {
449+
return;
450+
};
451+
452+
// If the range in the conclusion (terms) matches the range of no versions,
453+
// then we'll drop this node
454+
let Some(Term::Positive(term)) = derived.terms.get(package) else {
455+
return;
456+
};
457+
let versions = versions.complement();
458+
459+
// If we're disqualifying a single version, this is important to retain, e.g,
460+
// for `only foo==1.0.0 is available`
461+
if versions.as_singleton().is_some() {
462+
return;
463+
}
464+
465+
if *term != versions {
466+
return;
467+
}
468+
469+
// Replace this node with the other tree
470+
*tree = other.clone();
471+
}
472+
// If not, just recurse
473+
_ => {
474+
collapse_redundant_no_versions(Arc::make_mut(&mut derived.cause1));
475+
collapse_redundant_no_versions(Arc::make_mut(&mut derived.cause2));
476+
}
477+
}
478+
}
479+
}
480+
}
481+
425482
/// Given a [`DerivationTree`], collapse any `NoVersion` incompatibilities for workspace members
426483
/// to avoid saying things like "only <workspace-member>==0.1.0 is available".
427484
fn collapse_no_versions_of_workspace_members(

crates/uv/tests/it/pip_compile.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13123,16 +13123,7 @@ fn compile_enumerate_no_versions() -> Result<()> {
1312313123
----- stderr -----
1312413124
× No solution found when resolving dependencies:
1312513125
╰─▶ Because the current Python version (3.10.15) does not satisfy Python>=3.11,<4.0 and all versions of rooster-blue depend on Python>=3.11,<4.0, we can conclude that all versions of rooster-blue cannot be used.
13126-
And because only the following versions of rooster-blue are available:
13127-
rooster-blue==0.0.1
13128-
rooster-blue==0.0.2
13129-
rooster-blue==0.0.3
13130-
rooster-blue==0.0.4
13131-
rooster-blue==0.0.5
13132-
rooster-blue==0.0.6
13133-
rooster-blue==0.0.7
13134-
rooster-blue==0.0.8
13135-
and you require rooster-blue, we can conclude that your requirements are unsatisfiable.
13126+
And because you require rooster-blue, we can conclude that your requirements are unsatisfiable.
1313613127
"###);
1313713128

1313813129
Ok(())

0 commit comments

Comments
 (0)