6 ms·
>> The error handling is too weird. >What would you rather see? Exceptions
by soulbadguy 10y ago
>> The error handling is too weird.
>What would you rather see?
Exceptions
- pcwalton 10y agoWe would lose lots of users from C and C++ if we mandated exceptions for error handling. The code size and complexity of unwinding is too much of a price for many to pay.
- soulbadguy 10y agoNot mandate them , use have them as an options where the monadic Errors types are not enough or are too cumbersome to use.
- pcwalton 10y agoAnd thereby prevent people from writing code that needs to catch errors but can't use exceptions. Won't work.
- soulbadguy 10y agoI don't understand what that sentence means...
- thristian 10y agoSome people don't want to use exceptions because of runtime overhead costs. If exceptions are just "an option" that a library can choose when designing its interface, then you'll get a split ecosystem: a bunch of libraries that do use exceptions for error-handling, and then a separate bunch of libraries that do the same thing, but don't use exceptions for error handling, which is wasted, redundant effort.
- btschaegg 10y ago> then you'll get a split ecosystem Agreed. Point in case: Have a look at D and the discussions about their GC. I haven't kept up much about the last year, but my general impression runs down to: If you want to use their standard library. There's gonna be garbage collection. Period. If you want to avoid it, enjoy implementing its functionality all by yourself. With rust and exceptions you would likely not have a problem with the main ecosystem, but the same problem is bound to pop up with some big & famous library. Edit: Similarly, exceptions are one of the reasons C++'s SG14 exists.
- deleted 10y ago[deleted]
- Animats 10y agoRust is already paying the cost of unwinding. RFC 1236 added unwinding machinery for catching panics.[1] ("A drawback of this RFC is that it can water down Rust's error handling story.") This is the expensive part of exception handling. Rust has exceptions, but they're not very good. Go also backed into adding most of the machinery for exceptions by adding catch with unwind for panics. If you're going to have the unwinding machinery, why not have real exceptions? Exceptions aren't so bad if you do them the way Python does, using a predefined exception hierarchy. Catching an exception catches everything in its subtree. Catching RuntimeError catches most of the things one can induce from outside the program. Python's WITH statement also has one of the few mechanisms which can gracefully handle an error on releasing a resource. Exceptions in C++, Java, and Javascript are more troublesome. [1] https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md https://github.com/rust-lang/rfcs/blob/master/text/1236-stab...
- dbaupp 10y agoYou have talked about Python's exception scheme before, and been rebuffed before (it is too dynamic to use pervasively in a systems language), please be more specific, and also have the minimum grace to not repeat incorrect things. In any case, panics are not guaranteed to unwind or be catchable: they can be turned into aborts (yes, on the stable compiler). This means an arbitrary library using them for recoverable error handling is incorrect.
- Animats 10y agoWhat dynamism? An exception hierarchy just requires a type hierarchy, and Rust has enough inheritance for that. Rust has some dynamic dispatch, although it's not clear if the mechanism for trait objects [1] can implement an exception hierarchy cleanly. A WITH clause mechanism implies no dynamism. Please be more specific with your complaints. Thanks. [1] https://doc.rust-lang.org/book/trait-objects.html https://doc.rust-lang.org/book/trait-objects.html
- dbaupp 10y agoFirstly, "just" determining membership of a value within a type hierarchy requires far more dynamism than zero. Given a fairly arbitrary type-erased value x, how do you tell if its type implements some fairly arbitrary trait T? This hierarchy presumably has to be open, which makes the problem harder. Additionally, unless one is using explicitly typed exceptions (i.e. Java-style checked exceptions, very much unlike Python), it requires allocations, as it's not possible to statically determine the size of the error object to be returned. Similarly, from an assurance/reliability point of view, the dynamically typed nature of non-checked exceptions is unfortunate. (These second two are, I believe, the points I made last time we discussed Python's exceptions.)
- fjrieiekd 10y agoThere's also Swift's approach, which looks like exceptions but is really similar to Rust's approach under the hood. Swift also requires failable calls to be prefixed by "try" which makes them even easier to spot than the postfix "?" that Rust uses.
- sssilver 10y agoJust curious, have you ever used any other modern languages that do not use exceptions for error handling? Most people who complain are just used to the exception way, but once you embrace returning errors out of functions, it really does feel like a massive improvement in terms of the paradigm.
- CalChris 10y agoHow do you return failure for a bus error in Rust?
- Jweb_Guru 10y agoYou can use signal handlers if you need to, but it's not like there's a good way to handle most bus errors in userspace to begin with. Anyway neither standard C nor standard C++ even spec out interrupt handling, and SIGBUS isn't a standard signal :P
- CalChris 10y agoA signal handler (signal!(sig::ffi::Sig::BUS, test_bus);) will catch the bus error in userspace. You now need to communicate that caught exception to the offending fn. For that, you'll need setjmp() and longjmp(), something else that Rust lacks. If Rust is going to bill itself as a systems programming language, it needs these. I added them for my app: extern { #[link_name = "llvm.setjmp"] pub fn setjmp(a: *mut i8) -> i32; #[link_name = "llvm.longjmp"] pub fn longjmp(a: *mut i8, b: i32) -> (); } It took me awhile to figure this out (and it barely works). There's a cleaner way (adding a wrapper) that is even more work.
- Jweb_Guru 10y ago> A signal handler will catch the bus error in userspace. Sure, but what I meant is that most of the time userspace programs have nothing interesting they can do with the bus error (and, as I noted, standard C does not actually provide this option anyway). Regardless there are existing signal handling libraries that aren't that hard to use in Rust (you now describe one in your post), so I'm not sure why you're pointing to that as "something... that Rust lacks." There's no way I'm aware of that setjmp / longjmp could possibly be integrated with safe Rust, but I agree that they should be available to unsafe code (in a way that doesn't require invoking llvm intrinsics).
- mmstick 10y agoI would be downright appalled if Rust were to start promoting exceptions. It's an anti-feature.
- soulbadguy 10y agoBeing this emotionally invested in a feature, really is unprofessional...
- mmstick 10y agoUsing exceptions would be unprofessional. If someone were to use exceptions, then all of my carefully crafted error-handling routines would go up in flames because someone's library decided not to use an algebraic data type for conveying error messages across boundaries. It's bad enough that C libraries can suffer catastrophic failures bringing the entire stack down. I want a consistent error-handling strategy, and pattern matching is the best method of clearly displaying intents and possible downfalls.
- soulbadguy 10y ago> Using exceptions would be unprofessional. Unless it happens to be the best tools for the particular scenario... > then all of my carefully crafted error-handling routines would go up in flames No just sandbox the code inside a try catch... > pattern matching is the best method of clearly displaying intents and possible downfalls. You are stating an opinions as a fact here.
- mmstick 10y agoYou are basically stating that we should be doing both try/catch AND result/option at the same time, everywhere. That would get annoying fast.
- hyperpape 10y ago> No just sandbox the code inside a try catch... This works fine if it's just a matter of rolling back a database transaction or releasing file handles (b/c someone else is doing all the work for you). But if you have more complicated invariants, your try catch has to handle restoring those invariants, no matter what path your code took.