May 19, 2012
"Mehrdad" <wfunction@hotmail.com> wrote in message news:ifswigmcenyryxzyvbpv@forum.dlang.org...
> On Friday, 18 May 2012 at 18:59:23 UTC, Steven Schveighoffer wrote:
>> On Fri, 18 May 2012 14:30:46 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 5/18/12 1:22 PM, Mehrdad wrote:
>>>> My brain just exploded.
>>>> Can someone explain what's going on?
>>>>
>>>> class Test
>>>> {
>>>> public void foo() { }
>>>> }
>>>>
>>>> static assert(is(typeof(&Test.foo) == void function()));
>>>
>>> Looks like a bug. The assert should pass only if foo were static.
>>
>> No, this is not a bug.
>>
>> The purpose is so you can get the function pointer portion of a delegate without an instance of the object.
>
> I actually realized that might be the reason before I reported this, but then I thought:
>
> In that case, shouldn't the 'this' parameter be explicitly part of the function (at the end of the parameter list)?

No, that won't work in all cases due to the ordering of parameters, 'this' and the hidden struct pointer.


May 19, 2012
On Saturday, 19 May 2012 at 01:37:54 UTC, Daniel Murphy wrote:
> No, that won't work in all cases due to the ordering of parameters, 'this' and the hidden struct pointer.

Better than not working in /any/ cases lol. :P

Maybe you can add a void* for the hidden struct parameter? idk...
May 19, 2012
"Mehrdad" <wfunction@hotmail.com> wrote in message news:sxiwbwuwvcjrlvpfsgpi@forum.dlang.org...
> On Saturday, 19 May 2012 at 01:37:54 UTC, Daniel Murphy wrote:
>> No, that won't work in all cases due to the ordering of parameters, 'this' and the hidden struct pointer.
>
> Better than not working in /any/ cases lol. :P
>
> Maybe you can add a void* for the hidden struct parameter? idk...

I'd actually rather it /didn't/ work in any cases, and just returned void*. The .funcptr property of delegates too.  From what I can tell the main use of this 'feature' is to cause nasty bugs whenever somebody accidentally takes the address of a non-static member function without an instance. Last time I checked, phobos uses this in a couple of places to see if a member function can be called with a specific set of args, but this can be replaced with S.init.func(...).  There is an existing bug report for this somewhere.


May 19, 2012
On Saturday, 19 May 2012 at 02:38:11 UTC, Daniel Murphy wrote:
> I'd actually rather it /didn't/ work in any cases, and just returned void*.

Well if that's an option then I like that too.
May 19, 2012
Le 19/05/2012 03:37, Daniel Murphy a écrit :
> "Mehrdad"<wfunction@hotmail.com>  wrote in message
> news:ifswigmcenyryxzyvbpv@forum.dlang.org...
>> On Friday, 18 May 2012 at 18:59:23 UTC, Steven Schveighoffer wrote:
>>> On Fri, 18 May 2012 14:30:46 -0400, Andrei Alexandrescu
>>> <SeeWebsiteForEmail@erdani.org>  wrote:
>>>
>>>> On 5/18/12 1:22 PM, Mehrdad wrote:
>>>>> My brain just exploded.
>>>>> Can someone explain what's going on?
>>>>>
>>>>> class Test
>>>>> {
>>>>> public void foo() { }
>>>>> }
>>>>>
>>>>> static assert(is(typeof(&Test.foo) == void function()));
>>>>
>>>> Looks like a bug. The assert should pass only if foo were static.
>>>
>>> No, this is not a bug.
>>>
>>> The purpose is so you can get the function pointer portion of a delegate
>>> without an instance of the object.
>>
>> I actually realized that might be the reason before I reported this, but
>> then I thought:
>>
>> In that case, shouldn't the 'this' parameter be explicitly part of the
>> function (at the end of the parameter list)?
>
> No, that won't work in all cases due to the ordering of parameters, 'this'
> and the hidden struct pointer.
>
>

extern(this) and you are done expressing thiscall.
May 19, 2012
Le 18/05/2012 22:35, Andrei Alexandrescu a écrit :
> On 5/18/12 1:59 PM, Steven Schveighoffer wrote:
>> On Fri, 18 May 2012 14:30:46 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 5/18/12 1:22 PM, Mehrdad wrote:
>>>> My brain just exploded.
>>>> Can someone explain what's going on?
>>>>
>>>> class Test
>>>> {
>>>> public void foo() { }
>>>> }
>>>>
>>>> static assert(is(typeof(&Test.foo) == void function()));
>>>
>>> Looks like a bug. The assert should pass only if foo were static.
>>
>> No, this is not a bug.
>
> It is.
>
>> The purpose is so you can get the function pointer portion of a delegate
>> without an instance of the object.
>
> Typing is what it is. The following program is unsound without a cast in
> sight:
>
> class Test
> {
> void foo() { writeln("foo"); }
> }
>
> static assert(is(typeof(&Test.foo) == void function()));
>
> void fun()
> {
> writeln("fun");
> }
>
> void main() {
> alias void function() TFun;
> TFun a = &fun;
> a();
> a = &Test.foo;
> a();
> }
>
> At best things could be arranged that &Test.foo has type void
> function(Test) or something.
>
>
> Andrei

It would be nice, but require a way to express that calling convention (thiscall is often different than simply passing an argument).

I proposed extern(this).

This would have the extra benefice of being able to declare UFCS with thiscall convention.

If the extern isn't added, the feature must go, it is made to write bugs.
May 22, 2012
On Fri, 18 May 2012 16:35:38 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 5/18/12 1:59 PM, Steven Schveighoffer wrote:
>> On Fri, 18 May 2012 14:30:46 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 5/18/12 1:22 PM, Mehrdad wrote:
>>>> My brain just exploded.
>>>> Can someone explain what's going on?
>>>>
>>>> class Test
>>>> {
>>>> public void foo() { }
>>>> }
>>>>
>>>> static assert(is(typeof(&Test.foo) == void function()));
>>>
>>> Looks like a bug. The assert should pass only if foo were static.
>>
>> No, this is not a bug.
>
> It is.

Poor design?  Yes.  Bug? no.  It's behavior is very intentional and has been discussed several times over the last several years.  It's existed before D2 was even branched, at least since I learned D in 2007.

>> The purpose is so you can get the function pointer portion of a delegate
>> without an instance of the object.
>
> Typing is what it is. The following program is unsound without a cast in sight:
>
> class Test
> {
>      void foo() { writeln("foo"); }
> }
>
> static assert(is(typeof(&Test.foo) == void function()));
>
> void fun()
> {
>      writeln("fun");
> }
>
> void main() {
>      alias void function() TFun;
>      TFun a = &fun;
>      a();
>      a = &Test.foo;
>      a();
> }

I agree, it's unsound.  But so is this:

int *blah = void;

*blah = 5;

It doesn't mean that the language should forbid it, or that the compiler isn't implemented as designed.

At the *very least*, the address to member function operation should be illegal in @safe code.

> At best things could be arranged that &Test.foo has type void function(Test) or something.

I would suggest that it should be:

function(Test this) with the 'this' being mangled into the name, and affect the calling convention.

Structs would be function(ref Test this).

And const/shared/immutable decorations should apply properly to the 'this' parameter.

I'd wholeheartedly support such an improvement.  In fact, I'd be willing to write a DIP on it, if Walter had a chance of approving it.  I just don't know if it would happen...

-Steve
May 22, 2012
On 2012-05-22 20:14, Steven Schveighoffer wrote:

> I agree, it's unsound. But so is this:
>
> int *blah = void;
>
> *blah = 5;
>
> It doesn't mean that the language should forbid it, or that the compiler
> isn't implemented as designed.
>
> At the *very least*, the address to member function operation should be
> illegal in @safe code.
>
>> At best things could be arranged that &Test.foo has type void
>> function(Test) or something.
>
> I would suggest that it should be:
>
> function(Test this) with the 'this' being mangled into the name, and
> affect the calling convention.
>
> Structs would be function(ref Test this).
>
> And const/shared/immutable decorations should apply properly to the
> 'this' parameter.
>
> I'd wholeheartedly support such an improvement. In fact, I'd be willing
> to write a DIP on it, if Walter had a chance of approving it. I just
> don't know if it would happen...
>
> -Steve

It needs to be possible to compose delegates:

class Foo
{
    void foo () {};
}

void delegate () dg;

dg.funcptr = &Foo.foo;
dg.ptr = cast(void*) new Foo;
dg();

At least it needs to be possible to do that in code marked with @system.

-- 
/Jacob Carlborg
May 22, 2012
On Tue, 22 May 2012 14:28:33 -0400, Jacob Carlborg <doob@me.com> wrote:

> On 2012-05-22 20:14, Steven Schveighoffer wrote:
>
>> I would suggest that it should be:
>>
>> function(Test this) with the 'this' being mangled into the name, and
>> affect the calling convention.
>>
>> Structs would be function(ref Test this).
>>
>> And const/shared/immutable decorations should apply properly to the
>> 'this' parameter.
>>
>> I'd wholeheartedly support such an improvement. In fact, I'd be willing
>> to write a DIP on it, if Walter had a chance of approving it. I just
>> don't know if it would happen...
>>
>
> It needs to be possible to compose delegates:
>
> class Foo
> {
>      void foo () {};
> }
>
> void delegate () dg;
>
> dg.funcptr = &Foo.foo;

Error, cannot cast function of type void function(Foo this) to void function(void *this)

dg.funcptr = cast(void function(void *this))&Foo.foo; // ok

> dg.ptr = cast(void*) new Foo;
> dg();
>
> At least it needs to be possible to do that in code marked with @system.
>

I think it should require a cast, regardless of the @system attribute, you are telling the type system a function that requires a Foo is now OK to accept a void *.  I don't think that's something we should accept implicitly.

-Steve
May 22, 2012
On 2012-05-22 20:35, Steven Schveighoffer wrote:

>> It needs to be possible to compose delegates:
>>
>> class Foo
>> {
>> void foo () {};
>> }
>>
>> void delegate () dg;
>>
>> dg.funcptr = &Foo.foo;
>
> Error, cannot cast function of type void function(Foo this) to void
> function(void *this)
>
> dg.funcptr = cast(void function(void *this))&Foo.foo; // ok
>
>> dg.ptr = cast(void*) new Foo;
>> dg();
>>
>> At least it needs to be possible to do that in code marked with @system.
>>
>
> I think it should require a cast, regardless of the @system attribute,
> you are telling the type system a function that requires a Foo is now OK
> to accept a void *. I don't think that's something we should accept
> implicitly.
>
> -Steve

I have no problem with a couple of case, as long as it's possible to compose delegates as above. The example was just how it works today, and an explanation of what I meant by "composing delegates". This can be of great help when interfacing with other language. I used this technique to call D methods from Objective-C.

-- 
/Jacob Carlborg