Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix redundant enumeration of all package versions in some resolver errors #9885

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions crates/uv-resolver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ impl std::fmt::Display for NoSolutionError {
}

collapse_unavailable_versions(&mut tree);
collapse_redundant_no_versions(&mut tree);
collapse_redundant_depends_on_no_versions(&mut tree);

if should_display_tree {
Expand Down Expand Up @@ -427,6 +428,62 @@ fn display_tree_inner(
}
}

fn collapse_redundant_no_versions(
tree: &mut DerivationTree<PubGrubPackage, Range<Version>, UnavailableReason>,
) {
match tree {
DerivationTree::External(_) => {}
DerivationTree::Derived(derived) => {
match (
Arc::make_mut(&mut derived.cause1),
Arc::make_mut(&mut derived.cause2),
) {
// If we have a node for a package with no versions...
(
DerivationTree::External(External::NoVersions(package, versions)),
ref mut other,
)
| (
ref mut other,
DerivationTree::External(External::NoVersions(package, versions)),
) => {
// First, always recursively visit the other side of the tree
collapse_redundant_no_versions(other);

let DerivationTree::Derived(derived) = other else {
return;
};

// If the range in the conclusion (terms) matches the range of no versions,
// then we'll drop this node
let Some(Term::Positive(term)) = derived.terms.get(package) else {
return;
};
let versions = versions.complement();

// If we're disqualifying a single version, this is important to retain, e.g,
// for `only foo==1.0.0 is available`
if versions.as_singleton().is_some() {
return;
}

if *term != versions {
return;
}

// Replace this node with the other tree
*tree = other.clone();
}
// If not, just recurse
_ => {
collapse_redundant_no_versions(Arc::make_mut(&mut derived.cause1));
collapse_redundant_no_versions(Arc::make_mut(&mut derived.cause2));
}
}
}
}
}

/// Given a [`DerivationTree`], collapse any `NoVersion` incompatibilities for workspace members
/// to avoid saying things like "only <workspace-member>==0.1.0 is available".
fn collapse_no_versions_of_workspace_members(
Expand Down
11 changes: 1 addition & 10 deletions crates/uv/tests/it/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13126,16 +13126,7 @@ fn compile_enumerate_no_versions() -> Result<()> {
----- stderr -----
× No solution found when resolving dependencies:
╰─▶ Because the current Python version (3.10.[X]) 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.
And because only the following versions of rooster-blue are available:
rooster-blue==0.0.1
rooster-blue==0.0.2
rooster-blue==0.0.3
rooster-blue==0.0.4
rooster-blue==0.0.5
rooster-blue==0.0.6
rooster-blue==0.0.7
rooster-blue==0.0.8
and you require rooster-blue, we can conclude that your requirements are unsatisfiable.
And because you require rooster-blue, we can conclude that your requirements are unsatisfiable.
"###);

Ok(())
Expand Down
Loading