8 ms·
Result<T> -> throw/catch seems surprising and hard to walk back later. Why not use std::expected or a work-alike, and let the caller decide whether to throw an
by AprilArcus 6y ago
Result<T> -> throw/catch seems surprising and hard to walk back later. Why not use std::expected or a work-alike, and let the caller decide whether to throw an exception?
- singron 6y agoBeing a Googler project, I expected this to be a version of cxx that used StatusOr and -fno-exceptions.
- deleted 6y ago[deleted]
- joshuamorton 6y agoautoCXX is Google-y, but cxx doesn't appear to be, and enforcing noexcept in a general use tool seems ill-advised.
- steveklabnik 6y agoI am not sure, as I'm not the author. I can see it both ways, but I think I personally lean towards what you're saying.
- masklinn 6y agocxx is bidirectional so probably because the mapping needs to work both ways, and you will eventually have C++ -> Rust -> C++ where the "inner" C++ throwing would be expected to cause the "outer" C++ to catch? Not to mention as far as I know std::expected does not actually exist. It was first proposed 7 years ago but is still a proposal, now hoping for inclusion in C++23 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0323r9.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p032...)
- AprilArcus 6y ago> you will eventually have C++ -> Rust -> C++ where the "inner" C++ throwing would be expected to cause the "outer" C++ to catch? Look I hate to be that girl with the strong opinions on the orange website, but "goto is not an appropriate feature for an ffi" is a hill I'm ready to die on.
- CyberRabbi 6y agoExceptions are not “goto.” Exceptions are an example of “structured control flow” while “goto” certainly is not. Throwing an exception is an example of a “non local exit” which Rust also implements (in terms of “Return”). Also the exception does not leak into rust-space. Like it or not, any serious c++ ffi must accommodate C++ exceptions, since that is a standard feature (not to mention idiomatic error signaling mechanism) in C++.
- AprilArcus 6y ago> Throwing an exception is an example of a “non local exit” which Rust also implements (in terms of “Return”). They are not isomorphic. Return always hands control back to the caller; you can emerge from an exception inside any arbitrarily higher scope, and the proliferation of weird edge cases (what happens when I throw an uncaught exception in a constructor or destructor, the exception safety guarantee hierarchy) are good evidence for why this behavior is too complicated for its own good. > Like it or not, any serious c++ ffi must accommodate C++ exceptions Obviously this is the case and I'm not trying to say otherwise. I already said so upthread, but it seems to me that the least complicated way to do so is to wrap wrap foreign C++ function return values in a Result<T> (unless they can be statically proven not to throw), and report errors to C++ through some kind of Either-ish box. Then the C++ caller can decide whether they want to handle the error then and there, or throw an "idiomatic" exception.
- CyberRabbi 6y ago>> Throwing an exception is an example of a “non local exit” which Rust also implements (in terms of “Return”). > They are not isomorphic. It was never claimed that “return” and “throw” were isomorphic. Only that they are both examples of non-local exits. > good evidence for why this behavior is too complicated for its own good. That’s a nice opinion but I wouldn’t consider that evidence except under the loosest definitions of the word. By the same reasoning I could claim that being able to invoke “return” at any arbitrary point in the function is evidence that return is a complicated feature. Just like “return” exceptions in C++ have a statically defined set of areas they can branch to and the invocation of throw is well defined w.r.t. to object cleanup. Admittedly those landing sites are more numerous than “return” but not different in their more defining properties.
- MaulingMonkey 6y agoIndeed. I'd expect panics -> throw/catch -> panics... - since those both unwind the stack until they reach a handler by default - but Result -> throw/catch? No way. Making a work-alike and calling it rust::Result would be much more appropriate IMO. Even setting aside personal taste, some gamedev platforms - even in $(CURRENTYEAR) - still default to C++ exceptions being disabled. And may throw linker errors if you try to enable exceptions, while linking any closed source third party libraries that were built with default exceptionless build settings. I've rewritten my share of exception-based error handling - just to sanely port across platforms - as a result. It's just as well - I've fixed enough bugs where exceptions propigate across a C ABI to consider them UB-bait. There's a reason Rust lets you configure panic="abort", and a reason it gives you Result s without magic unwinding semantics, and a reason why a lot of C++ codebases have ended up with some kind of custom Result-alike.