Skip to content

Commit a580aea

Browse files
committed
Defer error printing for resolution errors
1 parent 6b2ef7d commit a580aea

File tree

3 files changed

+65
-16
lines changed

3 files changed

+65
-16
lines changed

compiler-core/src/dependency.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ mod tests {
401401
use hexpm::RetirementStatus;
402402

403403
use crate::{
404+
derivation_tree::DerivationTreePrinter,
404405
manifest::{Base16Checksum, ManifestPackage, ManifestPackageSource},
405406
requirement,
406407
};
@@ -1087,7 +1088,14 @@ mod tests {
10871088
&vec![].into_iter().collect(),
10881089
);
10891090

1090-
if let Err(Error::DependencyResolutionFailed(message)) = result {
1091+
if let Err(Error::DependencyResolutionNoSolution {
1092+
root_package_name,
1093+
derivation_tree,
1094+
}) = result
1095+
{
1096+
let message = crate::error::wrap(
1097+
&DerivationTreePrinter::new(root_package_name, derivation_tree.0).print(),
1098+
);
10911099
insta::assert_snapshot!(message)
10921100
} else {
10931101
panic!("expected a resolution error message")

compiler-core/src/derivation_tree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl DerivationTreePrinter {
7777

7878
/// Tries and print a pretty explanation for the given resolution tree.
7979
/// If for some reason our heuristic to produce a nice error message fails
80-
/// we return `None` se we can still produce a good enough error message!
80+
/// we return `None` so we can still produce a good enough error message!
8181
///
8282
fn pretty_explanation(&self) -> Option<String> {
8383
let root_package_index = self.nodes.get(self.root_package_name.as_str())?;

compiler-core/src/error.rs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,15 @@ file_names.iter().map(|x| x.as_str()).join(", "))]
236236
#[error("Failed to create canonical path for package {0}")]
237237
DependencyCanonicalizationFailed(String),
238238

239-
#[error("Dependency tree resolution failed: {0}")]
240-
DependencyResolutionFailed(String),
239+
#[error("Could not find versions that satisfy dependency requirements")]
240+
DependencyResolutionNoSolution {
241+
root_package_name: EcoString,
242+
derivation_tree:
243+
NeverEqual<pubgrub::DerivationTree<String, pubgrub::Ranges<Version>, String>>,
244+
},
245+
246+
#[error("Dependency resolution failed: {0}")]
247+
DependencyResolutionError(String),
241248

242249
#[error("The package {0} is listed in dependencies and dev-dependencies")]
243250
DuplicateDependency(EcoString),
@@ -329,6 +336,17 @@ file_names.iter().map(|x| x.as_str()).join(", "))]
329336
CannotAddSelfAsDependency { name: EcoString },
330337
}
331338

339+
// A wrapper that ignores the inner value for equality:
340+
#[derive(Debug, Clone)]
341+
pub struct NeverEqual<T>(pub T);
342+
343+
impl<T> PartialEq for NeverEqual<T> {
344+
fn eq(&self, _other: &Self) -> bool {
345+
false
346+
}
347+
}
348+
impl<T> Eq for NeverEqual<T> {}
349+
332350
/// This is to make clippy happy and not make the error variant too big by
333351
/// storing an entire `hexpm::version::Version` in the error.
334352
///
@@ -435,27 +453,30 @@ impl Error {
435453
error: ResolutionError<'_, T>,
436454
root_package_name: EcoString,
437455
) -> Error {
438-
Self::DependencyResolutionFailed(match error {
439-
ResolutionError::NoSolution(derivation_tree) => {
440-
DerivationTreePrinter::new(root_package_name, derivation_tree).print()
441-
}
456+
match error {
457+
ResolutionError::NoSolution(derivation_tree) => Self::DependencyResolutionNoSolution {
458+
root_package_name,
459+
derivation_tree: NeverEqual(derivation_tree),
460+
},
442461

443462
ResolutionError::ErrorRetrievingDependencies {
444463
package,
445464
version,
446465
source,
447-
} => format!(
466+
} => Self::DependencyResolutionError(format!(
448467
"An error occurred while trying to retrieve dependencies of {package}@{version}: {source}",
449-
),
468+
)),
450469

451470
ResolutionError::ErrorChoosingVersion { package, source } => {
452-
format!("An error occured while chosing the version of {package}: {source}",)
471+
Self::DependencyResolutionError(format!(
472+
"An error occured while chosing the version of {package}: {source}",
473+
))
453474
}
454475

455-
ResolutionError::ErrorInShouldCancel(err) => {
456-
format!("Dependency resolution was cancelled. {err}")
457-
}
458-
})
476+
ResolutionError::ErrorInShouldCancel(err) => Self::DependencyResolutionError(format!(
477+
"Dependency resolution was cancelled. {err}"
478+
)),
479+
}
459480
}
460481

461482
pub fn expand_tar<E>(error: E) -> Error
@@ -4202,14 +4223,34 @@ manifest.toml and a version range specified in gleam.toml:
42024223
}]
42034224
}
42044225

4205-
Error::DependencyResolutionFailed(error) => vec![Diagnostic {
4226+
Error::DependencyResolutionError(error) => vec![Diagnostic {
42064227
title: "Dependency resolution failed".into(),
42074228
text: wrap(error),
42084229
hint: None,
42094230
location: None,
42104231
level: Level::Error,
42114232
}],
42124233

4234+
Error::DependencyResolutionNoSolution {
4235+
root_package_name,
4236+
derivation_tree,
4237+
} => {
4238+
let text = wrap(
4239+
&DerivationTreePrinter::new(
4240+
root_package_name.clone(),
4241+
derivation_tree.0.clone(),
4242+
)
4243+
.print(),
4244+
);
4245+
vec![Diagnostic {
4246+
title: "Dependency resolution failed".into(),
4247+
text,
4248+
hint: None,
4249+
location: None,
4250+
level: Level::Error,
4251+
}]
4252+
}
4253+
42134254
Error::WrongDependencyProvided {
42144255
path,
42154256
expected,

0 commit comments

Comments
 (0)