Bug 4430 – Regression(2.037) erroneous matching on specialized template function

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2010-07-06T02:13:00Z
Last change time
2010-09-11T16:47:38Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
s.d.hammett

Comments

Comment #0 by s.d.hammett — 2010-07-06T02:13:12Z
A bug has been introduced in 2.037 which in some circumstances causes a specialized template function to be considered a match even when though it isn't. I tried to cut it down to a small test case but I didn't succeed, it must be something to do with a specific instantiation which is causing the bug. FWIW: http://www.sstk.co.uk/spiritd.zip Compiles fine w/ 2.036 If I can make a smaller test case, I'll update this bug report.
Comment #1 by webby — 2010-07-06T06:25:42Z
You can repro the compile error in the spiritd test app by doing: ///////// import spiritd.match, spiritd.nil; void main(string[] args) { Match!(nilT) temp; conv!(Match!(char))(temp); } ///////// (you only need the match bits to see the problem, rather than the whole thing).
Comment #2 by clugdbug — 2010-07-26T11:33:07Z
Reduced test case: struct Ghost(T) {} void bug4430(T)(Ghost!(T) x) {} void bug4430(T)(Ghost!(int) x) {} void spirit4430() { Ghost!(int) temp; bug4430!(Ghost!(char))( temp ); }
Comment #3 by clugdbug — 2010-09-01T00:19:06Z
Even further reduced, shows that a class template is not required. --- struct Ghost {} void bug4430(T)(int x) {} void bug4430(T)(Ghost x) {} void spirit4430() { bug4430!(char)( 777 ); } ---- bad.d(53): Error: template instance bug4430!(char) matches more than one templat e declaration, bad.d(48):bug4430(T) and bad.d(49):bug4430(T)
Comment #4 by clugdbug — 2010-09-01T11:57:33Z
This bug was triggered by svn commit 273, which was related to opDispatch. The immediate change was in CallExp::semantic(). Previously, it attempted full explicit instantiation, and if that failed, it tried partial explicit instantiation. In this case, the full explicit instantiation was failing (because there were two candidate templates), and then partial instantiation succeeded. After svn 273, it calls needsTypeInference(). If that returns true, it does partial instantiation, otherwise does full instantiation. In this example, it's returning false. There is a situation missing from needsTypeInference(). If there is more than one candidate template, and they are ALL function templates, and they are ALL potentially explicitly instantiated, we need to do partial instantiation. Template.c, needsTypeInference(), around line 4625. Index: template.c =================================================================== --- template.c (revision 655) +++ template.c (working copy) @@ -4622,6 +4622,7 @@ //printf("TemplateInstance::needsTypeInference() %s\n", toChars()); if (!tempdecl) tempdecl = findTemplateDeclaration(sc); + int multipleMatches = FALSE; for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) { /* If any of the overloaded template declarations need inference, @@ -4647,9 +4648,14 @@ if (Parameter::dim(fdtype->parameters) && (tp || tiargs->dim < td->parameters->dim)) return TRUE; + /* If there is more than one function template which matches, we may need type inference + */ + if (td != tempdecl) + multipleMatches = TRUE; } //printf("false\n"); - return FALSE; + return multipleMatches; } void TemplateInstance::semantic2(Scope *sc)
Comment #5 by bugzilla — 2010-09-11T16:47:38Z