www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template expansion bug?

reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
While doing some testing, I came across this behavior:

template foo(T) {
     void foo() {}
}

void main()
{
     foo!(int).foo();
     //foo!(int)(); // this works
}

Error:
testbug.d(7): Error: template testbug.foo does not match any function  
template declaration. Candidates are:
testbug.d(1):        testbug.foo(T)()
testbug.d(7): Error: template testbug.foo(T)() cannot deduce template  
function from argument types !()(void)

This happens on 2.063 and 2.061.

 From D spec: http://dlang.org/template.html

If a template has exactly one member in it, and the name of that member is  
the same as the template name, that member is assumed to be referred to in  
a template instantiation:

template Foo(T) {
   T Foo; // declare variable Foo of type T
}

void test() {
   Foo!(int) = 6; // instead of Foo!(int).Foo
}

...



I would have expected that foo!(int).foo() is equivalent to foo!(int)().   
Is this no longer the case?  Is there some issue here with DMD  
aggressively evaluating foo!(int) to be a call because of the no-arg  
function?

Actually, it does seem that way, if I change foo to accept a parameter,  
and call:

foo!(int).foo(1);

I get:

testbug.d(7): Error: foo (int t) is not callable using argument types ()
testbug.d(7): Error: foo (int t) is not callable using argument types ()

(and yes, double the error).

I can't at the moment think of a reason why anyone would ever use the full  
syntax, but I would expect it to be accessible, and for the compiler to  
treat foo as a template first, function call second.

-Steve
May 31 2013
next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On 2013-05-31, 16:42, Steven Schveighoffer wrote:

 While doing some testing, I came across this behavior:

 template foo(T) {
      void foo() {}
 }

 void main()
 {
      foo!(int).foo();
      //foo!(int)(); // this works
 }

I'm not certain, but it could be ambiguity: template foo(T) { struct foo { T foo; } } auto bar = foo!int.foo; // Is bar an int or a foo!int struct? -- Simen
May 31 2013
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 31 May 2013 13:18:13 -0400, Simen Kjaeraas  
<simen.kjaras gmail.com> wrote:

 On 2013-05-31, 16:42, Steven Schveighoffer wrote:

 While doing some testing, I came across this behavior:

 template foo(T) {
      void foo() {}
 }

 void main()
 {
      foo!(int).foo();
      //foo!(int)(); // this works
 }

I'm not certain, but it could be ambiguity: template foo(T) { struct foo { T foo; } } auto bar = foo!int.foo; // Is bar an int or a foo!int struct?

This is true, but there is an implicit call going on in the function version. Incidentally, testing shows that foo!int.foo in your case is the int, not the struct. Renaming the foo member to foox, it now complains similarly (can't find member foo, did you mean foox?). It appears that the expanded version of eponymous templates is pretty much disabled at this point. I'm not sure this is a bad thing, but it should at least be documented. I'm pretty sure this used to work, but I'd have to download an old version of DMD to figure that out :) -Steve
May 31 2013
prev sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 31 May 2013 at 14:42:32 UTC, Steven Schveigho
 I can't at the moment think of a reason why anyone would ever 
 use the full syntax, but I would expect it to be accessible, 
 and for the compiler to treat foo as a template first, function 
 call second.

 -Steve

I do believe that the idea is that once a template is "eponymous", then all calls are supposed to be aggressively expanded to the internal name, and not just "can be omitted". Once you've written the template, it is immediately "assumed" to be the eponymous call. At that point, trying to make a fully qualified call fails, because the template was already "expanded" (for lack of a better word). Leaving the possibility to choose both syntax would allow ambiguity, which is never good: Your template is either eponymous, or it isn't. It's not "sometimes eponymous". From what you have shown, I'd just say 2.062 introduced a bug, which was fixed by 2.063. EDIT: Allow I think that there is a bug that a template becomes eponymous when it contains a single public function that is eponymous, regardless of other functions. IMO, that is a good thing, but the spec state that there should be ONLY members with the same name. As for the "Exactly one": That's bullocks, unless you mean that overloads define a single function. There are tons of places where we use a template with overloaded eponymous resolution. I think the spec is wrong on that one.
May 31 2013