www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Discussion Thread: DIP 1029--Add throw as Function Attribute--Final

reply Mike Parker <aldacron gmail.com> writes:
This is the discussion thread for the Final Review of DIP 1029, 
"Add throw as Function Attribute":

https://github.com/dlang/DIPs/blob/9db80ddadcf5a220958ddcfec14b9c71cdb43d1c/DIPs/DIP1029.md

The review period will end at 11:59 PM ET on May 1, or when I 
make a post declaring it complete. Discussion in this thread may 
continue beyond that point.

Here in the discussion thread, you are free to discuss anything 
and everything related to the DIP. Express your support or 
opposition, debate alternatives, argue the merits, etc.

However, if you have any specific feedback on how to improve the 
proposal itself, then please post it in the feedback thread. The 
feedback thread will be the source for the review summary I write 
at the end of this review round. I will post a link to that 
thread immediately following this post. Just be sure to read and 
understand the Reviewer Guidelines before posting there:

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

And my blog post on the difference between the Discussion and 
Feedback threads:

https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/

Please stay on topic here. I will delete posts that are 
completely off-topic.
Apr 17
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 17 April 2020 at 11:28:05 UTC, Mike Parker wrote:

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post.
The feedback thread is here: https://forum.dlang.org/post/qhtqeavhyzjfamhgcjjl forum.dlang.org
Apr 17
parent reply James Lu <jamtlu gmail.com> writes:
On Friday, 17 April 2020 at 11:31:21 UTC, Mike Parker wrote:
 On Friday, 17 April 2020 at 11:28:05 UTC, Mike Parker wrote:

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post a 
 link to that thread immediately following this post.
The feedback thread is here: https://forum.dlang.org/post/qhtqeavhyzjfamhgcjjl forum.dlang.org
If I understand correctly, nothrow functions may throw Errors, but throw functions may throw Errors and Exceptions? If a nothrow function throws an Error, may the outer function catch it in a well-defined manner?
Apr 17
parent FeepingCreature <feepingcreature gmail.com> writes:
On Friday, 17 April 2020 at 12:58:56 UTC, James Lu wrote:
 On Friday, 17 April 2020 at 11:31:21 UTC, Mike Parker wrote:
 On Friday, 17 April 2020 at 11:28:05 UTC, Mike Parker wrote:

 However, if you have any specific feedback on how to improve 
 the proposal itself, then please post it in the feedback 
 thread. The feedback thread will be the source for the review 
 summary I write at the end of this review round. I will post 
 a link to that thread immediately following this post.
The feedback thread is here: https://forum.dlang.org/post/qhtqeavhyzjfamhgcjjl forum.dlang.org
If a nothrow function throws an Error, may the outer function catch it in a well-defined manner?
Catching `Error` is always undefined. That's why nothrow may throw them in the first place.
Apr 17
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
No objection to it as written, but there have been zero changes 
to the text between this review and the last, except adding the 
summary of the (apparently ignored by the author) previous round.

What's the point of going over an identical document again?
Apr 17
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/17/20 8:52 AM, Adam D. Ruppe wrote:
 No objection to it as written, but there have been zero changes to the 
 text between this review and the last, except adding the summary of the 
 (apparently ignored by the author) previous round.
There is a difference between ignored and advice considered and not taken. Though I think in at least one case (I posted on the review thread) something important was missed. -Steve
Apr 17
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 17 April 2020 at 14:39:26 UTC, Steven Schveighoffer 
wrote:
 There is a difference between ignored and advice considered and 
 not taken.
But even if it was all simply not taken, I'm OK with a response "I don't care, take it or leave it" (though two of the bullets don't even have that, just nothing)... but why are we wasting our time doing a discussion thread to review the same document again? Again, the text is *identical* to the last review, so what does the DIP manager expect from us this time that would be any different than last time? We complain that newsgroup discussions go in circles. Well, this is literally called a "round" lol, but it just seems ridiculous.
Apr 17
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/17/20 1:01 PM, Adam D. Ruppe wrote:
 On Friday, 17 April 2020 at 14:39:26 UTC, Steven Schveighoffer wrote:
 There is a difference between ignored and advice considered and not 
 taken.
But even if it was all simply not taken, I'm OK with a response "I don't care, take it or leave it" (though two of the bullets don't even have that, just nothing)... but why are we wasting our time doing a discussion thread to review the same document again?
I think it's just part of the red tape we created for ourselves! But it also gives the chance to reiterate the importance of advice not taken, or rephrase the argument in a way that is more convincing.
 Again, the text is *identical* to the last review, so what does the DIP 
 manager expect from us this time that would be any different than last 
 time?
This is how things like this work. There are responses to the points made, and Walter didn't make any changes based on that. It would also be possible to amend the DIP process such that if no changes are made before final review, it goes straight to formal assessment. Might not be a bad idea. It would save time too. The document is here: https://github.com/dlang/DIPs/blob/master/docs/process-reviews.md#final-review It says:
 The purpose of the Final Review is to provide one final opportunity to examine
the revisions made in response to the Community Review rounds and further
refine the DIP as necessary.
So, just amend that to say "If no revisions were made in response to the Community reviews, the DIP manager may forego the Final Review stage". -Steve
Apr 17
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Friday, 17 April 2020 at 17:01:31 UTC, Adam D. Ruppe wrote:
 On Friday, 17 April 2020 at 14:39:26 UTC, Steven Schveighoffer 
 wrote:
 There is a difference between ignored and advice considered 
 and not taken.
But even if it was all simply not taken, I'm OK with a response "I don't care, take it or leave it" (though two of the bullets don't even have that, just nothing)... but why are we wasting our time doing a discussion thread to review the same document again? Again, the text is *identical* to the last review, so what does the DIP manager expect from us this time that would be any different than last time? We complain that newsgroup discussions go in circles. Well, this is literally called a "round" lol, but it just seems ridiculous.
Please start a new thread if you want to discuss the DIP process and let's keep this one focused on the DIP. Thanks!
Apr 17
prev sibling next sibling parent James Lu <jamtlu gmail.com> writes:
On Friday, 17 April 2020 at 11:28:05 UTC, Mike Parker wrote:
 This is the discussion thread for the Final Review of DIP 1029, 
 "Add throw as Function Attribute":

 [...]
Have the ideas below been discussed? - an attribute "exception_aware": does the function body use catch or throw? - using "!!" to designate attribute remove: !!pure, !!nothrow. It is visible, it is explicit.
Apr 17
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2020-04-17 13:28, Mike Parker wrote:
 This is the discussion thread for the Final Review of DIP 1029, "Add 
 throw as Function Attribute":
 
 https://github.com/dlang/DIPs/blob/9db80ddadcf5a220958ddcfec14b9c71cdb4
d1c/DIPs/DIP1029.md 
I would like to see the "throw" keyword being used as an attribute to implement something like "Zero-overhead deterministic exceptions: Throwing values" [1]. I imagine it looking something like this: enum CopyError { permissionDenied } void copy(string src, string dest) throw(CopyError) { throw CopyError.permissionDenied; } void main() { try copy("foo", "bar"); catch (CopyError e) writeln(e); } Which would be lowered to something like the equivalent of the following code: struct Result(Value, Error) { bool isValue; union { Value value; Error error; } this(Value value) { this.value = value; isValue = true; } this(Error errro) { this.error = error; isValue = true; } } Result!(void, CopyError) copy(string src, string dest) { return Result!(void, CopyError)(CopyError.permissionDenied); } void main() { auto result = copy("foo", "bar"); if (!result.isValue) goto L1; L1: writeln(result.error); } [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf -- /Jacob Carlborg
Apr 18
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 18 April 2020 at 12:03:46 UTC, Jacob Carlborg wrote:
 Result!(void, CopyError) copy(string src, string dest)
 {
     return Result!(void, CopyError)(CopyError.permissionDenied);
 }

 void main()
 {
     auto result = copy("foo", "bar");

     if (!result.isValue)
         goto L1;
     L1:
         writeln(result.error);
 }
The big downside of this compared to exceptions is that you can forget to check the return value of `copy`, whereas exceptions cannot be ignored. respectively to force the programmer to check the return value. Without something equivalent in D, using algebraic data types for error handling is not really a viable approach.
Apr 18
parent Sebastiaan Koppe <mail skoppe.eu> writes:
On Saturday, 18 April 2020 at 14:02:46 UTC, Paul Backus wrote:
 On Saturday, 18 April 2020 at 12:03:46 UTC, Jacob Carlborg 
 wrote:
 void main()
 {
     auto result = copy("foo", "bar");

     if (!result.isValue)
         goto L1;
     L1:
         writeln(result.error);
 }
The big downside of this compared to exceptions is that you can forget to check the return value of `copy`, whereas exceptions cannot be ignored.
That part was only the lowered code.
Apr 18
prev sibling parent reply NaN <divide by.zero> writes:
On Saturday, 18 April 2020 at 12:03:46 UTC, Jacob Carlborg wrote:
 On 2020-04-17 13:28, Mike Parker wrote:
 This is the discussion thread for the Final Review of DIP 
 1029, "Add throw as Function Attribute":
 
 https://github.com/dlang/DIPs/blob/9db80ddadcf5a220958ddcfec14b9c71cdb43d1c/DIPs/DIP1029.md
I would like to see the "throw" keyword being used as an attribute to implement something like "Zero-overhead deterministic exceptions: Throwing values" [1]. I imagine it looking something like this: enum CopyError { permissionDenied } void copy(string src, string dest) throw(CopyError) { throw CopyError.permissionDenied; } void main() { try copy("foo", "bar"); catch (CopyError e) writeln(e); } Which would be lowered to something like the equivalent of the following code:
You could have the caller pass an alternate return address to the callee. So... void copy(string src, string dest, void* err) { if (somethingbad) { EAX = errorcode; RET (to) err; } *** } void main() { auto result = copy("foo", "bar", &L1); return; L1: writeln("Oh noes!"); } *** So all the callee has to do is poke the alternate return address into the stack and RET as normal. (On x86 at least).
Apr 18
parent Panke <tobias pankrath.net> writes:
On Saturday, 18 April 2020 at 16:28:59 UTC, NaN wrote:
 You could have the caller pass an alternate return address to 
 the callee. So...

 void copy(string src, string dest, void* err)
 {
     if (somethingbad) { EAX = errorcode; RET (to) err; } ***
 }

 void main()
 {
     auto result = copy("foo", "bar", &L1);

     return;

     L1: writeln("Oh noes!");
 }

 *** So all the callee has to do is poke the alternate return 
 address into the stack and RET as normal. (On x86 at least).
A paper describing the idea. https://dl.acm.org/doi/pdf/10.1145/1016848.1016864 I thought there was a more practical one, but only found this.
May 05
prev sibling parent reply Tove <tove fransson.se> writes:
On Friday, 17 April 2020 at 11:28:05 UTC, Mike Parker wrote:
 This is the discussion thread for the Final Review of DIP 1029, 
 "Add throw as Function Attribute":
On Tuesday, 5 May 2020 at 14:39:24 UTC, Petar Kirov [ZombineDev] wrote:
 Otherwise, I'd say that the best solution, which I think Andrei 
 agreed with [1] is `attribute(true)` and `attribute(false)` or 
 more generally: `attribute(boolExpr)`.

 [1]: https://forum.dlang.org/post/mknspb$1dgl$1 digitalmars.com
Good digging! I agree with you and Andrei, but using template syntax would be an additional improvement, it's not about saving one char, but avoiding matching () in the common case. attribute!true attribute!false attribute!(boolExpr)
May 05
parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 5 May 2020 at 15:30:38 UTC, Tove wrote:
 Good digging! I agree with you and Andrei, but using template 
 syntax would be an additional improvement, it's not about 
 saving one char, but avoiding matching () in the common case.

 attribute!true
 attribute!false
 attribute!(boolExpr)
It seems more confusing to me to use template syntax for something that isn't a template. We already use parentheses for stuff like `extern(C)`. Using them for function attributes is a natural extension of that.
May 05
next sibling parent Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Tuesday, 5 May 2020 at 15:55:30 UTC, Paul Backus wrote:
 On Tuesday, 5 May 2020 at 15:30:38 UTC, Tove wrote:
 Good digging! I agree with you and Andrei, but using template 
 syntax would be an additional improvement, it's not about 
 saving one char, but avoiding matching () in the common case.

 attribute!true
 attribute!false
 attribute!(boolExpr)
It seems more confusing to me to use template syntax for something that isn't a template. We already use parentheses for stuff like `extern(C)`. Using them for function attributes is a natural extension of that.
If we turn the existing function attributes into compiler recognized UDAs, the template version is one char shorter: version (A) { struct nogc { bool enabled; } void foo() (nogc(true)) { } } else version (B) { struct nogc(bool enabled) { } void foo() (nogc!true) { } } ;)
May 05
prev sibling parent Tove <tove fransson.se> writes:
On Tuesday, 5 May 2020 at 15:55:30 UTC, Paul Backus wrote:
 On Tuesday, 5 May 2020 at 15:30:38 UTC, Tove wrote:
 Good digging! I agree with you and Andrei, but using template 
 syntax would be an additional improvement, it's not about 
 saving one char, but avoiding matching () in the common case.

 attribute!true
 attribute!false
 attribute!(boolExpr)
It seems more confusing to me to use template syntax for something that isn't a template. We already use parentheses for stuff like `extern(C)`. Using them for function attributes is a natural extension of that.
It's not a function either and extern!C would be fine with me. IIRC `extern(C)` existed long before the single argument template syntax. It may appear a minor feature, but I miss it a lot when forced to use other languages.
May 05