www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Alternative to DIP1032

reply Steven Schveighoffer <schveiguy gmail.com> writes:
I wanted to make this a separate post, because it doesn't discuss 
DIP1032 really at all. My opinion on DIP1032 is that the solution is too 
much of a breaking change, and adds more WTF to D to be accepted. I 
don't really know how to fix it except for opting-in to the feature.

But maybe there's another way. I've read a bunch of posts on this, and 
I'm wondering if we can make something else work.

as inspired by this comment: 
https://github.com/dlang/DIPs/pull/170#issuecomment-550073583

What if, we designate "overriding" attributes for a delegate or function 
parameter? In essence, the function is treated at the call site as if 
the delegate is always called, and the function itself adjusts its 
attributes to match that of the delegate.

Let's add a new attribute __called. Forget the name, I just need it for 
demonstration:

int foo(__called void delegate() dg)  safe pure  nogc;

I've left out nothrow for a good reason I'll discuss later.

Now, if you call foo with a  system delegate, foo becomes  system. If 
you call foo with an impure delegate, foo becomes impure. If you call it 
with a gc-allocating delegate, foo becomes gc-allocating.

The reason is because there is no actual difference in these attributes 
in term of how the function is implemented, the differences are purely 
semantic. Inside the function, the only thing that pure does is make it 
so you can't call impure functions. If you remove the restriction based 
on the attributes of the delegate, the function implementation should be 
the same. Same thing for  safe and  nogc.

nothrow is different, because the actual implementation of the function 
is different (stack unwinding doesn't need to happen). So I don't think 
you can have the same function implemented inside for both throwing and 
nothrow functions. I'm too ignorant of the requirements to be sure, 
maybe someone else can chime in.

Another problem is pure functions that forward the delegate to another 
pure function would have to also have a __called delegate that is 
passed, and they would NOT be able to be optimized based on purity (i.e. 
they could not be treated as "strong pure") for that call.

Just a thought to throw out and see if it sticks.

-Steve
Apr 03 2020
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Friday, 3 April 2020 at 15:47:19 UTC, Steven Schveighoffer 
wrote:
 [snip]
Won't it be confusing to people that an attribute won't always mean what it says?
Apr 03 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/3/20 1:09 PM, jmh530 wrote:
 On Friday, 3 April 2020 at 15:47:19 UTC, Steven Schveighoffer wrote:
 [snip]
Won't it be confusing to people that an attribute won't always mean what it says?
Possibly. But the problem is that in order for this to work, everything *else* in the function must be compiled according to the stated attribute. It's just the delegate call that can trump the stated ones. So you can't just leave the attribute off. The message for the failure also can be adjusted to be clearer. e.g.: "Error calling `foo(someDelegate)` is not allowed in ` safe` function `bar`. `foo` is assumed ` system` due to delegate `someDelegate`." Another mechanism would be to flag the tagged attributes as being "overridable" somehow by the delegate. I think the concept is sound, but how to achieve, I don't really know the best way. -Steve
Apr 03 2020