Skip to content

Commit

Permalink
Return NoSolutionError from unit propagation (#28)
Browse files Browse the repository at this point in the history
In uv, the only pubgrub error that can occur is a `NoSolutionError`, and
the only place it can occur is `unit_propagation`. By returning
`NoSolutionError` instead of `PubGrubError`, we can remove
`unreachable!()` calls on uv's side. `NoSolutionError` is a type alias
for `DerivationTree`.
  • Loading branch information
konstin authored Jul 15, 2024
1 parent b4435e2 commit 3f0ba76
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
22 changes: 16 additions & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ use thiserror::Error;
use crate::report::DerivationTree;
use crate::solver::DependencyProvider;

/// There is no solution for this set of dependencies.
pub type NoSolutionError<DP> = DerivationTree<
<DP as DependencyProvider>::P,
<DP as DependencyProvider>::VS,
<DP as DependencyProvider>::M,
>;

/// Errors that may occur while solving dependencies.
#[derive(Error)]
pub enum PubGrubError<DP>
where
DP: DependencyProvider,
{
pub enum PubGrubError<DP: DependencyProvider> {
/// There is no solution for this set of dependencies.
#[error("No solution")]
NoSolution(DerivationTree<DP::P, DP::VS, DP::M>),
NoSolution(NoSolutionError<DP>),

/// Error arising when the implementer of
/// [DependencyProvider]
Expand Down Expand Up @@ -62,13 +66,19 @@ where
Failure(String),
}

impl<DP: DependencyProvider> From<NoSolutionError<DP>> for PubGrubError<DP> {
fn from(err: NoSolutionError<DP>) -> Self {
Self::NoSolution(err)
}
}

impl<DP> std::fmt::Debug for PubGrubError<DP>
where
DP: DependencyProvider,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoSolution(arg0) => f.debug_tuple("NoSolution").field(arg0).finish(),
Self::NoSolution(err) => f.debug_tuple("NoSolution").field(&err).finish(),
Self::ErrorRetrievingDependencies {
package,
version,
Expand Down
10 changes: 4 additions & 6 deletions src/internal/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use std::collections::HashSet as Set;
use std::sync::Arc;

use crate::error::PubGrubError;
use crate::error::NoSolutionError;
use crate::internal::arena::Arena;
use crate::internal::incompatibility::{Incompatibility, Relation};
use crate::internal::partial_solution::SatisfierSearch::{
Expand Down Expand Up @@ -126,7 +126,7 @@ impl<DP: DependencyProvider> State<DP> {

/// Unit propagation is the core mechanism of the solving algorithm.
/// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
pub fn unit_propagation(&mut self, package: DP::P) -> Result<(), PubGrubError<DP>> {
pub fn unit_propagation(&mut self, package: DP::P) -> Result<(), NoSolutionError<DP>> {
self.unit_propagation_buffer.clear();
self.unit_propagation_buffer.push(package);
while let Some(current_package) = self.unit_propagation_buffer.pop() {
Expand Down Expand Up @@ -205,16 +205,14 @@ impl<DP: DependencyProvider> State<DP> {
fn conflict_resolution(
&mut self,
incompatibility: IncompDpId<DP>,
) -> Result<(DP::P, IncompDpId<DP>), PubGrubError<DP>> {
) -> Result<(DP::P, IncompDpId<DP>), NoSolutionError<DP>> {
let mut current_incompat_id = incompatibility;
let mut current_incompat_changed = false;
loop {
if self.incompatibility_store[current_incompat_id]
.is_terminal(&self.root_package, &self.root_version)
{
return Err(PubGrubError::NoSolution(
self.build_derivation_tree(current_incompat_id),
));
return Err(self.build_derivation_tree(current_incompat_id));
} else {
let (package, satisfier_search_result) = self.partial_solution.satisfier_search(
&self.incompatibility_store[current_incompat_id],
Expand Down

0 comments on commit 3f0ba76

Please sign in to comment.