-
-
Notifications
You must be signed in to change notification settings - Fork 418
refactor!: catch up Exn designs with the upstream #2384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
d3c1d47
849936f
2345fc3
9bbe26a
2d5ae3b
60cbe5c
fb78fab
73cf39a
5ae1cf2
052480f
207f416
04f29ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,7 +14,6 @@ | |
|
|
||
| use std::error::Error; | ||
| use std::fmt; | ||
| use std::fmt::Formatter; | ||
| use std::marker::PhantomData; | ||
| use std::ops::Deref; | ||
| use std::panic::Location; | ||
|
|
@@ -69,10 +68,8 @@ impl<E: Error + Send + Sync + 'static> Exn<E> { | |
| } | ||
|
|
||
| /// Create a new exception with the given error and children. | ||
| /// | ||
| /// It's no error if `children` is empty. | ||
| #[track_caller] | ||
| pub fn from_iter<T, I>(children: I, err: E) -> Self | ||
| pub fn raise_all<T, I>(children: I, err: E) -> Self | ||
| where | ||
| T: Error + Send + Sync + 'static, | ||
| I: IntoIterator, | ||
|
|
@@ -94,6 +91,14 @@ impl<E: Error + Send + Sync + 'static> Exn<E> { | |
| new_exn | ||
| } | ||
|
|
||
| /// Use the current exception as the head of a chain, adding `err` to its children. | ||
| #[track_caller] | ||
| pub fn chain<T: Error + Send + Sync + 'static>(mut self, err: impl Into<Exn<T>>) -> Exn<E> { | ||
| let err = err.into(); | ||
| self.frame.children.push(*err.frame); | ||
| self | ||
| } | ||
|
|
||
| /// Use the current exception the head of a chain, adding `errors` to its children. | ||
| #[track_caller] | ||
| pub fn chain_iter<T, I>(mut self, errors: I) -> Exn<E> | ||
|
||
|
|
@@ -116,14 +121,6 @@ impl<E: Error + Send + Sync + 'static> Exn<E> { | |
| self.frame.children.drain(..).map(Exn::from) | ||
| } | ||
|
|
||
| /// Use the current exception the head of a chain, adding all `err` to its children. | ||
| #[track_caller] | ||
| pub fn chain<T: Error + Send + Sync + 'static>(mut self, err: impl Into<Exn<T>>) -> Exn<E> { | ||
| let err = err.into(); | ||
| self.frame.children.push(*err.frame); | ||
| self | ||
| } | ||
|
|
||
| /// Erase the type of this instance and turn it into a bare `Exn`. | ||
| pub fn erased(self) -> Exn { | ||
| let untyped_frame = { | ||
|
|
@@ -148,7 +145,7 @@ impl<E: Error + Send + Sync + 'static> Exn<E> { | |
| } | ||
|
|
||
| /// Return the current exception. | ||
| pub fn as_error(&self) -> &E { | ||
| pub fn error(&self) -> &E { | ||
| self.frame | ||
| .error | ||
| .downcast_ref() | ||
|
|
@@ -175,19 +172,21 @@ impl<E: Error + Send + Sync + 'static> Exn<E> { | |
| } | ||
|
|
||
| /// Turn ourselves into a top-level [Error] that implements [`std::error::Error`]. | ||
| /// | ||
| /// [Error]: crate::Error | ||
| pub fn into_error(self) -> crate::Error { | ||
| self.into() | ||
| } | ||
|
|
||
| /// Return the underlying exception frame. | ||
| pub fn as_frame(&self) -> &Frame { | ||
| pub fn frame(&self) -> &Frame { | ||
| &self.frame | ||
| } | ||
|
|
||
| /// Iterate over all frames in breadth-first order. The first frame is this instance, | ||
| /// followed by all of its children. | ||
| pub fn iter(&self) -> impl Iterator<Item = &Frame> { | ||
| self.as_frame().iter() | ||
| self.frame().iter() | ||
| } | ||
|
|
||
| /// Iterate over all frames and find one that downcasts into error of type `T`. | ||
|
|
@@ -204,18 +203,18 @@ where | |
| type Target = E; | ||
|
|
||
| fn deref(&self) -> &Self::Target { | ||
| self.as_error() | ||
| self.error() | ||
| } | ||
| } | ||
|
|
||
| impl<E: Error + Send + Sync + 'static> fmt::Debug for Exn<E> { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| write_frame_recursive(f, self.as_frame(), "", ErrorMode::Display, TreeMode::Linearize) | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| write_frame_recursive(f, self.frame(), "", ErrorMode::Display, TreeMode::Linearize) | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Debug for Frame { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| write_frame_recursive(f, self, "", ErrorMode::Display, TreeMode::Linearize) | ||
| } | ||
| } | ||
|
|
@@ -233,7 +232,7 @@ enum TreeMode { | |
| } | ||
|
|
||
| fn write_frame_recursive( | ||
| f: &mut Formatter<'_>, | ||
| f: &mut fmt::Formatter<'_>, | ||
| frame: &Frame, | ||
| prefix: &str, | ||
| err_mode: ErrorMode, | ||
|
|
@@ -257,9 +256,8 @@ fn write_frame_recursive( | |
| write!(f, "\n{prefix}└─ ")?; | ||
|
|
||
| let child_child_len = child.children().len(); | ||
| let may_linerarize_chain = | ||
| matches!(tree_mode, TreeMode::Linearize) && children_len == 1 && child_child_len == 1; | ||
| if may_linerarize_chain { | ||
| let may_linearize_chain = matches!(tree_mode, TreeMode::Linearize) && children_len == 1 && child_child_len == 1; | ||
| if may_linearize_chain { | ||
| write_frame_recursive(f, child, prefix, err_mode, tree_mode)?; | ||
| } else if cidx < children_len - 1 { | ||
| write_frame_recursive(f, child, &format!("{prefix}| "), err_mode, tree_mode)?; | ||
|
|
@@ -271,14 +269,14 @@ fn write_frame_recursive( | |
| Ok(()) | ||
| } | ||
|
|
||
| fn write_location(f: &mut Formatter<'_>, exn: &Frame) -> fmt::Result { | ||
| fn write_location(f: &mut fmt::Formatter<'_>, exn: &Frame) -> fmt::Result { | ||
| let location = exn.location(); | ||
| write!(f, ", at {}:{}:{}", location.file(), location.line(), location.column()) | ||
| } | ||
|
|
||
| impl<E: Error + Send + Sync + 'static> fmt::Display for Exn<E> { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| std::fmt::Display::fmt(&self.frame, f) | ||
| fmt::Display::fmt(&self.frame, f) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -451,14 +449,14 @@ impl From<Frame> for Exn { | |
| pub struct Untyped(Box<dyn Error + Send + Sync + 'static>); | ||
|
|
||
| impl fmt::Display for Untyped { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| std::fmt::Display::fmt(&self.0, f) | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| fmt::Display::fmt(&self.0, f) | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Debug for Untyped { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| std::fmt::Debug::fmt(&self.0, f) | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| fmt::Debug::fmt(&self.0, f) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -468,14 +466,14 @@ impl Error for Untyped {} | |
| pub struct Something; | ||
|
|
||
| impl fmt::Display for Something { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| f.write_str("Something went wrong") | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Debug for Something { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| std::fmt::Display::fmt(&self, f) | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| fmt::Display::fmt(&self, f) | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I know gix-error has to wrap once more the inner error into
Untypedbecausedowncastmust have the type param matched. In this case, it seems to be inevitable.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, the
into_inner()andinto_box()can be removed as there is alwaysgix_error::Errorto hold these types.Let's leave it as is for now, and I will consider removing them to avoid that double-box.