www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Possibility of adopting Rust's Error Handling?

reply mee6 <mee6 lookat.me> writes:
Rust's error handling is pretty good, I think they've proved the 
use of Result!(T, E). I was just always getting informative 
messages from the get go. I think there's a  nogc exception DIP 
in the works but I think this way of handling errors is better.

I won't go too much into detail of rust as this website does a 
good job of going over it.

https://doc.rust-lang.org/book/ch09-00-error-handling.html

Anyways this could be adopted instead of trying to get  nogc 
exceptions working. Rust uses exceptions but only for panic!() 
Which terminates the application. All it does is rewind the stack 
to see all the function calls for debugging pretty much.

I also think it works with chaining functions as that's what Rust 
does a lot too. They have a `?` operator that does basically this 
boiler plate code.

```d
auto result = expr;
if (result.isErr())
     return result;
```

D could implement this fairly easily and without much intrusion, 
but it would add a lot of value to be able to do something like:

```rust
auto value = chain()?.funcs()?;
```

While being  nogc and without using exceptions. Other than for 
panics.
Mar 31 2022
next sibling parent reply user1234 <user1234 12.de> writes:
On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting informative 
 messages from the get go. I think there's a  nogc exception DIP 
 in the works but I think this way of handling errors is better.

 I won't go too much into detail of rust as this website does a 
 good job of going over it.

 https://doc.rust-lang.org/book/ch09-00-error-handling.html

 Anyways this could be adopted instead of trying to get  nogc 
 exceptions working. Rust uses exceptions but only for panic!() 
 Which terminates the application. All it does is rewind the 
 stack to see all the function calls for debugging pretty much.

 I also think it works with chaining functions as that's what 
 Rust does a lot too. They have a `?` operator that does 
 basically this boiler plate code.

 ```d
 auto result = expr;
 if (result.isErr())
     return result;
 ```

 D could implement this fairly easily and without much 
 intrusion, but it would add a lot of value to be able to do 
 something like:

 ```rust
 auto value = chain()?.funcs()?;
 ```
yikes, I'd prefer if D could use `?` for [safe navigation].
 While being  nogc and without using exceptions. Other than for 
 panics.
[safe navigation]: https://en.wikipedia.org/wiki/Safe_navigation_operator
Mar 31 2022
next sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Thursday, 31 March 2022 at 21:35:00 UTC, user1234 wrote:
 On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting 
 informative messages from the get go. I think there's a  nogc 
 exception DIP in the works but I think this way of handling 
 errors is better.

 I won't go too much into detail of rust as this website does a 
 good job of going over it.

 https://doc.rust-lang.org/book/ch09-00-error-handling.html

 Anyways this could be adopted instead of trying to get  nogc 
 exceptions working. Rust uses exceptions but only for panic!() 
 Which terminates the application. All it does is rewind the 
 stack to see all the function calls for debugging pretty much.

 I also think it works with chaining functions as that's what 
 Rust does a lot too. They have a `?` operator that does 
 basically this boiler plate code.

 ```d
 auto result = expr;
 if (result.isErr())
     return result;
 ```

 D could implement this fairly easily and without much 
 intrusion, but it would add a lot of value to be able to do 
 something like:

 ```rust
 auto value = chain()?.funcs()?;
 ```
yikes, I'd prefer if D could use `?` for [safe navigation].
 While being  nogc and without using exceptions. Other than for 
 panics.
[safe navigation]: https://en.wikipedia.org/wiki/Safe_navigation_operator
Why not for both? `.?` and `??` could be overloadable operators like `opDot`, which when applied to pointers and class references will behave like they do in other languages, while structs could overload them to implement behavior like Rust's `Result` type.
Mar 31 2022
prev sibling parent reply mee6 <mee6 lookat.me> writes:
On Thursday, 31 March 2022 at 21:35:00 UTC, user1234 wrote:
 On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting 
 informative messages from the get go. I think there's a  nogc 
 exception DIP in the works but I think this way of handling 
 errors is better.

 I won't go too much into detail of rust as this website does a 
 good job of going over it.

 https://doc.rust-lang.org/book/ch09-00-error-handling.html

 Anyways this could be adopted instead of trying to get  nogc 
 exceptions working. Rust uses exceptions but only for panic!() 
 Which terminates the application. All it does is rewind the 
 stack to see all the function calls for debugging pretty much.

 I also think it works with chaining functions as that's what 
 Rust does a lot too. They have a `?` operator that does 
 basically this boiler plate code.

 ```d
 auto result = expr;
 if (result.isErr())
     return result;
 ```

 D could implement this fairly easily and without much 
 intrusion, but it would add a lot of value to be able to do 
 something like:

 ```rust
 auto value = chain()?.funcs()?;
 ```
yikes, I'd prefer if D could use `?` for [safe navigation].
 While being  nogc and without using exceptions. Other than for 
 panics.
[safe navigation]: https://en.wikipedia.org/wiki/Safe_navigation_operator
That is Rust's equivalent. https://en.m.wikipedia.org/wiki/Safe_navigation_operator#Rust
Mar 31 2022
parent user1234 <user1234 12.de> writes:
On Thursday, 31 March 2022 at 22:05:30 UTC, mee6 wrote:
 On Thursday, 31 March 2022 at 21:35:00 UTC, user1234 wrote:
 On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting 
 informative messages from the get go. I think there's a  nogc 
 exception DIP in the works but I think this way of handling 
 errors is better.

 I won't go too much into detail of rust as this website does 
 a good job of going over it.

 https://doc.rust-lang.org/book/ch09-00-error-handling.html

 Anyways this could be adopted instead of trying to get  nogc 
 exceptions working. Rust uses exceptions but only for 
 panic!() Which terminates the application. All it does is 
 rewind the stack to see all the function calls for debugging 
 pretty much.

 I also think it works with chaining functions as that's what 
 Rust does a lot too. They have a `?` operator that does 
 basically this boiler plate code.

 ```d
 auto result = expr;
 if (result.isErr())
     return result;
 ```

 D could implement this fairly easily and without much 
 intrusion, but it would add a lot of value to be able to do 
 something like:

 ```rust
 auto value = chain()?.funcs()?;
 ```
yikes, I'd prefer if D could use `?` for [safe navigation].
 While being  nogc and without using exceptions. Other than 
 for panics.
[safe navigation]: https://en.wikipedia.org/wiki/Safe_navigation_operator
That is Rust's equivalent. https://en.m.wikipedia.org/wiki/Safe_navigation_operator#Rust
yeah, nice. Everyone needs to see that and think twice. Is Rust awefull afterall ?
Apr 01 2022
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting informative 
 messages from the get go. I think there's a  nogc exception DIP 
 in the works but I think this way of handling errors is better.

 I won't go too much into detail of rust as this website does a 
 good job of going over it.

 https://doc.rust-lang.org/book/ch09-00-error-handling.html

 Anyways this could be adopted instead of trying to get  nogc 
 exceptions working. Rust uses exceptions but only for panic!() 
 Which terminates the application. All it does is rewind the 
 stack to see all the function calls for debugging pretty much.

 I also think it works with chaining functions as that's what 
 Rust does a lot too. They have a `?` operator that does 
 basically this boiler plate code.

 ```d
 auto result = expr;
 if (result.isErr())
     return result;
 ```

 D could implement this fairly easily and without much 
 intrusion, but it would add a lot of value to be able to do 
 something like:

 ```rust
 auto value = chain()?.funcs()?;
 ```

 While being  nogc and without using exceptions. Other than for 
 panics.
There is a lot of influences from Rust right now but I think we should be cautious adopting its features because I see more and more that many of the features don't age well. What is Rust error handling? Rust error handling is basically a tagged enum return type. Essentially it is a return value with some extra language built in features (like the ? mentioned). Problem with the Rust error handling is that you must use the same type for the entire call chain for it to work. Otherwise you must convert the error type or use a generic trait which dynamically allocated. Essentially you have the same problems as you would with return values. Its just an inferior error handling method compared to exceptions other than it might have better for performance. Versatility always comes at a cost. If you compare this with exceptions, they are much more versatile and the types can be infinitely expanded without even converting or alter an existing interface. Exceptions in D use TypeInfo (or RTTI in C++) in order to determine the error type. An advantage is that it uses polymorphism so that you can selectively choose the level which errors you want to catch. D has made exceptions even more convenient by adding scope guard so it is really a part of the language. I think that exceptions are superior to return values for the programmer. However there are performance bottlenecks. Instead D should focus on how to improve its exceptions, like looking if value exceptions could be beneficial, unnecessary locking, if they can be stored temporarily on stack instead of heap, how they can better work with the optimizer, include TypeInfo in better C so that exceptions work there.
Mar 31 2022
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Mar 31, 2022 at 09:46:53PM +0000, IGotD- via Digitalmars-d wrote:
[...]
 I think that exceptions are superior to return values for the
 programmer.
+1.
 However there are performance bottlenecks. Instead D should focus on
 how to improve its exceptions, like looking if value exceptions could
 be beneficial, unnecessary locking, if they can be stored temporarily
 on stack instead of heap, how they can better work with the optimizer,
 include TypeInfo in better C so that exceptions work there.
AIUI, D used to have its own implementation of exceptions that was more performant than libunwind. Sadly, that got junked in the name of C++ compatibility, so now we're stuck with libunwind along with all of its downfalls. In theory, if we're willing to accept ABI changes, we could replace the current libunwind-based implementation with a register-based status to indicate when an exception is thrown, and emit explicit branches for that. Then it would be the equivalent of error-code-based handling, except without the code uglification and the type constraints. T -- Computers are like a jungle: they have monitor lizards, rams, mice, c-moss, binary trees... and bugs.
Mar 31 2022
parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Thursday, 31 March 2022 at 22:00:17 UTC, H. S. Teoh wrote:
 AIUI, D used to have its own implementation of exceptions that 
 was more performant than libunwind.  Sadly, that got junked in 
 the name of C++ compatibility, so now we're stuck with 
 libunwind along with all of its downfalls.

 In theory, if we're willing to accept ABI changes, we could 
 replace the current libunwind-based implementation with a 
 register-based status to indicate when an exception is thrown, 
 and emit explicit branches for that. Then it would be the 
 equivalent of error-code-based handling, except without the 
 code uglification and the type constraints.


 T
Just wondering, would it be possible to use lubunwind, only in extern c++ declarations? I.e. we'd have own exception handling in D code, and C++ compliant exceptions in extern C++ one? This would mean that when d code interacts with c++ it will get translated into respective mechanism, from c++ if it is from c++ code called by D code, and into c++ one if it is from extern c++ d code that is called by c++ code. Alexandru
Apr 01 2022
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Apr 01, 2022 at 09:41:09AM +0000, Alexandru Ermicioi via Digitalmars-d
wrote:
[...]
 Just wondering, would it be possible to use lubunwind, only in extern
 c++ declarations?
 
 I.e. we'd have own exception handling in D code, and C++ compliant
 exceptions in extern C++ one?
 
 This would mean that when d code interacts with c++ it will get
 translated into respective mechanism, from c++ if it is from c++ code
 called by D code, and into c++ one if it is from extern c++ d code
 that is called by c++ code.
[...] That's what I'd propose. But Walter seems dead set against exceptions in general, so I dunno whether this will ever actually happen. T -- Lottery: tax on the stupid. -- Slashdotter
Apr 01 2022
prev sibling parent mee6 <mee6 lookat.me> writes:
On Thursday, 31 March 2022 at 21:46:53 UTC, IGotD- wrote:
 On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 [...]
There is a lot of influences from Rust right now but I think we should be cautious adopting its features because I see more and more that many of the features don't age well. What is Rust error handling? Rust error handling is basically a tagged enum return type. Essentially it is a return value with some extra language built in features (like the ? mentioned). Problem with the Rust error handling is that you must use the same type for the entire call chain for it to work. Otherwise you must convert the error type or use a generic trait which dynamically allocated. Essentially you have the same problems as you would with return values. Its just an inferior error handling method compared to exceptions other than it might have better for performance. Versatility always comes at a cost. If you compare this with exceptions, they are much more versatile and the types can be infinitely expanded without even converting or alter an existing interface.
Personally I think that's one of the reasons to not use it. Errors that are recoverable are finite. There's no good way to see exactly what it will throw. With return value handlingly you know exactly what you are getting. You could make it more generic or at multiple types. Errors shouldn't happen often and yes that would have to heap allocate but those are tradeoffs that can be looked over.
  D has made exceptions even more convenient by adding scope 
 guard so it is really a part of the language.

 I think that exceptions are superior to return values for the 
 programmer. However there are performance bottlenecks. Instead 
 D should focus on how to improve its exceptions, like looking 
 if value exceptions could be beneficial, unnecessary locking, 
 if they can be stored temporarily on stack instead of heap, how 
 they can better work with the optimizer, include TypeInfo in 
 better C so that exceptions work there.
Both can exist together, you can have a library implementation of Result. The feature for it is aldo a small convince but ultimately isn't required to get the benefits of result value error handling.
Mar 31 2022
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E)....
It has some warts still, that is why packages like these exist, https://docs.rs/thiserror/latest/thiserror/ https://docs.rs/anyhow/latest/anyhow/ To work around the boilerplate and lack of support in standard library when combining errors from different libraries. Rust still suffers from a npm like approach to stuff that should be part of the standard library for basic stuff, error definition, async runtimes, serialization,...
Mar 31 2022
parent mee6 <mee6 lookat.me> writes:
On Friday, 1 April 2022 at 06:17:53 UTC, Paulo Pinto wrote:
 On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E)....
It has some warts still, that is why packages like these exist, https://docs.rs/thiserror/latest/thiserror/ https://docs.rs/anyhow/latest/anyhow/ To work around the boilerplate and lack of support in standard library when combining errors from different libraries. Rust still suffers from a npm like approach to stuff that should be part of the standard library for basic stuff, error definition, async runtimes, serialization,...
Yes it seems they don't want to commit on those extensions. They seem to not want to define what an error is which leads to that problem. It can be avoided by including those things in the implementation details. C++ has an expect struct in the pipeline but it doesn't define what an error is either, nor how to handle multiple error types. That would need to be worked on as well.
Apr 01 2022
prev sibling next sibling parent reply mesni <mensikovk817 gmail.com> writes:
On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting informative 
 messages from the get go. I think there's a  nogc exception DIP 
 in the works but I think this way of handling errors is better.

 [...]
With an already existing Nullable it looks like this: ```d auto value = chain().get.funcs().get; ``` I don't see much difference
Apr 01 2022
parent reply mee6 <mee6 lookat.me> writes:
On Saturday, 2 April 2022 at 02:29:16 UTC, mesni wrote:
 On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting 
 informative messages from the get go. I think there's a  nogc 
 exception DIP in the works but I think this way of handling 
 errors is better.

 [...]
With an already existing Nullable it looks like this: ```d auto value = chain().get.funcs().get; ``` I don't see much difference
You don't get the error of why it is null to begin with, and it doesn't forward errors. It is quite different even if the syntax is similar.
Apr 02 2022
parent ryuukk_ <ryuukk.dev gmail.com> writes:
In my opinion Rust error handling is one of the worst

I much preffer Go/Zig/Odin, my favorite would be Odin's one

     f, err := os.open(...)
     if err != os.ERROR_NONE {
         // handle error
     }
     defer os.close(f) // will be executed at the end of the scope

Multiple returns is the trick!! simple, easy to read and handle, 
i can understand if one prefer exception sicne they bubble up, 
even though i think it encourages a lazy design of APIs, for 
that, then Zig's one will suits you better, since it's more 
strict about that part
Apr 02 2022
prev sibling parent mesni <mensikovk817 gmail.com> writes:
On Thursday, 31 March 2022 at 21:21:04 UTC, mee6 wrote:
 Rust's error handling is pretty good, I think they've proved 
 the use of Result!(T, E). I was just always getting informative 
 messages from the get go. I think there's a  nogc exception DIP 
 in the works but I think this way of handling errors is better.

 I won't go too much into detail of rust as this website does a 
 good job of going over it.

 https://doc.rust-lang.org/book/ch09-00-error-handling.html

 Anyways this could be adopted instead of trying to get  nogc 
 exceptions working. Rust uses exceptions but only for panic!() 
 Which terminates the application. All it does is rewind the 
 stack to see all the function calls for debugging pretty much.

 I also think it works with chaining functions as that's what 
 Rust does a lot too. They have a `?` operator that does 
 basically this boiler plate code.

 ```d
 auto result = expr;
 if (result.isErr())
     return result;
 ```

 D could implement this fairly easily and without much 
 intrusion, but it would add a lot of value to be able to do 
 something like:

 ```rust
 auto value = chain()?.funcs()?;
 ```

 While being  nogc and without using exceptions. Other than for 
 panics.
Moreover, here is an interesting trick ```d import std.stdio; import std.typecons; import std.exception; template ErrorGet(alias Func){ ref auto getn(T)(ref T n){ if(n.isNull) Func(0); return n.get(); } } alias PanicGet = ErrorGet!((a){assert(a);}); alias ThrowGet = ErrorGet!(enforce); void main(){ Nullable!int a; a = 8; with(PanicGet){ a.getn.writeln; } with(ThrowGet){ a.getn.writeln; } } ```
Apr 01 2022