8 ms·
Nothing in the language assumes unfailing allocation. It's only the current standard library APIs that don't support failable allocation, but there is work unde
by Ar-Curunir 7y ago
Nothing in the language assumes unfailing allocation. It's only the current standard library APIs that don't support failable allocation, but there is work underway to remedy this.
- quotemstr 7y agoThe fundamental mistake in the Rust programming language is avoiding the use of exceptions for reporting errors. It's because the Rust designers eschewed exceptions that lots of standard library functions that need to allocate memory are also no-fail. If we reported allocation failure with Result, we'd have Result _everywhere_, which would have an ergonomic disaster, especially before the "?" operator appeared. If Rust had been designed to use exceptions from the start, this problem wouldn't exist, and it'd be a much nicer language besides. Some people seem to just have a philosophical or aesthetic aversion to exceptions, which is a shame, because exceptions work wonderfully in practice. Rust's development path is especially unfortunate because when you return Result everywhere and use the "?" operator consistently, what you end up writing looks just like exceptional code, but with weird warts and limitations from the language essentially implementing exceptions with return codes instead of first-class affordances built into the language itself. It's because Rust got error handling wrong that I still prefer C++ despite Rust's advantages in variable lifetime reificiation. Exceptions turn out to be so useful in general-purpose programming that Rust had to add them in a hacky way after the fact using macros and special operators. I understand that my position is controversial, but it's still my opinion and it's going to inform my language choice.
- nixpulvis 7y agoI disagree. In fact, I'd go a step further the opposite direction and say that the inclusion of panics was a mistake in the language design, though we're stuck with it now. To be fair, they do allow much better diagnostics when things fail, so this is more of a matter of simplicity vs developer economics, unless I'm missing something.
- quotemstr 7y agoI agree that supporting panics was a mistake as long as exceptions aren't really supported. Panics force everyone to pay for the possibility of unwinding without getting to use unwinding for exceptions. It's unfortunate. If you're going to have to consider the possibility unwinding, running destructors, and so on, just add exceptions! You don't need the panic mechanism to get good stack traces. You can get good stack traces in plain C with abort(): walking the stack does not require unwinding the stack! Confusing these two concepts is just another example of the unfixable confusion baked into the core of Rust that ruins an otherwise-interesting language.
- steveklabnik 7y agoIf you don’t want to pay for landing pads, you can compile your program with panic=abort, and you won’t get them. As you say, you can still get stack traces. The only reason that this is feasible is precisely because panics are not used for recoverable error handing in Rust; libraries don’t break if you turn this option on.
- nixpulvis 7y agoWell, panics should not be used for recoverable error handing in Rust. There's no guarantee turning off panics in favor of aborts wont break the assumptions of some library. That library should probably break tho, since as you said, panics aren't meant to emulate application logic exceptions. use std::panic::catch_unwind; fn main() { let err = catch_unwind(|| { panic!("B") }); println!("Look ma, recoverable error handing! {:?}", err); }
- steveklabnik 7y agoYes, libraries that do this are encouraged to configure their Cargo.toml so that compilation will fail if someone turns on aborts.
- mwcampbell 7y agoCan I go further and disable stack traces as well, without giving up entirely on std? I don't want my release builds to have any of the extra code required to walk the stack. Just let the app crash; if I want a stack trace, I'll use a debugger.
- dthul 7y agoNot downvoting you because I think you bring up meaningful opinions. I have to say that I much prefer errors as values though. With exceptions I never know what I might get, with error values on the other hand I know exactly what I'll get. And the "?" operator makes it very low friction. It can sometimes be annoying to wrap error values into an appropriate type though, especially if you combine error types from multiple libraries
- couchand 7y ago> With exceptions I never know what I might get... Exactly this. It's just as Joel Spolsky wrote in that fifteen-year-old article that hit the front page yesterday: exceptions are an invisible goto. > It can sometimes be annoying to wrap error values into an appropriate type though, especially if you combine error types from multiple libraries For one-off code, the quick-error create is invaluable. For production code, I find this is one more indication of the value of the Rust philosophy. Forcing you to address the issue means you get a chance to thoughtfully consider what API you wish to offer your consumers. Most likely, you want to wrap the original errors so details of your dependencies don't become part of your public API.
- quotemstr 7y ago> Exactly this. It's just as Joel Spolsky wrote in that fifteen-year-old article that hit the front page yesterday: exceptions are an invisible goto. Exception semantics are well-defined. Exceptions clean up the stack, unlike longjmp and such, and in C++, you can mark which functions throw and which ones don't. When you write Rust code using Result everywhere and propagate all errors using "?", you end up with code that looks just like code that uses exceptions, but with extra syntax noise and decreased efficiency due to the need for runtime branching instead of exception dispatch tables. When you call a Rust function that can fail, do you carefully think through all the various failure paths and reason about everything from scratch? No. You call a function. The compiler complains, you insert a "?", and the compiler stops complaining. You don't reason about all possible errors, and you shouldn't have to reason about all possible errors. Exceptions free program logic on the common path from the mental overhead of the error path, and that's a good thing. Languages that start off boldly exception-free, like Rust and Go, end up reinventing the try/catch model because it turns out that exceptions are actually incredibly useful. As long as exceptions have been around, people have claimed that they've made code hard to follow. I reject these claims. They're just not consistent with my experience. In my experience, it's not difficult at all to understand control flow in exceptional systems, and there are many large C++ systems that you probably use all the time that work with exceptions without major problems. It's the weirdest thing: people who claim that exceptions make C++ unusable on Monday go on to write some Java or Python in Tuesday and don't seem to have immense cognitive difficulty in these languages. That you should avoid exceptions in C++ is obsolete conventional thinking from the 1990s era of bad compilers.