Skip to content

Commit 8b75a11

Browse files
refactor: give consistent error messages for solver errors
Signed-off-by: Andrius Pukšta <andrius.puksta@sensmetry.com>
1 parent 69c7c33 commit 8b75a11

3 files changed

Lines changed: 58 additions & 70 deletions

File tree

core/src/solve/pubgrub.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: MIT OR Apache-2.0
33

44
use fluent_uri::Iri;
5-
use pubgrub::{DependencyProvider, VersionSet};
5+
use pubgrub::{DefaultStringReporter, DependencyProvider, Reporter, VersionSet};
66

77
use std::{
88
cell::RefCell,
@@ -307,23 +307,69 @@ fn compute_deps<R: ResolveRead>(
307307
Ok(pubgrub::Dependencies::Available(depmap))
308308
}
309309

310-
#[derive(Error, Debug)]
311-
#[error("{inner}")]
310+
#[derive(Debug)]
312311
pub struct SolverError<R: ResolveRead + fmt::Debug + 'static> {
313-
#[from]
314312
pub inner: Box<pubgrub::PubGrubError<ProjectSolver<R>>>,
315313
}
316314

315+
impl<R: ResolveRead + fmt::Debug + 'static> From<Box<pubgrub::PubGrubError<ProjectSolver<R>>>>
316+
for SolverError<R>
317+
{
318+
fn from(mut value: Box<pubgrub::PubGrubError<ProjectSolver<R>>>) -> Self {
319+
if let pubgrub::PubGrubError::NoSolution(ref mut derivation_tree) = *value {
320+
derivation_tree.collapse_no_versions();
321+
}
322+
Self { inner: value }
323+
}
324+
}
325+
317326
impl<R: ResolveRead + fmt::Debug + 'static> From<pubgrub::PubGrubError<ProjectSolver<R>>>
318327
for SolverError<R>
319328
{
320329
fn from(value: pubgrub::PubGrubError<ProjectSolver<R>>) -> Self {
321-
Self {
322-
inner: Box::new(value),
330+
Self::from(Box::new(value))
331+
}
332+
}
333+
334+
impl<R: ResolveRead + fmt::Debug + 'static> Display for SolverError<R> {
335+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336+
match self.inner.as_ref() {
337+
pubgrub::PubGrubError::NoSolution(derivation_tree) => {
338+
writeln!(
339+
f,
340+
"failed to satisfy usage constraints:\n{}",
341+
DefaultStringReporter::report(derivation_tree)
342+
)
343+
}
344+
pubgrub::PubGrubError::ErrorRetrievingDependencies {
345+
package, source, ..
346+
} => match package {
347+
DependencyIdentifier::Requested(_) => {
348+
write!(f, "failed to retrieve project(s): {source}")
349+
}
350+
DependencyIdentifier::Remote(iri) => {
351+
write!(f, "failed to retrieve `{iri}`: {source}")
352+
}
353+
},
354+
pubgrub::PubGrubError::ErrorChoosingVersion { package, source } => match package {
355+
DependencyIdentifier::Requested(_) => {
356+
// `fn choose_version()` is infallible in this path
357+
unreachable!();
358+
}
359+
DependencyIdentifier::Remote(iri) => {
360+
write!(f, "unable to select version of `{iri}`: {source}")
361+
}
362+
},
363+
pubgrub::PubGrubError::ErrorInShouldCancel(_) => {
364+
// ProjectSolver doesn't implement this and default impl does nothing
365+
unreachable!();
366+
}
323367
}
324368
}
325369
}
326370

371+
impl<R: ResolveRead + fmt::Debug + 'static> std::error::Error for SolverError<R> {}
372+
327373
#[derive(Error, Debug)]
328374
pub enum InternalSolverError<R: ResolveRead> {
329375
#[error("resolution error: {0}")]

sysand/src/commands/add.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ use sysand_core::{
1414
};
1515

1616
use crate::{
17-
CliError,
18-
cli::ResolutionOptions,
19-
command_sync,
20-
commands::lock::{create_resolver, handle_lock_error},
21-
read_lockfile,
17+
CliError, cli::ResolutionOptions, command_sync, commands::lock::create_resolver, read_lockfile,
2218
};
2319

2420
// TODO: Collect common arguments
@@ -74,8 +70,7 @@ pub fn command_add<S: AsRef<str>>(
7470
// Lock before adding to check if resource (and its required version)
7571
// can be found
7672
let usage = usage_raw.validate()?;
77-
let LockOutcome { lock, .. } =
78-
do_lock_extend(current_lock, [usage], resolver).map_err(handle_lock_error)?;
73+
let LockOutcome { lock, .. } = do_lock_extend(current_lock, [usage], resolver)?;
7974

8075
do_add(&mut current_project, usage_raw)?;
8176

sysand/src/commands/lock.rs

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,17 @@ use std::collections::HashMap;
55
use std::path::Path;
66
use std::sync::Arc;
77

8-
use anyhow::{Result, anyhow};
9-
use pubgrub::Reporter as _;
8+
use anyhow::Result;
109

1110
use sysand_core::{
12-
commands::lock::{
13-
DEFAULT_LOCKFILE_NAME, LockError, LockOutcome, LockProjectError, do_lock_local_editable,
14-
},
11+
commands::lock::{DEFAULT_LOCKFILE_NAME, LockOutcome, do_lock_local_editable},
1512
config::Config,
16-
project::{ProjectRead, memory::InMemoryProject, utils::wrapfs},
13+
project::{memory::InMemoryProject, utils::wrapfs},
1714
resolve::{
18-
ResolveRead,
1915
memory::{AcceptAll, MemoryResolver},
2016
priority::PriorityResolver,
2117
standard::{StandardResolver, standard_resolver},
2218
},
23-
solve::pubgrub::DependencyIdentifier,
2419
stdlib::known_std_libs,
2520
};
2621

@@ -56,13 +51,7 @@ pub fn command_lock<P: AsRef<Path>>(
5651
let LockOutcome {
5752
lock,
5853
dependencies: _dependencies,
59-
} = match do_lock_local_editable(&path, wrapped_resolver) {
60-
Ok(lock_outcome) => lock_outcome,
61-
Err(LockProjectError::LockError(lock_error)) => {
62-
return Err(handle_lock_error(lock_error));
63-
}
64-
Err(err) => Err(err)?,
65-
};
54+
} = do_lock_local_editable(&path, wrapped_resolver)?;
6655

6756
let canonical = lock.canonicalize();
6857
wrapfs::write(
@@ -128,45 +117,3 @@ pub fn create_resolver<P: AsRef<Path>>(
128117
);
129118
Ok(wrapped_resolver)
130119
}
131-
132-
pub fn handle_lock_error<PR: ProjectRead, RR: ResolveRead + std::fmt::Debug>(
133-
lock_error: LockError<PR, RR>,
134-
) -> anyhow::Error {
135-
if let LockError::Solver(solver_error) = lock_error {
136-
match *solver_error.inner {
137-
pubgrub::PubGrubError::NoSolution(mut derivation_tree) => {
138-
derivation_tree.collapse_no_versions();
139-
140-
anyhow!(
141-
"failed to satisfy usage constraints:\n{}",
142-
pubgrub::DefaultStringReporter::report(&derivation_tree)
143-
)
144-
}
145-
pubgrub::PubGrubError::ErrorRetrievingDependencies {
146-
package, source, ..
147-
} => match package {
148-
DependencyIdentifier::Requested(_) => {
149-
anyhow!("failed to retrieve project(s): {source}")
150-
}
151-
DependencyIdentifier::Remote(iri) => {
152-
anyhow!("failed to retrieve `{iri}`: {source}")
153-
}
154-
},
155-
pubgrub::PubGrubError::ErrorChoosingVersion { package, source } => match package {
156-
DependencyIdentifier::Requested(_) => {
157-
// `fn choose_version()` is infallible in this path
158-
unreachable!();
159-
}
160-
DependencyIdentifier::Remote(iri) => {
161-
anyhow!("unable to select version of `{iri}`: {source}")
162-
}
163-
},
164-
pubgrub::PubGrubError::ErrorInShouldCancel(_) => {
165-
// ProjectSolver doesn't implement this and default impl does nothing
166-
unreachable!();
167-
}
168-
}
169-
} else {
170-
anyhow!("{lock_error}")
171-
}
172-
}

0 commit comments

Comments
 (0)