From c25306cddca2e40268dc3705a51247a981cf85e9 Mon Sep 17 00:00:00 2001 From: konstin Date: Mon, 15 Jul 2024 12:19:05 +0200 Subject: [PATCH] Return `NoSolutionError` from unit propagation 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`. --- src/error.rs | 22 ++++++++++++++++------ src/internal/core.rs | 10 ++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/error.rs b/src/error.rs index b4921f32..9306e16f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -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 = DerivationTree< + ::P, + ::VS, + ::M, +>; + /// Errors that may occur while solving dependencies. #[derive(Error)] -pub enum PubGrubError -where - DP: DependencyProvider, -{ +pub enum PubGrubError { /// There is no solution for this set of dependencies. #[error("No solution")] - NoSolution(DerivationTree), + NoSolution(NoSolutionError), /// Error arising when the implementer of /// [DependencyProvider] @@ -62,13 +66,19 @@ where Failure(String), } +impl From> for PubGrubError { + fn from(err: NoSolutionError) -> Self { + Self::NoSolution(err) + } +} + impl std::fmt::Debug for PubGrubError 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, diff --git a/src/internal/core.rs b/src/internal/core.rs index 40587b1a..42acc1e5 100644 --- a/src/internal/core.rs +++ b/src/internal/core.rs @@ -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::{ @@ -126,7 +126,7 @@ impl State { /// Unit propagation is the core mechanism of the solving algorithm. /// CF - pub fn unit_propagation(&mut self, package: DP::P) -> Result<(), PubGrubError> { + pub fn unit_propagation(&mut self, package: DP::P) -> Result<(), NoSolutionError> { self.unit_propagation_buffer.clear(); self.unit_propagation_buffer.push(package); while let Some(current_package) = self.unit_propagation_buffer.pop() { @@ -205,16 +205,14 @@ impl State { fn conflict_resolution( &mut self, incompatibility: IncompDpId, - ) -> Result<(DP::P, IncompDpId), PubGrubError> { + ) -> Result<(DP::P, IncompDpId), NoSolutionError> { 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],