www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 7265] New: Function Literals where a keyword was omitted should be delegate even if inference.

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

           Summary: Function Literals where a keyword was omitted should
                    be delegate even if inference.
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Severity: regression
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: zan77137 nifty.com



This code should be work (on git head):

-------
import std.stdio;

void main()
{
    auto dg = { writeln("delegate"); };
    static assert(is(typeof(dg) == delegate));
}
-------
main.d(6): Error: static assert  (is(void function() == delegate)) is false
-------

This is being documented as follows:

 If the keywords function or delegate are omitted, it defaults to being a
delegate.
-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 10 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265


timon.gehr gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr gmx.ch
          Component|DMD                         |websites
           Severity|regression                  |normal



This is a case of outdated documentation.
From TDPL, p150:
"If both function and delegate are absent from the literal, the compiler
automatically detects which one is necessary".

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 15 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265





 This is a case of outdated documentation.
 From TDPL, p150:
 "If both function and delegate are absent from the literal, the compiler
 automatically detects which one is necessary".
It is an example unlike the specifications(TDPL, p150). The case is the following situation: ------- import std.stdio, std.traits; void main() { void function() fn = { writeln("function"); }; static assert(isFunctionPointer!(typeof(fn))); void delegate() dg = { writeln("delegate"); }; static assert(isDelegate!(typeof(dg))); } ------- As noted above, the specifications are applied only when there is a necessary type. When there is not a required type, in the case like this time, it should infer the type of the default. This resembles the following examples: ------- import std.traits; void main() { byte a = 1; // typeof(a) is byte auto b = 1; // typeof(b) is int // int cannot implicitly cast to byte. static assert (isImplicitlyConvertible!(typeof(b), typeof(a))); // false. } ------- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265


timon.gehr gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|DMD                         |websites



Everything behaves as specified in TDPL. This is not a compiler bug.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com



09:25:15 PST ---

 Everything behaves as specified in TDPL. This is not a compiler bug.
Yah, I just tested this: import std.stdio, std.traits; void main() { auto fn = { writeln("function"); }; static assert(isFunctionPointer!(typeof(fn))); int x; auto dg = { writeln("delegate because it prints ", x); }; static assert(isDelegate!(typeof(dg))); } So the literal is properly classified as a function or delegate depending on it needing a frame pointer or not. There's one remaining question I have. I rewrote the example like this: import std.stdio, std.traits; void main() { auto fn = { writeln("function"); }; static assert(is(typeof(fn) == function)); int x; auto dg = { writeln("delegate because it prints ", x); }; static assert(is(typeof(dg) == delegate)); } The second static assert works, but the first doesn't. Why? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265






 Everything behaves as specified in TDPL. This is not a compiler bug.
Yah, I just tested this: import std.stdio, std.traits; void main() { auto fn = { writeln("function"); }; static assert(isFunctionPointer!(typeof(fn))); int x; auto dg = { writeln("delegate because it prints ", x); }; static assert(isDelegate!(typeof(dg))); } So the literal is properly classified as a function or delegate depending on it needing a frame pointer or not.
Hmm... Because it included a clear breaking change, I thought that a sample code was wrong.
 There's one remaining question I have. I rewrote the example like this:
 
 
 import std.stdio, std.traits;
 
 void main()
 {
     auto fn = { writeln("function"); };
     static assert(is(typeof(fn) == function));
 
     int x;
     auto dg = { writeln("delegate because it prints ", x); };
     static assert(is(typeof(dg) == delegate));
 }
 
 The second static assert works, but the first doesn't. Why?
"fn" of the first case is a function pointer and is not a function. The code outputs a compilation error definitely. ----- import std.stdio, std.traits; void main() { static assert(is(typeof(main) == function)); // true, typeof(main) is function static assert(is(typeof(&main) == function)); // false, typeof(&main) is function pointer } ----- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265




10:15:03 PST ---

 -----
 import std.stdio, std.traits;
 
 void main()
 {
     static assert(is(typeof(main) == function)); // true, typeof(main) is
 function
     static assert(is(typeof(&main) == function)); // false, typeof(&main) is
 function pointer
 }
 -----
I think fn in auto fn = { ... }; should be the same thing - a name for a function. I guess that's not easy to implement. Kenji, Walter? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265




 I think fn in
 
 auto fn = { ... };
 
 should be the same thing - a name for a function. I guess that's not easy to
 implement. Kenji, Walter?
Rewriting it to true function declaration is easy, but fn is looks like a variable so peaple will try to rebind it with assignment: fn = { writeln("another function literal"); }; and will get an error. It is inconsistent. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED



16:36:05 PST ---
OK, thanks.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 16 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265




By the way, the reason why I set this Issue with regression is that I cause a
difficult problem with the following cases:

------
import std.stdio, std.functional;

// Library code
struct Control {
    alias void delegate(Control o) Handler;
    Handler[] _handlers;

    void addHandler(H)(H hnd) {
        _handlers ~= cast(Handler)hnd;
    }

    void addHandler2(H)(H hnd) if (is(H == delegate)) {
        _handlers ~= cast(Handler)hnd;
    }

    // Workaround. It is settled if can handle either by toDelegate.
    void addHandler3(H)(H hnd) {
        _handlers ~= cast(Handler)toDelegate(hnd);
    }

    void call() {
        foreach (h; _handlers) {
            h(this);
        }
    }
}

// User code
void main() {
    int i;
    auto c = new Control;
    // OK. This literal is inferred delegate.
    c.addHandler( (Object o){ writeln(i); } );

    // Error. This literal is inferred function pointer.
//    c.addHandler( (Object o){ writeln("test"); } );

    // Error. This literal is inferred function pointer, too.
    // The constraint-if does not influence the type inference.
//    c.addHandler2( (Object o){ writeln("test2"); } );

    // Workaround.
    c.addHandler3( (Object o){ writeln("test3"); } );

    c.call();
}
------

When a library code has a definition such as Control, many breaking changes
befall user codes.
Actually, this way is used by DFL.

One of simple workaround is to use toDelegate with library codes.

I think that another solution is to let implicit conversion perform a role as
toDelegate.

I remember it has entered ML agenda several times. But I've forgotten the
conclusion.
Is there a person knowing the details?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 17 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7265





 One of simple workaround is to use toDelegate with library codes.
 
 I think that another solution is to let implicit conversion perform a role as
 toDelegate.
 
 I remember it has entered ML agenda several times. But I've forgotten the
 conclusion.
 Is there a person knowing the details?
I think no conclusion has been reached yet. Andrei (and me too) wants implicit conversions from function pointer to delegate to work, but Walter disagrees with it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 17 2012