Bug 4913 – Repeated template instantiations with the same symbol argument fails
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-09-21T18:41:00Z
Last change time
2011-02-06T13:45:53Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
rsinfu
Comments
Comment #0 by rsinfu — 2010-09-21T18:41:06Z
The following valid code doesn't compile:
--------------------
template Test(alias symbol) {}
struct S(T...)
{
T vars; // (5)
alias Test!(vars[0]) first;
alias Test!(vars[0]) second; // (7)
}
alias S!(int) a; // (9)
--------------------
% dmd -o- -c test.d
test.d(5): Error: expression _vars_field_0 is not a valid template value argument
test.d(7): Error: template instance test.Test!(_vars_field_0) error instantiating
test.d(9): instantiated from here: S!(int)
--------------------
The first instantiation of the Test with a symbol argument vars[0] succeeds. But the second instantiation fails. The error does not occur if the line (7) is commented out.
Comment #1 by rsinfu — 2010-09-21T18:43:39Z
This patch fixes the problem (dmd r680):
====================
--- src/template.c
+++ src/template.c
@@ -4641,6 +4641,12 @@ Identifier *TemplateInstance::genIdent()
ea = NULL;
goto Lsa;
}
+ if (ea->op == TOKdsymbol)
+ {
+ sa = ((DsymbolExp *)ea)->s;
+ ea = NULL;
+ goto Lsa;
+ }
buf.writeByte('V');
if (ea->op == TOKtuple)
{ ea->error("tuple is not a valid template value argument");
====================
NOTE: I think the problem is that DsymbolExp::semantic() just returns 'this' if it already run, whereas the function does elaborate AST rewriting. As for this report's case, it rewrites itself to a VarExp *only* at the first semantic run.
So, the following patch also fixes the reported problem.
====================
--- src/expression.c
+++ src/expression.c
@@ -2244,8 +2244,10 @@ Lagain:
//printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
//printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
+#if 0
if (type)
return this;
+#endif
if (!s->isFuncDeclaration()) // functions are checked after overloading
checkDeprecated(sc, s);
s = s->toAlias();