Live data from Hacker News

Rust error handling

bitfieldconsulting.com

51–60 of 65 posts

Re: Rust error handling

#51

Earlier quoted context omitted.

Why bother having a typed return value? That could be in the documentation too. The whole point of a type system is to help me understand what the function can and cannot do without needing to make guesses based on the documentation. It's not fatal, but it is annoying and inconsistent that Rust can do this on the happy path but not the error path.

The type system cannot capture 100% of the semantics of the function. You put what you can in there, but you also need documentation. You could provide a bespoke error type for every single function that returns an error, but that's a ton of boilerplate, and you're effectively just moving the documentation from the function to the error type (enum variant names are not sufficiently descriptive to avoid having to writ…

> You could provide a bespoke error type for every single function that returns an error, but that's a ton of boilerplate

If we had more typescript-like discriminated union semantics a lot of the boilerplate would go away. Throw in automatic implementation of From traits for enums composed of other enums / types and it could be pretty close to perfect.

Re: Rust error handling

#52
post #49

Earlier quoted context omitted.

That isn't possible. The assert may not even be produced in code you control. The reason panics/exceptions exist is it is too onerous to handle every possible error condition at all callsites (allocation failure and broken pipes are the famous examples), and it is not possible to enumerate all possible error conditions (unintentional programmer errors for example). People have religious ideas about handling panics fo…

Panics shouldn't exist in modern Rust (if there is such a thing) at all.

I take it you mean panics should always abort?

Re: Rust error handling

#53

It's far from perfect. One of the biggest problems with Rust error handling is that if you want to have explicit error return types encoded in the type system you need to create ad hoc enums for each method that returns an error. If you only use a single error type for all functions you will inevitably have functions returning Results that contain error variants that the function will never actually return but still…

I'm just now learning Rust, as a long time C++'er, and this was the first part of my Rust journey where I thought to myself, "Boy, this really smells--this couldn't possibly be the idiomatic Rust Way to handle functions that can produce different types of errors. I must be doing something wrong!" For example, I have a function that takes an array of bytes, decodes it as UTF-8 to text, parses that text into an i32, an…

Many error types implement std::error::Error, maybe using that would make things easier.

An example: https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re: Rust error handling

#54
post #2

Maybe not perfect, but it seems to work out better than exceptions. Exceptions are a good idea which turned out to be too complicated. A language has to use destructors to clean up for almost everything for this to work. "?" has no "catch" clause within the function. So if an object has an invariant, and that invariant must be restored on error, the destructors must restore the invariant. If that just means unlocking…

This recent post resonated with me: https://cedardb.com/blog/exceptions_vs_errors/

There are certain obvious (and some less obvious) benefits to both exceptions and results, but I get the impression a lot of programmers have overreacted against exceptions.

Exceptions "just work" the same in every codebase and require little boilerplate in most languages. I think results really shine for internal business logic where errors are more "invalid" than "exceptional."

Re: Rust error handling

#55

For those who want to experiment with this style in C#, I've found this package to work: https://github.com/JohannesMoersch/Functional

Another good option I’ve personally used if you want a smaller API surface with just Result and Maybe concepts is True Myth. https://true-myth.github.io/true-myth-csharp/

Re: Rust error handling

#56
post #53

Earlier quoted context omitted.

I'm just now learning Rust, as a long time C++'er, and this was the first part of my Rust journey where I thought to myself, "Boy, this really smells--this couldn't possibly be the idiomatic Rust Way to handle functions that can produce different types of errors. I must be doing something wrong!" For example, I have a function that takes an array of bytes, decodes it as UTF-8 to text, parses that text into an i32, an…

Many error types implement std::error::Error, maybe using that would make things easier. An example: https://play.rust-lang.org/?version=stable&mode=debug&editio...

Hmm, I think I tried this a few times, but I could never get the right magical combination of dyn, Box and & to get it to compile.

Re: Rust error handling

#57
post #7

Earlier quoted context omitted.

Yeah. The error type requires so much boilerplate that I honestly thought I was stupid and doing something wrong. But nope. Just horrific amounts of boilerplate. Then people who don’t want to engage with ThisError and Anyhow do bullshit hacks like making everything a string that has to be parsed (and don’t provide functions to parse). I get why it is that way, but it feels icky.

> I get why it is that way, but it feels icky. There is no reason it has to be so boilerplate heavy, a lot of it can be fixed but someone has to put in the work. The only technical reason that could hold it back is compile times.

Of course there is a reason it is this way. In lower level languages, compilers need to know the type and size of the type at compile time. This holds true even for languages with looser typing like C.

You are not going to get strict types in a low level language and also get ergonomic errors. This is fundamentally not how compilers works.

Re: Rust error handling

#58

Earlier quoted context omitted.

If you're writing something safety critical like avionics flight control software, you probably don't want to crash in production either. I've also always interpreted "fail fast" as "Make defects obvious during development so they don't exist when you deploy to customers."

These are thought provoking counter examples. So, on a micro-level, let's say I have a function that expects x to be a float between 0 and 1, and there's some math and logic built on this assumption. Of course, in development if this expectation is violated, we fail fast and loudly and then fix the problem. In production it's not quite so clear. But still, is it ever the right thing to ignore that an invariant is vio…

> But still, is it ever the right thing to ignore that an invariant is violated and just hope that things somehow work out?

Yes! Of course! In many situations it probably doesn't matter that the numbers go a little wrong, and that result will be better than crashing. In other situations it will be better to crash than to give junk results. As we already said, it depends on the situation.

Re: Rust error handling

#60
post #14

> But, since good programs don’t panic, and neither do good programmers, it’s very rare that using unwrap or expect is actually the right thing to do. I respectfully disagree. The assert!() macro is a way to document invariants. It's a bug if a variant is violated. It shouldn't have happened, but if it happens, then there's nothing the user can do except reporting the crash. The unwrap() and expect() method document…

The easiest counterpoint to this is to think about a HTTP request. If your library is called by one route, and is known to fail in certain circumstances, this failure should not bring down the entire system. A well designed library should generally not make the choice to crash a system - that's the caller's decision. Yes there are exceptions to this, which is why TFA stated this as "rare" not "never".

Using the assert macro in your code is (in my experience) generally bad. If your code is written well, you can never test that code path. Document invariants with tests instead, or better yet with infallible code.

Post reply on HN