foundry_common/errors/
mod.rs1mod fs;
4pub use fs::FsPathError;
5
6mod artifacts;
7pub use artifacts::*;
8
9mod private {
10 use eyre::Chain;
11 use std::error::Error;
12
13 pub trait ErrorChain {
14 fn chain(&self) -> Chain<'_>;
15 }
16
17 impl ErrorChain for dyn Error + 'static {
18 fn chain(&self) -> Chain<'_> {
19 Chain::new(self)
20 }
21 }
22
23 impl ErrorChain for eyre::Report {
24 fn chain(&self) -> Chain<'_> {
25 self.chain()
26 }
27 }
28}
29
30pub fn display_chain<E: private::ErrorChain + ?Sized>(error: &E) -> String {
32 dedup_chain(error).join("; ")
33}
34
35pub fn dedup_chain<E: private::ErrorChain + ?Sized>(error: &E) -> Vec<String> {
37 let mut causes = all_sources(error);
38 causes.dedup_by(|b, a| a.contains(b.as_str()));
40 causes
41}
42
43fn all_sources<E: private::ErrorChain + ?Sized>(err: &E) -> Vec<String> {
44 err.chain().map(|cause| cause.to_string().trim().to_string()).collect()
45}
46
47pub fn convert_solar_errors(dcx: &solar::interface::diagnostics::DiagCtxt) -> eyre::Result<()> {
49 match dcx.emitted_errors() {
50 Some(Ok(())) => Ok(()),
51 Some(Err(e)) if !e.is_empty() => eyre::bail!("solar run failed:\n\n{e}"),
52 _ if dcx.has_errors().is_err() => eyre::bail!("solar run failed"),
53 _ => Ok(()),
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn dedups_contained() {
63 #[derive(thiserror::Error, Debug)]
64 #[error("my error: {0}")]
65 struct A(#[from] B);
66
67 #[derive(thiserror::Error, Debug)]
68 #[error("{0}")]
69 struct B(String);
70
71 let ee = eyre::Report::from(A(B("hello".into())));
72 assert_eq!(ee.chain().count(), 2, "{ee:?}");
73 let full = all_sources(&ee).join("; ");
74 assert_eq!(full, "my error: hello; hello");
75 let chained = display_chain(&ee);
76 assert_eq!(chained, "my error: hello");
77 }
78}