Skip to content

Commit

Permalink
Hacks
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jul 23, 2024
1 parent 37a6761 commit 1814580
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 132 deletions.
6 changes: 6 additions & 0 deletions src/internal/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ impl<T> fmt::Debug for Id<T> {
}
}

impl<T> fmt::Display for Id<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.raw)
}
}

impl<T> Id<T> {
pub fn into_raw(self) -> usize {
self.raw as usize
Expand Down
11 changes: 4 additions & 7 deletions src/internal/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,14 @@ impl<DP: DependencyProvider> State<DP> {
/// Add the dependencies for the current version of the current package as incompatibilities.
pub fn add_package_version_dependencies(
&mut self,
package: DP::P,
package: Id<DP::P>,
version: DP::V,
dependencies: impl IntoIterator<Item = (DP::P, DP::VS)>,
) {
let dep_incompats = self.add_incompatibility_from_dependencies(
package.clone(),
version.clone(),
dependencies,
);
let dep_incompats =
self.add_incompatibility_from_dependencies(package, version.clone(), dependencies);
self.partial_solution.add_package_version_incompatibilities(
package.clone(),
package,
version.clone(),
dep_incompats,
&self.incompatibility_store,
Expand Down
8 changes: 4 additions & 4 deletions src/internal/partial_solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
}
}

pub fn prioritized_packages(&self) -> impl Iterator<Item = (&DP::P, &DP::VS)> {
pub fn prioritized_packages(&self) -> impl Iterator<Item = (Id<DP::P>, &DP::VS)> {
let check_all = self.changed_this_decision_level
== self.current_decision_level.0.saturating_sub(1) as usize;
let current_decision_level = self.current_decision_level;
Expand All @@ -278,7 +278,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
// or if we backtracked in the mean time.
check_all || pa.highest_decision_level == current_decision_level
})
.filter_map(|(p, pa)| pa.assignments_intersection.potential_package_filter(p))
.filter_map(|(&p, pa)| pa.assignments_intersection.potential_package_filter(p))
}

pub fn pick_highest_priority_pkg(
Expand Down Expand Up @@ -391,11 +391,11 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
// Check none of the dependencies (new_incompatibilities)
// would create a conflict (be satisfied).
if store[new_incompatibilities].iter().all(not_satisfied) {
log::info!("add_decision: {:?} @ {}", package, version);
log::info!("add_decision: {} @ {}", package, version);
self.add_decision(package, version);
} else {
log::info!(
"not adding {:?} @ {} because of its dependencies",
"not adding {} @ {} because of its dependencies",
package,
version
);
Expand Down
124 changes: 3 additions & 121 deletions src/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,135 +62,17 @@
//! If there is no solution, the reason will be provided as clear as possible.
use std::cmp::Reverse;
use std::collections::{BTreeMap, BTreeSet as Set};
use std::collections::BTreeMap;
use std::convert::Infallible;
use std::error::Error;
use std::fmt::{Debug, Display};

use crate::error::PubGrubError;
pub use crate::internal::arena::Id;
pub use crate::internal::core::State;
pub use crate::internal::incompatibility::{Incompatibility, Kind};
use crate::internal::arena::Id;
use crate::package::Package;
use crate::type_aliases::{DependencyConstraints, Map, SelectedDependencies};
use crate::type_aliases::{DependencyConstraints, Map};
use crate::version_set::VersionSet;
use log::{debug, info};

/// Main function of the library.
/// Finds a set of packages satisfying dependency bounds for a given package + version pair.
pub fn resolve<DP: DependencyProvider>(
dependency_provider: &DP,
package: DP::P,
version: impl Into<DP::V>,
) -> Result<SelectedDependencies<DP>, PubGrubError<DP>> {
let mut state: State<DP> = State::init(package.clone(), version.into());
let mut added_dependencies: Map<Id<DP::P>, Set<DP::V>> = Map::default();
let mut next = state.root_package;
loop {
dependency_provider
.should_cancel()
.map_err(|err| PubGrubError::ErrorInShouldCancel(err))?;

info!("unit_propagation: {:?}", &next);
state.unit_propagation(next)?;

debug!(
"Partial solution after unit propagation: {}",
state.partial_solution
);

let Some(highest_priority_pkg) =
state.partial_solution.pick_highest_priority_pkg(|p, r| {
dependency_provider.prioritize(&state.package_store[p], r)
})
else {
return Ok(state
.partial_solution
.extract_solution()
.map(|(p, v)| (state.package_store[p].clone(), v))
.collect());
};
next = highest_priority_pkg;

let term_intersection = state
.partial_solution
.term_intersection_for_package(next)
.ok_or_else(|| {
PubGrubError::Failure("a package was chosen but we don't have a term.".into())
})?;
let decision = dependency_provider
.choose_version(
&state.package_store[next],
term_intersection.unwrap_positive(),
)
.map_err(PubGrubError::ErrorChoosingPackageVersion)?;
info!("DP chose: {:?} @ {:?}", next, decision);

// Pick the next compatible version.
let v = match decision {
None => {
let inc = Incompatibility::no_versions(next, term_intersection.clone());
state.add_incompatibility(inc);
continue;
}
Some(x) => x,
};

if !term_intersection.contains(&v) {
return Err(PubGrubError::Failure(
"choose_package_version picked an incompatible version".into(),
));
}

let is_new_dependency = added_dependencies
.entry(next)
.or_default()
.insert(v.clone());

if is_new_dependency {
// Retrieve that package dependencies.
let p = next;
let dependencies = dependency_provider
.get_dependencies(&state.package_store[p], &v)
.map_err(|err| PubGrubError::ErrorRetrievingDependencies {
package: state.package_store[p].clone(),
version: v.clone(),
source: err,
})?;

let dependencies = match dependencies {
Dependencies::Unavailable(reason) => {
state.add_incompatibility(Incompatibility::custom_version(
p,
v.clone(),
reason,
));
continue;
}
Dependencies::Available(x) if x.contains_key(&state.package_store[p]) => {
return Err(PubGrubError::SelfDependency {
package: state.package_store[p].clone(),
version: v,
});
}
Dependencies::Available(x) => x,
};

// Add that package and version if the dependencies are not problematic.
let dep_incompats =
state.add_incompatibility_from_dependencies(p, v.clone(), dependencies);

state
.partial_solution
.add_version(p, v, dep_incompats, &state.incompatibility_store);
} else {
// `dep_incompats` are already in `incompatibilities` so we know there are not satisfied
// terms and can add the decision directly.
info!("add_decision (not first time): {:?} @ {}", &next, v);
state.partial_solution.add_decision(next, v);
}
}
}

/// An enum used by [DependencyProvider] that holds information about package dependencies.
/// For each [Package] there is a set of versions allowed as a dependency.
Expand Down

0 comments on commit 1814580

Please sign in to comment.