Bug 6574 – Erroneous recursive call in template instantiation
Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-08-29T19:49:00Z
Last change time
2015-02-18T03:42:15Z
Keywords
pull, spec, wrong-code
Assigned to
nobody
Creator
andrej.mitrovich
Comments
Comment #0 by andrej.mitrovich — 2011-08-29T19:49:09Z
For lack of a better name..
import std.stdio;
enum Method
{
A,
B,
}
void Foo(Method method = Method.A)()
{
write("dispatch, ");
Foo!method();
}
void Foo(Method method : Method.A)()
{
writeln("Foo A");
}
void Foo(Method method : Method.B)()
{
writeln("Foo B");
}
void main()
{
Foo!(); // dispatch, Foo A
Foo(); // dispatch, Foo A
}
That works. Now uncomment the first instantiation, the `Foo!()` part and compile and run. The "dispatch" template instance keeps calling itself until the stack is blown and the app exits.
What I was trying to do with code like the above was to use template overloading with type specialization to switch between different types of drawing methods. The default "dispatch" template is there in case the user doesn't care which drawing method to use, the dispatch would then instantiate a specialized template (one specialized for Method.A in this case).
But as you can see, this is buggy territory..
Comment #1 by lt.infiltrator — 2014-03-19T20:18:16Z
As of v2.065, the provided code compiles and runs without errors. Taking out the 'Foo!();' line causes a compilation warning about a size change but still seems to compile and run fine (though there probably is a bug there).
Comment #2 by andrej.mitrovich — 2014-03-20T01:11:38Z
(In reply to comment #1)
> As of v2.065, the provided code compiles and runs without errors. Taking out
> the 'Foo!();' line causes a compilation warning about a size change but still
> seems to compile and run fine (though there probably is a bug there).
The following runs forever for me with 2.065:
-----
import std.stdio;
enum Method
{
A,
B,
}
void Foo(Method method = Method.A)()
{
write("dispatch, ");
Foo!method();
}
void Foo(Method method : Method.A)()
{
writeln("Foo A");
}
void Foo(Method method : Method.B)()
{
writeln("Foo B");
}
void main()
{
Foo(); // dispatch, Foo A
}
-----
I can't see any compilation warnings either.
Comment #3 by lt.infiltrator — 2014-03-20T05:54:44Z
That's very odd. For me, the infloop only happens with my v2.062 gdc; my v2.065 dmd and dpaste's v2.065 both give the warning and output of "dispatch, Foo A".
Comment #4 by k.hara.pg — 2015-01-09T10:13:44Z
This is a mangling scheme issue and function symbol is confused in link stage.
module test;
extern(C) int printf(const char*, ...);
enum Method { A, B, }
void foo(Method method = Method.A)()
{
pragma(msg, "1: ", foo.mangleof);
foo!method();
}
void foo(Method method : Method.A)()
{
pragma(msg, "2: ", foo.mangleof);
}
void main()
{
foo();
}
foo() instantiates the first version `void foo(Method method = Method.A)()`,
then it instantiates the second version `void foo(Method method : Method.A)()`.
But the instantiated two functions have exactly same mangled names, so the pragmas print:
1: _D4test24__T3fooVE4test6Methodi1Z3fooFZv
2: _D4test24__T3fooVE4test6Methodi1Z3fooFZv
and the foo!method() wrongly call itself.