Potential issue with DMD where the template constrains are not evaluated early enough to prevent type recursion

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Fri May 13 16:31:00 PDT 2016


On 13.05.2016 23:21, Georgi D wrote:
> Hi,
>
> I have the following code which should compile in my opinion:
>
> struct Foo {}
>
> import std.range.primitives;
> import std.algorithm.iteration : map, joiner;
>
> auto toChars(R)(R r) if (isInputRange!R)
> {
>     return r.map!(toChars).joiner(", ");
> }
>
> auto toChars(Foo f)
> {
>     import std.range : chain;
>     return chain("foo", "bar");
> }
>
> void main()
> {
>     import std.range : repeat;
>     Foo f;
>     auto r = f.repeat(3);
>     auto chars = r.toChars();
> }
>
> But fails to compile with the following error:
>
> Error: template instance std.algorithm.iteration.MapResult!(toChars,
> Take!(Repeat!(Foo))) forward reference of function toChars
>
> The reason it fails to compile in my opinion is that the template
> constraint fails to remove the generic toChars from the list possible
> matches early enough so the compiler thinks there is a recursive call
> and cannot deduce the return type.

It's tricky. The reason it fails to compile is that the template 
argument you are passing does not actually refer to the overload set.

return r.map!(.toChars).joiner(", "); works.



Consider:

int foo()(){
     pragma(msg, typeof(&foo)); // int function()
     return 2;
}
double foo(){
     return foo!();
}

The reason for this behavior is that the first declaration is syntactic 
sugar for:

template foo(){
     int foo(){
         pragma(msg, typeof(&foo));
         return 2;
     }
}

Since template foo() introduces a scope, the inner 'int foo()' shadows 
the outer 'double foo()'. There are special cases in the compiler that 
reverse eponymous lookup before overload resolution (i.e. go from 
foo!().foo back to foo) in case some identifier appears in the context 
ident() or ident!(), so one does not usually run into this. This is not 
done for alias parameters.

The error message is bad though. Also, I think it is not unreasonable to 
expect the code to work. Maybe reversal of eponymous lookup should be 
done for alias parameters too.


More information about the Digitalmars-d mailing list