summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias Fischler <Mafii@users.noreply.github.com>2023-06-24 14:18:21 +0200
committerGitHub <noreply@github.com>2023-06-24 14:18:21 +0200
commit2e03fb34cb9efd3f287b9658a8d84df52ad660dd (patch)
tree92c4fd41d98e8242cccf24aa1f34be0b0f020c7e /src
parent0de7860118d0906f26accba51f4fe83e524836d8 (diff)
Add infrastructure to enrich errors with hints (#1486)
Diffstat (limited to 'src')
-rw-r--r--src/diag.rs55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/diag.rs b/src/diag.rs
index 4fb9ecc0..0f669f64 100644
--- a/src/diag.rs
+++ b/src/diag.rs
@@ -82,6 +82,8 @@ pub struct SourceError {
pub message: EcoString,
/// The trace of function calls leading to the error.
pub trace: Vec<Spanned<Tracepoint>>,
+ /// Additonal hints to the user, indicating how this error could be avoided or worked around.
+ pub hints: Vec<EcoString>,
}
impl SourceError {
@@ -92,6 +94,7 @@ impl SourceError {
pos: ErrorPos::Full,
trace: vec![],
message: message.into(),
+ hints: vec![],
}
}
@@ -112,6 +115,12 @@ impl SourceError {
ErrorPos::End => full.end..full.end,
}
}
+
+ /// Adds a user-facing hint to the error.
+ pub fn with_hints(mut self, hints: &mut Vec<EcoString>) -> Self {
+ self.hints.append(hints);
+ self
+ }
}
/// A part of an error's [trace](SourceError::trace).
@@ -194,6 +203,52 @@ where
}
}
+pub type StrWithHintResult<T> = Result<T, StrWithHint>;
+
+pub struct StrWithHint {
+ message: EcoString,
+ hints: Vec<EcoString>,
+}
+
+impl<T> At<T> for Result<T, StrWithHint> {
+ fn at(self, span: Span) -> SourceResult<T> {
+ self.map_err(|mut diags| {
+ Box::new(vec![
+ SourceError::new(span, diags.message).with_hints(&mut diags.hints)
+ ])
+ })
+ }
+}
+
+/// Allows adding a user-facing hint in addition to the error.
+pub trait Hint<T, S>
+where
+ S: Into<EcoString>,
+{
+ fn hint(self, hint: S) -> StrWithHintResult<T>;
+}
+
+impl<T, S> Hint<T, S> for StrResult<T>
+where
+ S: Into<EcoString>,
+{
+ fn hint(self, hint: S) -> StrWithHintResult<T> {
+ self.map_err(|message| StrWithHint { message, hints: vec![hint.into()] })
+ }
+}
+
+impl<T, S> Hint<T, S> for StrWithHintResult<T>
+where
+ S: Into<EcoString>,
+{
+ fn hint(self, hint: S) -> StrWithHintResult<T> {
+ self.map_err(|mut diags| {
+ diags.hints.push(hint.into());
+ diags
+ })
+ }
+}
+
/// A result type with a file-related error.
pub type FileResult<T> = Result<T, FileError>;