www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2557] New: inconsistent behavior when taking reference to member without instance

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557

           Summary: inconsistent behavior when taking reference to member
                    without instance
           Product: D
           Version: 1.037
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: d brian.codekitchen.net


See attached test case. When the current context has no 'this', taking a
reference to a member function works correctly. However inside another class'
instance method, the same code throws an error, seemingly trying to
automatically apply the current 'this' even though I'm trying to take a
function, not a delegate.

The inconsistent behavior is buggy. I would argue towards allowing the
reference to be taken in the 'this' instance, since it can be useful when
building up delegates as shown in the test case. Obviously pointless here, but
I discovered the bug when trying to refactor my code for walking over a
collection calling a given method after applying a filtering function, so there
is real-world call for doing this.


-- 
Jan 05 2009
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #1 from d brian.codekitchen.net  2009-01-05 09:50 -------
Created an attachment (id=285)
 --> (http://d.puremagic.com/issues/attachment.cgi?id=285&action=view)
test case


-- 
Jan 05 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557


smjg iname.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg iname.com
           Keywords|                            |accepts-invalid




------- Comment #2 from smjg iname.com  2009-01-11 17:28 -------
It doesn't work.  "works" means "behaves correctly", not "compiles without
error".

The code is wrong regardless of whether dofun is static or not.  A.fun needs an
object of type A.  But it doesn't have one.

----------
bz2557.d(21): Error: this for fun needs to be type A not type method_ref.B
bz2557.d(21): Error: cannot implicitly convert expression (&this.fun) of type
void delegate() to void function()
----------


-- 
Jan 11 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #3 from 2korden gmail.com  2009-01-11 17:42 -------
(In reply to comment #2)
 The code is wrong regardless of whether dofun is static or not.  A.fun needs an
 object of type A.  But it doesn't have one.
 

I'm not so sure. Object of type A is provided by these two lines of code: A a = new A; dg2.ptr = cast(void*)a; --
Jan 11 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #4 from smjg iname.com  2009-01-11 19:09 -------
But your code tries to use &A.fun, not &a.fun.  For &A.fun to make any sense
with A being a type, fun would have to be a static method of A.


-- 
Jan 11 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #5 from 2korden gmail.com  2009-01-12 00:26 -------
That's a feature! Even if method is not static, it still has a single unique
body. If so, why can't you take its address?


-- 
Jan 11 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #6 from smjg iname.com  2009-01-12 03:09 -------
(In reply to comment #5)
 That's a feature! Even if method is not static, it still has a single unique
 body. If so, why can't you take its address?

http://www.digitalmars.com/d/1.0/type.html#delegates "There are no pointers-to-members in D, but a more useful concept called delegates are supported." Even if there were, the type would not be void function() as is declared in the attached code, but rather void function(A) or perhaps something like void A.function() akin to C++ notation (IIRC) void (A::*)() Maybe void function() would work if the calling convention specifies that the context pointer be always passed in a register that is never used for any other kind of function argument, but that isn't the case in the current ABI. --
Jan 12 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #7 from 2korden gmail.com  2009-01-12 04:53 -------
Makes sense. Perhaps, another enhancement report should be created with a
request to change typeof(&A.foo) from void function() to void delegate() with a
dg.ptr being null.


-- 
Jan 12 2009
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #8 from smjg iname.com  2009-01-12 07:15 -------
(In reply to comment #7)
 Makes sense. Perhaps, another enhancement report should be created with a
 request to change typeof(&A.foo) from void function() to void delegate() with a
 dg.ptr being null.

That would still be prone to accidental misuse IMO. Really, D should do one of the following: (a) add method pointer types (b) define &A.foo to be of a type that has the context pointer as just another parameter (which might break if ABI changes to support function-to-delegate conversion are implemented) (c) (continue to) disallow &A.foo altogether --
Jan 12 2009
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2557





------- Comment #9 from d brian.codekitchen.net  2009-01-14 16:46 -------
 It doesn't work.  "works" means "behaves correctly", not "compiles without
error".

I understand the difference between "works" and "compiles', it does work in my testing. The method body I'm taking a pointer to is empty in the test case but I first ran into this inconsistency while refactoring some code, where the method body was *not* empty and the code inside the method executed correctly. Whether it *should* work or not is certainly debatable, but I find it a useful behavior except for the inconsistency shown. --
Jan 14 2009