bestouff 2 days ago

I saw this in a linked article :

> some Rust code will explicitly check its Result types, while other Rust code sprinkles '?' around and accepts that if the program sails off the happy path, it simply dies.

This is blatantly false. Rust's '?' operator bubbles the error up the callstack, transforming it along the way (generally wrapping it in another error type) but it doesn't "simply dies" at all.

  • nextaccountic 2 days ago

    (Note: that was in this article https://utcc.utoronto.ca/~cks/space/blog/programming/ErrorHa...)

    Yeah and more generally, the author seems to group Go and C on one side (langs where errors are values) and Rust in another, when actually in Rust errors are values just like in Go, and the ? operator just does early return (similar to if err != nil return from Go). Results just make it impossible to use the return value of some function without deciding what to do with its errors, which is awesome (you can't just forget to treat errors)

    The distinction between results and panics in Rust is also very instructive. Rust forces the developer to distinguish between recoverable and unrecoverable errors because after the program hit a panic (meant to represent unrecoverable errors) there is probably no meaningful way to continue the execution (data structures might be in an inconsistent state for example, if the panic happened in the midst of an update). Panics very often indicate a bug in the program (for example: array indexing with an out of bounds index means there was a bug while calculating the index) and no amount of error recovery will eliminate the fact that the program has a bug that must be fixed. It's absolutely the best default to interrupt the program after a bug rather than continue and propagate data corruption further.

    Now, what can happen is that a library you call considered some error to be unrecoverable (and thus threw a panic) rather than returning a Result, and you think that was a mistake and would like to treat the error. Well that's just a bad API and the correct response is to just send a PR or fork the library and apply the changes yourself. But if one absolutely needs to recover from panics (for example, in a web server a panic generally should send an error 500 to the client but not take down the whole process, which is serving many concurrent requests), you can just compile with panic=unwind (the default) and use catch_unwind.

    Error handling is not a solved problem, but Rust solves it way better than any language I've seen.

  • bsaul 2 days ago

    rust beginner here : how do you automatically remap the error to another type using ? operator ?

    • nextaccountic 2 days ago

      The ? operator has implicit error conversion. As another user said, it usses the From trait which performs conversions between one type and another. (Note that generally in Rust type conversions don't happen implicitly and you need to call .into() -- the ? situation is an exception)

      If you want to have more finer grained control on the error conversion (the From conversion is always the same for some pair of error types) you can use map_err before calling ?, like something.map_err(|e| othererror)?

      https://doc.rust-lang.org/std/result/enum.Result.html#method...

      If you are using anyhow and wants to attach a string message to the error (maybe to explain what happened to the user), you can also use .context(), also called .wrap_err() in eyre (eyre is a fork of anyhow)

      https://docs.rs/anyhow/latest/anyhow/trait.Context.html

      https://docs.rs/eyre/latest/eyre/trait.WrapErr.html

      The following article is ten years old, but was continually updated to keep it fresh and I think it does a good job explaining how error handling works in Rust:

      https://burntsushi.net/rust-error-handling/

    • tonyedgecombe 2 days ago

      You implement the From trait, something like this transforms an io::Error into your own type:

          impl From<io::Error> for MyError {
              fn from(_err: io::Error) -> MyError {
                  MyError::IOError
              }
          }
brian-bk 2 days ago

I'm pessimistic about Go if they _don't_ change error handling. The handling of nil's and errors (by extension panic's) is purely conventional, and baked in to the language has no protection.

Author asserts that error handling is unsolved and therefor a solution shouldn't be attempted. I disagree, anything is better than Go's error handling now.