Jump to page: 1 2
Thread overview
[Issue 7135] New: [tdpl] Multiple delegate-related issues (literal syntax, @system deduction)
Dec 31, 2011
Kenji Hara
Dec 31, 2011
Kenji Hara
Dec 31, 2011
Don
Dec 31, 2011
timon.gehr@gmx.ch
Jan 01, 2012
Kenji Hara
Mar 14, 2012
Kenji Hara
May 21, 2013
Kenji Hara
December 19, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135

           Summary: [tdpl] Multiple delegate-related issues (literal
                    syntax, @system deduction)
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Mac OS X
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: andrei@metalanguage.com


--- Comment #0 from Andrei Alexandrescu <andrei@metalanguage.com> 2011-12-18 21:08:50 PST ---
This is a copy of a failing TDPL example. First, the compiler doesn't accept the delegate literal syntax unless it includes the keyword "delegate". Fixing that somehow makes the compiler decide the literal is @system and refuses binding it.

module test;// Context begin
#line 1369 "0900-operators.tex"
import std.variant;

alias Variant delegate(Dynamic self, Variant[] args...) DynMethod;
// Context end
// Context begin
#line 1383 "0900-operators.tex"
class Dynamic {
   private DynMethod[string] methods;
   void addMethod(string name, DynMethod m) {
      methods[name] = m;
   }
   void removeMethod(string name) {
      methods.remove(name);
   }
   // Dispatch dynamically on method
   Variant call(string methodName, Variant[] args...) {
      return methods[methodName](this, args);
   }
   // Provide syntactic sugar with opDispatch
   Variant opDispatch(string m, Args)(Args args...) {
      Variant[] packedArgs = new Variant[args.length];
      foreach (i, arg; args) {
         packedArgs[i] = Variant(arg);
      }
      return call(m, args);
   }
}
// Context end
#line 1409 "0900-operators.tex"
unittest {
  import std.stdio;
  auto obj = new Dynamic;
  obj.addMethod("sayHello",
      delegate Variant(Dynamic, Variant[]) {
        writeln("Hello, world!");
        return Variant();
     });
  obj.sayHello();  // Prints "Hello, world!"
}

void main(){}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135



--- Comment #1 from Kenji Hara <k.hara.pg@gmail.com> 2011-12-30 23:28:51 PST ---
This is not the delegate literal type deduction problem.
It is a trivial mismatching of delegate types.

This is the reduced code to explain the problem.
----
struct Variant {}
class Dynamic {}
alias Variant delegate(Dynamic self, Variant[] args...) DynMethod;
void main()
{
    DynMethod dg = delegate Variant(Dynamic, Variant[]) {
        return Variant();
    };
}

Output:
----
test.d(6): Error: cannot implicitly convert expression (__dgliteral1) of type
Variant delegate(Dynamic _param_0, Variant[] _param_1) pure nthrow @safe to
Variant delegate(Dynamic self, Variant[] args...)

DynMethod has typesafe variadic parameter, but literal doesn't have. So this is a bug of TDPL sample code, not compiler's.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135



--- Comment #2 from Andrei Alexandrescu <andrei@metalanguage.com> 2011-12-31 00:40:00 PST ---
(In reply to comment #1)
> This is not the delegate literal type deduction problem.
> It is a trivial mismatching of delegate types.
> 
> This is the reduced code to explain the problem.
> ----
> struct Variant {}
> class Dynamic {}
> alias Variant delegate(Dynamic self, Variant[] args...) DynMethod;
> void main()
> {
>     DynMethod dg = delegate Variant(Dynamic, Variant[]) {
>         return Variant();
>     };
> }
> 
> Output:
> ----
> test.d(6): Error: cannot implicitly convert expression (__dgliteral1) of type
> Variant delegate(Dynamic _param_0, Variant[] _param_1) pure nthrow @safe to
> Variant delegate(Dynamic self, Variant[] args...)
> 
> DynMethod has typesafe variadic parameter, but literal doesn't have. So this is a bug of TDPL sample code, not compiler's.

I think (and perhaps I'm wrong) that the signature with ... and the one without must be equivalent. The ... makes a difference only in the call syntax, but in fact still passes an array. (Note that the variadics ending with "T[] param..." are not unsafe C-style variadics.) Please advise - thanks!

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135



--- Comment #3 from Kenji Hara <k.hara.pg@gmail.com> 2011-12-31 01:01:24 PST ---
(In reply to comment #2)
> I think (and perhaps I'm wrong) that the signature with ... and the one without must be equivalent. The ... makes a difference only in the call syntax, but in fact still passes an array. (Note that the variadics ending with "T[] param..." are not unsafe C-style variadics.) Please advise - thanks!

Hmm, current compiler always raise an error against the difference of variadic argument kind (non-variarics vs typesafe-variadics vs C-style variadics).

But, from http://d-programming-language.org/abi.html

> The variadic part is converted to a dynamic array and the rest is the same as for non-variadic functions.

So, in ABI layer, (..., T[]) and (..., T[]...) might be same...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135


Don <clugdbug@yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |clugdbug@yahoo.com.au


--- Comment #4 from Don <clugdbug@yahoo.com.au> 2011-12-31 03:12:50 PST ---
(In reply to comment #3)
> (In reply to comment #2)
> > I think (and perhaps I'm wrong) that the signature with ... and the one without must be equivalent. The ... makes a difference only in the call syntax, but in fact still passes an array. (Note that the variadics ending with "T[] param..." are not unsafe C-style variadics.) Please advise - thanks!
> 
> Hmm, current compiler always raise an error against the difference of variadic argument kind (non-variarics vs typesafe-variadics vs C-style variadics).
> 
> But, from http://d-programming-language.org/abi.html
> 
> > The variadic part is converted to a dynamic array and the rest is the same as for non-variadic functions.
> 
> So, in ABI layer, (..., T[]) and (..., T[]...) might be same...

I don't think so. One difference is visible in declaration.html (there may be
other). It says:

"An implementation may construct the object or array instance on the stack. Therefore, it is an error to refer to that instance after the variadic function has returned:

int[] test(int[] a ...) {
  return a;       // error, array contents invalid after return
}
"
So, it would be legal to call the delegate with the Variant[]... stored on the
stack. But it would fail.
It might be OK to assign a (Variant[]...) function to a (Variant[]) delegate,
but I'm pretty sure the other direction doesn't work.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135


timon.gehr@gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr@gmx.ch


--- Comment #5 from timon.gehr@gmx.ch 2011-12-31 07:32:53 PST ---
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #2)
> > > I think (and perhaps I'm wrong) that the signature with ... and the one without must be equivalent. The ... makes a difference only in the call syntax, but in fact still passes an array. (Note that the variadics ending with "T[] param..." are not unsafe C-style variadics.) Please advise - thanks!
> > 
> > Hmm, current compiler always raise an error against the difference of variadic argument kind (non-variarics vs typesafe-variadics vs C-style variadics).
> > 
> > But, from http://d-programming-language.org/abi.html
> > 
> > > The variadic part is converted to a dynamic array and the rest is the same as for non-variadic functions.
> > 
> > So, in ABI layer, (..., T[]) and (..., T[]...) might be same...
> 
> I don't think so. One difference is visible in declaration.html (there may be
> other). It says:
> 
> "An implementation may construct the object or array instance on the stack. Therefore, it is an error to refer to that instance after the variadic function has returned:
> 
> int[] test(int[] a ...) {
>   return a;       // error, array contents invalid after return
> }
> "
> So, it would be legal to call the delegate with the Variant[]... stored on the
> stack. But it would fail.
> It might be OK to assign a (Variant[]...) function to a (Variant[]) delegate,
> but I'm pretty sure the other direction doesn't work.

It should be OK to assign (scope Variant[]) to (Variant[]...).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135


Andrei Alexandrescu <andrei@metalanguage.com> changed:

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


--- Comment #6 from Andrei Alexandrescu <andrei@metalanguage.com> 2011-12-31 08:43:40 PST ---
OK, it looks like this is safe to close now. I compiled a slightly modified version. There was a bug elsewhere, the line

   Variant opDispatch(string m, Args)(Args args...) {

should be

   Variant opDispatch(string m, Args...)(Args args) {

Also, the signature of the delegate should contain "...", i.e. replace

      delegate Variant(Dynamic, Variant[]) {

with

      delegate Variant(Dynamic, Variant[]...) {

The working code is:

module test;// Context begin
#line 1369 "0900-operators.tex"
import std.variant;

alias Variant delegate(Dynamic self, Variant[] args...) DynMethod;
// Context end
// Context begin
#line 1383 "0900-operators.tex"
class Dynamic {
   private DynMethod[string] methods;
   void addMethod(string name, DynMethod m) {
      methods[name] = m;
   }
   void removeMethod(string name) {
      methods.remove(name);
   }
   // Dispatch dynamically on method
   Variant call(string methodName, Variant[] args...) {
      return methods[methodName](this, args);
   }
   // Provide syntactic sugar with opDispatch
   Variant opDispatch(string m, Args...)(Args args) {
      Variant[] packedArgs = new Variant[args.length];
      foreach (i, arg; args) {
         packedArgs[i] = Variant(arg);
      }
      return call(m, args);
   }
}
// Context end
#line 1409 "0900-operators.tex"
unittest {
  import std.stdio;
  auto obj = new Dynamic;
  obj.addMethod("sayHello",
      delegate Variant(Dynamic, Variant[]...) {
        writeln("Hello, world!");
        return Variant();
     });
  obj.sayHello();  // Prints "Hello, world!"
}

void main(){}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
December 31, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=7135


Andrei Alexandrescu <andrei@metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |


--- Comment #7 from Andrei Alexandrescu <andrei@metalanguage.com> 2011-12-31 10:32:43 PST ---
One more thing - the example in the book reads:

  obj.addMethod("sayHello",
      Variant(Dynamic, Variant[]...) {
        writeln("Hello, world!");
        return Variant();
     });

That doesn't work. The compilable version reads:

obj.addMethod("sayHello",
      delegate Variant(Dynamic, Variant[]...) {
        writeln("Hello, world!");
        return Variant();
     });

Can we arrange things such that the "delegate" or "function" keywords aren't require in the literal definition?

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



--- Comment #8 from Kenji Hara <k.hara.pg@gmail.com> 2012-01-01 05:56:47 PST ---
(In reply to comment #7)
> One more thing - the example in the book reads:
> 
>   obj.addMethod("sayHello",
>       Variant(Dynamic, Variant[]...) {
>         writeln("Hello, world!");
>         return Variant();
>      });
> 
> That doesn't work. The compilable version reads:
> 
> obj.addMethod("sayHello",
>       delegate Variant(Dynamic, Variant[]...) {
>         writeln("Hello, world!");
>         return Variant();
>      });
> 
> Can we arrange things such that the "delegate" or "function" keywords aren't require in the literal definition?

From past, omission of delegate keyword +  specification of return type has been wrong syntax. So Variant(Dynamic, Varinat[]...) { ... } couldn't compile.

And recent commit

https://github.com/D-Programming-Language/dmd/commit/c50eb5f5726a65efa1224ff0f0fd60acbb6e3027

has been disallowed optional parameter names, because of parameter type inference.

From these matters, current TDPL code never become valid.

----

Today, following literal notations has been allowed with current dmd.

delegate Variant(Dynamic self, Variant[] args...) {...}
delegate (Dynamic self, Variant[] args...) {...}
(Dynamic self, Variant[] args...) {...}

----

Note: Unfortunately, current dmd does not support parameter type inference + type-safe variadisc like follows.

//delegate (self, args...) {...}
//(self, args...) {...}

Because args could have three kind of infer targets.

T[N] args...    // T is the element type of args
T[] args...     // T is the element type of args
T args...       // T is class type, and args is translated to new T(args)

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



--- Comment #9 from Kenji Hara <k.hara.pg@gmail.com> 2012-03-13 20:50:21 PDT ---
(In reply to comment #8)
> Note: Unfortunately, current dmd does not support parameter type inference + type-safe variadisc like follows.
> 
> //delegate (self, args...) {...}
> //(self, args...) {...}

I've filed bug 7705 to allow such lambda syntax, and posted a pull request to fix it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
« First   ‹ Prev
1 2