Skip to content
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

Documentation #4

Open
withoutboats opened this issue Sep 20, 2019 · 11 comments
Open

Documentation #4

withoutboats opened this issue Sep 20, 2019 · 11 comments

Comments

@withoutboats
Copy link
Owner

Would be nice to have actually good documentation here

@yoshuawuyts
Copy link
Contributor

Some random bits I think might be worth addressing (though not sure if it makes more sense for docs, or a blog, or):

  • why checked exceptions? Which challenges are being addressed?
  • how does this crate tie into the larger lang error handling story?
  • what's the relationship of fehler, failure, and snafu?
  • perhaps worth mentioning try blocks also?
  • failure had a really nice Error + ErrorKind model. How do we define custom errors with Fehler? (though perhaps it's not even in scope, might be worth mentioning?)

I really like the readme so far, and the doc comments too! The only part that I feel is absent still is examples, in particular some common patterns. And some of the context around Fehler and the Rust language.

@withoutboats
Copy link
Owner Author

failure had a really nice Error + ErrorKind model. How do we define custom errors with Fehler? (though perhaps it's not even in scope, might be worth mentioning?)

I thought this pattern was really nice, but I don't know if anyone has ever actually used it!

@yoshuawuyts
Copy link
Contributor

I thought this pattern was really nice, but I don't know if anyone has ever actually used it!

I used to for the longest time, but it ended up being a lot of boilerplate that I eventually stopped using it. I do feel like it represents the right pattern, and wish it was easier to construct!

@withoutboats
Copy link
Owner Author

withoutboats commented Sep 20, 2019

It's very easy to wipe away the boilerplate. Pretty sure if the user just defines MyErrorKind themselves they just need to pick a name for MyError:

error_with_kind! { MyError => MyErrorKind }

// Do this part yourself
enum MyErrorKind {
   // ...
}

But I've never really liked these gadgetty macros that create a whole type with a bunch of different impls.

@yoshuawuyts
Copy link
Contributor

Yeah, I never liked those macros either. I was wondering though; since Error is essentially only ever a wrapper around ErrorKind. Couldn't we make it generic, and recommend people use a type alias to wrap it? Coupled with #11 (comment) this might look something like:

// The "Error" type is provided by Der Fehler, which we can reuse in our type alias.
mod fehler {
    use std::fmt::{self, Debug, Display};
    
    pub struct Error<E: Display> {
        inner: E
    }
    
    impl<E: Display> Display for Error<E> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            Display::fmt(&self.inner, f)
        }
    }
    
    impl<E: Display> Debug for Error<E> {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            Display::fmt(self, f)
        }
    }

    impl<E: Display> std::error::Error for Error<E> {}
}

/// The kinds of errors that can occur.
#[derive(Debug, Display)]
pub enum ErrorKind {
    /// The user id {user_id} is invalid
    UserIdInvalid { user_id: i32 },
    /// An error not part of this list
    Other,
}

/// Our crate's error kind
pub type Error = fehler::Error<ErrorKind>;

This would have the downside of not neatly showing up as a struct in the docs. But neither do Result definitions, and for all intents and purposes they behave the same.

I have the feeling I might be missing something, but perhaps this may actually be an option?

@withoutboats
Copy link
Owner Author

That's exactly what failure's Context type was, it was only recommended to create a new type since it'd be part of your public API

@yoshuawuyts
Copy link
Contributor

Ahh, okay! I thought I was onto something, haha.

@seniorjoinu
Copy link

Please add crates.io link into readme.

@Ten0
Copy link

Ten0 commented Apr 10, 2020

I cannot find in the documentation how it behaves with return statements.

@earthengine
Copy link

earthengine commented Feb 10, 2021

Maybe a bit late, but I would share my experience. fehler is better work with derive_more where you can derive From and Display, which is very handy to define your custom error class. We do not need fehler to have the ability for custom error classes. Instead, if derive_more can support std::Error it would be great.

For example:

#[derive(From, Debug, Display)]
enum MyError {
    #[display(fmt = "IO Error: {}", _0)]
    Io(std::io::Error),
    #[display(fmt = "Format Error: {}", _0)]
    Format(std::fmt::Error)
}
impl std::error::Error for MyError {};

With From implemented, you are already able to throw either a std::io::Error or a std::fmt::Error. With Display and Debug implementing std::error::Error is just one line.

derive_more 0.99.11

@ijackson
Copy link

Maybe a bit late, but I would share my experience. fehler is better work with derive_more

derive_more is nice but I recommend you check out thiserror. It lets you derive Error, and has nice annotations for precise control of the Display and From impls.

When I want a more generic error type I use anyhow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants