News for hackers. Stuff that matters.
Re:Go’ing Insane: Endless Error Handling by chrismorgan on Tuesday September 14, 2021 @08:00AM (#28523381)
In the code shown, `foo()?;` is equivalent to this:

  match foo() {
      Ok(val) => val,
      Err(err) => return Err(err.into()),
  };
(This isn’t exactly how it’s implemented—that detail is unstable and has actually changed <https://github.com/rust-lang/rfcs/pull/3058> since ? was stabilised, without disrupting things!—but it’s equivalent in this instance. As examples of how it’s not exact: you can use ? on Option too; and inside a try block (unstable), ? isn’t a return, acting more like a break-with-value.)

For wrapping the error: note the .into() in the desugaring: it’ll perform any necessary type conversions which is the normal way you’d do error wrapping. But if you want to do anything more than that, or adding specific context, you’re still in luck! You can use method chaining to manipulate the result. In the standard library is map_err <https://doc.rust-lang.org/std/result/enum.Result.html#method...>:

  foo().map_err(|err| f(err))?
And you can add other methods to such types with extension traits; as an example, the anyhow crate, popular for application-level error handling (where you don’t care about precise modelling of errors) makes it so that, on importing anyhow::Context <https://docs.rs/anyhow/1.0.44/anyhow/trait.Context.html>, you can add context to an error like this:

  foo().context("foo failed")?
  foo().with_context(|| "foo failed")?

There are no comments on this comment yet.