From 87a6cc2d24b1a08b07373f5155b6819257d7f393 Mon Sep 17 00:00:00 2001 From: Luca BRUNO Date: Wed, 18 Sep 2024 14:48:21 +0200 Subject: [PATCH] Use a single buffer for hints on resolver errors This changes the structure of the hints generator in the resolver when encountering solution errors, so that it re-uses a single output buffer owned by the caller. It avoids repeated allocations of a temporary buffer within each recursive function call. --- crates/uv-resolver/src/error.rs | 8 +++++-- crates/uv-resolver/src/pubgrub/report.rs | 30 ++++++++++++++---------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/crates/uv-resolver/src/error.rs b/crates/uv-resolver/src/error.rs index 4a38e3e303c6..af3e72715a88 100644 --- a/crates/uv-resolver/src/error.rs +++ b/crates/uv-resolver/src/error.rs @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::fmt::Formatter; use std::sync::Arc; +use indexmap::IndexSet; use pubgrub::{DefaultStringReporter, DerivationTree, Derived, External, Range, Reporter}; use rustc_hash::FxHashMap; @@ -248,7 +249,8 @@ impl std::fmt::Display for NoSolutionError { write!(f, "{report}")?; // Include any additional hints. - for hint in formatter.hints( + let mut additional_hints = IndexSet::default(); + formatter.generate_hints( &self.error, &self.selector, &self.index_locations, @@ -256,7 +258,9 @@ impl std::fmt::Display for NoSolutionError { &self.incomplete_packages, &self.fork_urls, &self.markers, - ) { + &mut additional_hints, + ); + for hint in additional_hints { write!(f, "\n\n{hint}")?; } diff --git a/crates/uv-resolver/src/pubgrub/report.rs b/crates/uv-resolver/src/pubgrub/report.rs index 7e96ed0e80af..386ca0d40fc7 100644 --- a/crates/uv-resolver/src/pubgrub/report.rs +++ b/crates/uv-resolver/src/pubgrub/report.rs @@ -499,7 +499,7 @@ impl PubGrubReportFormatter<'_> { /// /// The [`PubGrubHints`] help users resolve errors by providing additional context or modifying /// their requirements. - pub(crate) fn hints( + pub(crate) fn generate_hints( &self, derivation_tree: &ErrorTree, selector: &CandidateSelector, @@ -508,8 +508,8 @@ impl PubGrubReportFormatter<'_> { incomplete_packages: &FxHashMap>, fork_urls: &ForkUrls, markers: &ResolverMarkers, - ) -> IndexSet { - let mut hints = IndexSet::default(); + output_hints: &mut IndexSet, + ) { match derivation_tree { DerivationTree::External( External::Custom(package, set, _) | External::NoVersions(package, set), @@ -518,7 +518,12 @@ impl PubGrubReportFormatter<'_> { // Check for no versions due to pre-release options. if !fork_urls.contains_key(name) { self.prerelease_available_hint( - package, name, set, selector, markers, &mut hints, + package, + name, + set, + selector, + markers, + output_hints, ); } } @@ -532,7 +537,7 @@ impl PubGrubReportFormatter<'_> { index_locations, unavailable_packages, incomplete_packages, - &mut hints, + output_hints, ); } } @@ -547,7 +552,7 @@ impl PubGrubReportFormatter<'_> { &**dependency, PubGrubPackageInner::Python(PubGrubPython::Target) ) { - hints.insert(PubGrubHint::RequiresPython { + output_hints.insert(PubGrubHint::RequiresPython { source: self.python_requirement.source(), requires_python: self.python_requirement.target().clone(), package: package.clone(), @@ -558,7 +563,7 @@ impl PubGrubReportFormatter<'_> { } DerivationTree::External(External::NotRoot(..)) => {} DerivationTree::Derived(derived) => { - hints.extend(self.hints( + self.generate_hints( &derived.cause1, selector, index_locations, @@ -566,8 +571,9 @@ impl PubGrubReportFormatter<'_> { incomplete_packages, fork_urls, markers, - )); - hints.extend(self.hints( + output_hints, + ); + self.generate_hints( &derived.cause2, selector, index_locations, @@ -575,10 +581,10 @@ impl PubGrubReportFormatter<'_> { incomplete_packages, fork_urls, markers, - )); + output_hints, + ); } - } - hints + }; } fn index_hints(