5 ms·
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
by brigadier132 2y ago
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 need to be handled.
Without enum variants being explicit types and the ability to easily create anonymous enums using union and intersection operators Rust enums require a ton of boilerplate.
- wredue 2y agoYeah. 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.
- brigadier132 2y ago> 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.
- eddd-ddde 2y agoZig has automatic error unions. No boilerplate at all, but not just a single "error" type. The only downside I see in zig errors is that they can't hold extra data.
- ziml77 2y agoIt's a massive downside. When I was using the JSON parser I found it very annoying that it could only tell me the input JSON was invalid, not where in the input the problem was.
- eddd-ddde 2y agoYeah I agree. I think they tend to go for a mutable parameter reference to keep track of that stuff, which is definitely C-like but kinda unwieldy.
- wredue 2y agoOf 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.
- lilyball 2y agoThis is true, though the issue of having error variants the function can't return is fairly overblown, because most code doesn't bother handling all error variants individually. Most of the time an error is either propagated upwards (possibly wrapped in another error) or logged. Inspecting the error variants is usually only done if you want to specially handle some of them (such as handling `ErrorKind::NotFound` when deleting a file), rather than exhaustively handling all variants.
- brigadier132 2y agoWe can disagree on it being overblown or not but I think it would be enormously useful to be able to look at a function signature and know exactly how it can fail.
- None4U 2y agoThey tried that in Java and no one uses it...
- erik_seaberg 2y agoLambdas broke checked exceptions. You can't declare that you throw whatever a generic lambda might throw, so they quickly devolved to "I throw nothing (only unchecked)." The "I throw everything" alternative is rarely used because it spreads virally through every caller.
- baq 2y agoChecked exceptions were strongly discouraged because they have nonlocal behavior when changing library code. If you want to rethrow exceptions you can’t handle you have to update all callers when the callee changes the throw signature. Lambdas are orthogonal.
- erik_seaberg 2y agoI'm thinking of cases like Stream#flatMap where I might be prepared for what a lambda (probably a method ref) could throw, yet still can't use it because exception lists for the Stream interface methods had to be declared statically years ago.
- ryandrake 2y agoI'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, and checks the int that it is within a valid range. This is not a big function. But it might produce one of: 1. str::Utf8Error, 2. num::ParseIntError, or 3. MyCustomInBoundsError. There's no clean way to write a Rust function that could return either of them. I had to bundle everything up into an enum and then return that, and then the caller has to do some "match" acrobatics to handle each error differently. I hate to say this, but I miss Python and C++'s exceptions. How nice to just try: something and then: except SomeError: doFoo() except ThatErrror: doBar() except AnotherError: doBaz() finally: sayGoodbye() An elegant weapon for a more civilized age. What do I know though? I'm still in the larval stage of Rust learning where I'm randomly adding &, *, .deref() and .clone() just to try to get the compiler to accept my code.
- deleted 2y ago[deleted]
- deleted 2y ago[deleted]
- rascul 2y agoMany error types implement std::error::Error, maybe using that would make things easier. An example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5da3cd06b72c80d06aa2eaa2fc74b4ef https://play.rust-lang.org/?version=stable&mode=debug&editio...
- ryandrake 2y agoHmm, 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.
- joshka 2y ago