Jump to page: 1 2
Thread overview
[Issue 7265] New: Function Literals where a keyword was omitted should be delegate even if inference.
Jan 10, 2012
SHOO
Jan 15, 2012
timon.gehr@gmx.ch
Jan 16, 2012
SHOO
Jan 16, 2012
timon.gehr@gmx.ch
Jan 16, 2012
SHOO
Jan 17, 2012
Kenji Hara
Jan 17, 2012
SHOO
Jan 17, 2012
timon.gehr@gmx.ch
January 10, 2012
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


--- Comment #0 from SHOO <zan77137@nifty.com> 2012-01-10 09:30:54 PST ---
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: -------
January 15, 2012
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


--- Comment #1 from timon.gehr@gmx.ch 2012-01-15 11:56:18 PST ---
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: -------
January 16, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265



--- Comment #2 from SHOO <zan77137@nifty.com> 2012-01-16 03:48:12 PST ---
(In reply to comment #1)
> 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: -------
January 16, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265


timon.gehr@gmx.ch changed:

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


--- Comment #3 from timon.gehr@gmx.ch 2012-01-16 08:44:22 PST ---
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: -------
January 16, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265


Andrei Alexandrescu <andrei@metalanguage.com> changed:

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


--- Comment #4 from Andrei Alexandrescu <andrei@metalanguage.com> 2012-01-16 09:25:15 PST ---
(In reply to comment #3)
> 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: -------
January 16, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265



--- Comment #5 from SHOO <zan77137@nifty.com> 2012-01-16 10:07:04 PST ---
(In reply to comment #4)
> (In reply to comment #3)
> > 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: -------
January 16, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265



--- Comment #6 from Andrei Alexandrescu <andrei@metalanguage.com> 2012-01-16 10:15:03 PST ---
(In reply to comment #5)
> -----
> 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: -------
January 17, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265



--- Comment #7 from Kenji Hara <k.hara.pg@gmail.com> 2012-01-16 16:11:52 PST ---
> 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: -------
January 17, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265


Andrei Alexandrescu <andrei@metalanguage.com> changed:

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


--- Comment #8 from Andrei Alexandrescu <andrei@metalanguage.com> 2012-01-16 16:36:05 PST ---
OK, thanks.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 17, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7265



--- Comment #9 from SHOO <zan77137@nifty.com> 2012-01-17 06:37:31 PST ---
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: -------
« First   ‹ Prev
1 2