D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 9555 - Type deduction for new lambda syntax literals breaks with templates
Summary: Type deduction for new lambda syntax literals breaks with templates
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-21 03:06 UTC by Dicebot
Modified: 2013-02-21 13:33 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Dicebot 2013-02-21 03:06:35 UTC
Simple motivating example:

--- test.d ---
import std.functional;

void main()
{
    auto deleg = toDelegate(a => a > 2);
}
------

--- shell ---
$ rdmd test.d 
test.d(5): Error: template std.functional.toDelegate does not match any function template declaration. Candidates are:
/usr/include/dmd/phobos/std/functional.d(722):        std.functional.toDelegate(F)(auto ref F fp) if (isCallable!(F))
test.d(5): Error: template std.functional.toDelegate(F)(auto ref F fp) if (isCallable!(F)) cannot deduce template function from argument types !()(void)
------

Type of lambda was deduced as "void" here.
Comment 1 Maxim Fomin 2013-02-21 04:29:03 UTC
Actually type of lambda was not deduced to void, void here is pseudo type of non-instantiated template, because a => a > 2 is a lambda template. If you append type of a parameter, this would work, for ex:

import std.functional;

void main()
{
    auto deleg = toDelegate( (int a) => a > 2);
}

Since there is no guesses what type of "a" can be in the original code, template cannot be instantiated. 

By the way, idea mentioned in forum discussion that there is problem with new (lambda) syntax is also wrong, because the code can be rewritten with delegate template:

import std.functional;

void main()
{
    auto deleg = toDelegate( delegate (a) { return a > 2; } );
}

with the same problem and same error message.

Close this as invalid.
Comment 2 bioinfornatics 2013-02-21 04:39:49 UTC

but if your delegate look like : in bool delegate(in size_t) lambda

you can't use (in int a) => a > 2)
or (const int a) => a > 2)
Comment 3 bioinfornatics 2013-02-21 04:41:32 UTC
skip my comment that is allowed to do ((in int a) => a > 2)
Comment 4 Dicebot 2013-02-21 08:18:45 UTC
Waa, it is a template? Unexpected. What about turning this into enhancement request to improve error message though? Something like "not enough context to deduce lambda type".
Comment 5 Maxim Fomin 2013-02-21 09:26:44 UTC
(In reply to comment #4)
> Waa, it is a template? Unexpected. What about turning this into enhancement
> request to improve error message though? Something like "not enough context to
> deduce lambda type".

Enough context can be provided later. 

template get(alias a)
{
    alias a!int get;
}

template foo(fun...)
{
    alias get!fun foo;
}

void main()
{
    alias foo!(a=>a) a;
    assert(a(1) == 1);
    assert(a(1.0) is 1.0); //NG
}

Note, this is reduced from how map and unaryfun works. If you turn it into context-independent error, this would mean code break for some usages which are currently accepted.
Comment 6 Dicebot 2013-02-21 13:33:15 UTC
I was speaking exactly about the case when it is used and context is lacking. This message "cannot deduce template function from argument types !()(void)" is very misleading for someone who is not aware of lambda implementation inner details.