Jump to page: 1 2
Thread overview
DIP 1011--extern(delegate)--Preliminary Review Round 1
Jul 14, 2017
Mike Parker
Jul 14, 2017
Jonathan Marler
Jul 14, 2017
Nicholas Wilson
Jul 14, 2017
Dmitry Olshansky
Jul 14, 2017
Jonathan Marler
Jul 16, 2017
Nicholas Wilson
Jul 17, 2017
Jonathan Marler
Jul 24, 2017
Nicholas Wilson
Jul 24, 2017
Andrea Fontana
Jul 25, 2017
Andrea Fontana
Jul 21, 2018
soolaïman
Jul 22, 2018
Jonathan Marler
July 14, 2017
DIP 1011 is titled "extern(delegate)".

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md

All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on July 28 (3:59 AM GMT July 29), or when I make a post declaring it complete.

At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round. Otherwise, it will be queued for the formal review and evaluation by the language authors.

Thanks in advance to all who participate.

Destroy!
July 14, 2017
On Friday, 14 July 2017 at 10:43:05 UTC, Mike Parker wrote:
> DIP 1011 is titled "extern(delegate)".

Looks good to me, useful, doesn't brake code, DIP seems correct.

July 14, 2017
On 7/14/17 6:43 AM, Mike Parker wrote:
> DIP 1011 is titled "extern(delegate)".
> 
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
> 
> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on July 28 (3:59 AM GMT July 29), or when I make a post declaring it complete.
> 
> At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round. Otherwise, it will be queued for the formal review and evaluation by the language authors.
> 
> Thanks in advance to all who participate.
> 
> Destroy!

It seems reasonable.

One concern I have is this:

extern(delegate) ref int foo(ref int x) { return x; }

int x;

auto dg = &x.foo; // is dg an int * or a delegate?

Currently, this means the former. I'm concerned about ambiguities and how to resolve them if all of a sudden someone decides it's a good idea to change their functions to extern(delegate), and code like this silently switches over. Or someone tries to form a delegate from one of these, but instead ends up calling the function instead.

-Steve
July 14, 2017
On Friday, 14 July 2017 at 10:43:05 UTC, Mike Parker wrote:
> DIP 1011 is titled "extern(delegate)".

Looks good!
July 14, 2017
On Friday, 14 July 2017 at 10:43:05 UTC, Mike Parker wrote:
> DIP 1011 is titled "extern(delegate)".
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>

 Contrary to  other poster I believe this is wrong way to solve a problem. A far simpler approach is to allow compiler implicitly convert function pointer to delegate. The dance with making an ABI wrapper can be left to compiler proper.

And no annotation hell.

---
Dmitry Olshansky
July 14, 2017
On 7/14/17 1:02 PM, Dmitry Olshansky wrote:
> On Friday, 14 July 2017 at 10:43:05 UTC, Mike Parker wrote:
>> DIP 1011 is titled "extern(delegate)".
>>
>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>>
> 
>   Contrary to  other poster I believe this is wrong way to solve a problem. A far simpler approach is to allow compiler implicitly convert function pointer to delegate. The dance with making an ABI wrapper can be left to compiler proper.
> 
> And no annotation hell.

But I think the idea is to avoid the extra indirection and call, no? We already have toDelegate, which works fine if you don't care about that.

-Steve
July 14, 2017
On Friday, 14 July 2017 at 12:52:56 UTC, Steven Schveighoffer wrote:
> On 7/14/17 6:43 AM, Mike Parker wrote:
>> DIP 1011 is titled "extern(delegate)".
>> 
>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>> 
>> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on July 28 (3:59 AM GMT July 29), or when I make a post declaring it complete.
>> 
>> At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round. Otherwise, it will be queued for the formal review and evaluation by the language authors.
>> 
>> Thanks in advance to all who participate.
>> 
>> Destroy!
>
> It seems reasonable.
>
> One concern I have is this:
>
> extern(delegate) ref int foo(ref int x) { return x; }
>
> int x;
>
> auto dg = &x.foo; // is dg an int * or a delegate?
>
> Currently, this means the former. I'm concerned about ambiguities and how to resolve them if all of a sudden someone decides it's a good idea to change their functions to extern(delegate), and code like this silently switches over. Or someone tries to form a delegate from one of these, but instead ends up calling the function instead.
>
> -Steve

I thought about this use case and it's an interesting one.

TLDR; it should return "int delegate()" not "int*"

First I want to say this use case happens less often then you might think. It's only a problem when the function has no arguments. If the function does have arguments then omitting the parameter list clearly means the application wants a delegate/function pointer. Currently, taking the address of a member function call will return a delegate, even if it returns a reference.

import std.stdio;
struct Foo
{
    static int staticInt;
    ref int bar()
    {
        return staticInt;
    }
}

Foo foo;
writeln(typeid(&foo.bar)); // prints "int delegate()"

// NOTE: If you want to take the address of the return value, you add the () to the call, i.e.
writeln(typeid(&foo.bar())); // prints "int*"

Furthermore, since taking the address of a UFCS call currently has no meaning, this would evaluate to int* if it was a UFCS call:

ref int baz(ref Foo foo)
{
    static int staticInt;
    return staticInt;
}
writeln(typeid(&foo.baz)); // prints "int*"

So the semantic analyzer has a precendence for the '&' operator when applied to "dotted" function calls.  It checks if the expression could result in a delegate, if not then it falls back to taking the address of the return value.

As you have noticed, since extern(delegate) adds meaning to taking the address of a UFCS call, the semantic analyzer will now be able to create a delegate in a place where it previously couldn't.

extern(delegate) ref int baz(ref Foo foo)
{
    static int staticInt;
    return staticInt;
}
writeln(typeid(&foo.baz)); // is it "int*" or "int delegate()"?

The implementation could go either way but I think it should be consistent with the semantics for delegates meaning it should result in "int delegate()" and here's why:

  * Having an inconsistent precedence for member functions and extern(delegate) functions would be confusing

  * If taking the address of the return value has precendence, we would have to come up with a new syntax when the application wants to do the opposite.  Currently, if the application really means they want to take the address of the return value, they can simply add an empty parameter list to disambiguate the meaning, i.e. they could use &foo.bar() instead of &foo.bar.  If we used the opposite precedence, there is currently no way to say we really want a delegate instead of taking the address of the return value.

  * If an existing project does start using extern(delegate), in almost all cases the change from taking the address of the return value to getting a delegate will almost always result in a compile time error.  In your example if the meaning of &x.foo changed, it would return a different type which would very likely be caught by the compiler, depending of course on how the value is used.  There are cases where it wouldn't be caught, but it's very unlikely.

  * This only affects code that goes back and modifies their application to use extern(delegate).  In other words, it's not breaking existing code unless that existing code itself changes to use this feature.
July 14, 2017
On 7/14/17 1:18 PM, Jonathan Marler wrote:
> On Friday, 14 July 2017 at 12:52:56 UTC, Steven Schveighoffer wrote:
>> On 7/14/17 6:43 AM, Mike Parker wrote:
>>> DIP 1011 is titled "extern(delegate)".
>>>
>>> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>>>
>>> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on July 28 (3:59 AM GMT July 29), or when I make a post declaring it complete.
>>>
>>> At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round. Otherwise, it will be queued for the formal review and evaluation by the language authors.
>>>
>>> Thanks in advance to all who participate.
>>>
>>> Destroy!
>>
>> It seems reasonable.
>>
>> One concern I have is this:
>>
>> extern(delegate) ref int foo(ref int x) { return x; }
>>
>> int x;
>>
>> auto dg = &x.foo; // is dg an int * or a delegate?
>>
>> Currently, this means the former. I'm concerned about ambiguities and how to resolve them if all of a sudden someone decides it's a good idea to change their functions to extern(delegate), and code like this silently switches over. Or someone tries to form a delegate from one of these, but instead ends up calling the function instead.
>>
> 
> I thought about this use case and it's an interesting one.
> 
> TLDR; it should return "int delegate()" not "int*"

I can say from experience, this can wreak havoc on things like template constraints. Changing behavior subtly for the same syntax has consequences.

I wonder if there should be a deprecation period. It's an odd case, because it only happens if the declaration is changed to extern(delegate), which means before the change would be introduced, no code would break.

But I fully see quite a few people doing this because people write a lot of UFCS functions these days, and slapping an extern(delegate): label for these functions might be just the blunt instrument people reach for.

I also see people doing &foo.someUFCSFunc without realizing it's not going to create a delegate. It may be obvious to the compiler that it's wrong, so they may still get an error. Where I see possible problems is things like template constraints (e.g. if(is(typeof(&foo.f) == int *)) )

However, we do have precedent that &func is different for @property functions vs. normal ones, so there is some validity to your chosen path. And the opposite choice (int *) would make it impossible to take a delegate to such a function.

-Steve
July 14, 2017
On Friday, 14 July 2017 at 17:02:37 UTC, Dmitry Olshansky wrote:
> ...The dance with making an ABI wrapper can be left to compiler proper.

This proposal doesn't make ABI wrappers, it changes the ABI of the function itself.
July 16, 2017
On Friday, 14 July 2017 at 10:43:05 UTC, Mike Parker wrote:
> DIP 1011 is titled "extern(delegate)".
>
> https://github.com/dlang/DIPs/blob/master/DIPs/DIP1011.md
>
> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on July 28 (3:59 AM GMT July 29), or when I make a post declaring it complete.
>
> At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round. Otherwise, it will be queued for the formal review and evaluation by the language authors.
>
> Thanks in advance to all who participate.
>
> Destroy!

Not that it is a requirement to consider fir this DIP, but how would this play with Vittorio's lambda Value capture DIP(?)?
« First   ‹ Prev
1 2