digitalmars.D.bugs - [Issue 4173] New: Explicitly instantiated templates still try to do IFTI in some cases
- d-bugmail puremagic.com (47/47) May 10 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
- d-bugmail puremagic.com (22/22) Jul 26 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
- d-bugmail puremagic.com (16/16) Aug 30 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
- d-bugmail puremagic.com (26/26) Sep 03 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
- d-bugmail puremagic.com (171/171) Sep 03 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
- d-bugmail puremagic.com (8/8) Sep 03 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
- d-bugmail puremagic.com (12/12) Sep 11 2010 http://d.puremagic.com/issues/show_bug.cgi?id=4173
http://d.puremagic.com/issues/show_bug.cgi?id=4173 Summary: Explicitly instantiated templates still try to do IFTI in some cases Product: D Version: 2.037 Platform: Other OS/Version: Linux Status: NEW Severity: regression Priority: P2 Component: DMD AssignedTo: nobody puremagic.com ReportedBy: schveiguy yahoo.com 14:17:02 PDT --- I'm unsure if this is a minimal case: interface I(T) { T foo(); } interface I2(T, U) { T foo(); U bar(); } void fn(T)(I!T t1) { } void fn(T, U)(I2!(T, U) t1) { } class C : I!int { int foo() { return 5;} } void main() { auto c = new C; I!int i = c; fn!(int)(i); // compiles fn!(int)(c); // fails } output: testtemplate.d(26): Error: template testtemplate.fn(T) does not match any function template declaration testtemplate.d(26): Error: template testtemplate.fn(T) cannot deduce template function from argument types !(int)(C) testtemplate.d(26): Error: template instance errors instantiating template This compiled with 2.036. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 10 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4173 Don <clugdbug yahoo.com.au> changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|Explicitly instantiated |Regression(2.037) |templates still try to do |Explicitly instantiated |IFTI in some cases |templates still try to do | |IFTI in some cases Reduced test case: class I(X) { } // also for interface void fn(T)(I!T t1) { } void fn(A, B)(int t1) { } class C : I!int { } void bug4173() { C c; fn!(int)(c); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 26 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4173 This bug was triggered by svn commit 273, which was related to opDispatch. The immediate change was in CallExp::semantic(). Previously, it attempted full instantiation, and if that failed, it tried partial explicit instantiation. After this change, it calls needsTypeInference(). It does partial instantiation if true, otherwise does full instantiation. In this test case, there is one template which requires partial explicit instantantion, and one which does not. So, in 2.036 and earlier, the full instantiation succeeded, before it even considered the two-argument template. Seems as though the code for explicit instantiation is slightly more capable at the moment, than the partial instantiation code. Bug 4430 is probably another instance of the same bug. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 30 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4173 It seems to be just luck that this ever worked at all. Template parameter deduction has never worked for base classes or interfaces of a class. So although this particular case used to work, it was very fragile -- very closely related cases would fail. I've only been able to fix this by implementing template parameter deduction for base classes. It allows them as a "match with implicit conversion". Thus, it also fixes bug 1715 "Template specialization checks for equality rather than convertibility" and bug 1970 "Templated interfaces not matched". But I've found a very annoying case: interface I(X) {} class C: I!(char), I!(double) {} void foo(T)(I!(T) x) {} void main() { C c = new C; foo(c); // could match with I!char or I!double } This should be treated as a match-with-implicit-conversion for c, but the type T has not been determined, so template instantiation should fail. If the signature is instead: foo(T)(I!(T) x, T y){} and called with foo(c, 1.2), then instantiation should succeed. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 03 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4173 Don <clugdbug yahoo.com.au> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |patch This patch is a drop-in replacement for TypeClass::deduceType() in template.c, line 2180 in D1, 2480 in D2. The patch is unchanged between D1 & D2. It fixes these bugs: bug 1715 Template specialization checks for equality rather than convertibility bug 1970 Templated interfaces not matched bug 4173 Regression(2.037) Explicitly instantiated templates still try to do IFTI in some cases It is far more general than any of those bugs. It checks all base interfaces, and detects ambiguities. It copes with some pretty difficult cases: interface TwoWay(A,B) {} class C1: TwoWay!(char, float), TwoWay!(int, float) {} class C2: TwoWay!(int, char), TwoWay!(float, char) {} C1 twoway; C2 twoway2; B foo(A, B)(TwoWay!(A, B) x, TwoWay!(B, A) y) { return B.init;} static assert(is(typeof(foo(twoway, twoway2)) == float)); static assert(is(typeof(foo(twoway2, twoway)) == char)); though it can only do this if it can determine at least one template parameter from the first function parameter. PATCH: Template.c line 2480, replacing TypeClass::deduceType() ---------------------- /* Helper for TypeClass::deduceType(). * Classes can match with implicit conversion to a base class or interface. * This is complicated, because there may be more than one base class which * matches. In such cases, one or more parameters remain ambiguous. * For example, * * interface I(X, Y) {} * class C : I(uint, double), I(char, double) {} * C x; * foo(T, U)( I!(T, U) x) * * deduces that U is double, but T remains ambiguous (could be char or uint). * * Given a baseclass b, and initial deduced types 'dedtypes', this function * tries to match tparam with b, and also tries all base interfaces of b. * If a match occurs, numBaseClassMatches is incremented, and the new deduced * types are ANDed with the current 'best' estimate for dedtypes. */ void deduceBaseClassParameters(BaseClass *b, Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, Objects *best, int &numBaseClassMatches) { TemplateInstance *parti = b->base->parent->isTemplateInstance(); if (parti) { // Make a temporary copy of dedtypes so we don't destroy it Objects *tmpdedtypes = new Objects(); tmpdedtypes->setDim(dedtypes->dim); memcpy(tmpdedtypes->data, dedtypes->data, dedtypes->dim * sizeof(void *)); TypeInstance *t = new TypeInstance(0, parti); MATCH m = t->deduceType(sc, tparam, parameters, tmpdedtypes); if (m != MATCHnomatch) { // If this is the first ever match, it becomes our best estimate if (numBaseClassMatches==0) memcpy(best->data, tmpdedtypes->data, tmpdedtypes->dim * sizeof(void *)); else for (size_t k = 0; k < tmpdedtypes->dim; ++k) { // If we've found more than one possible type for a parameter, // mark it as unknown. if (tmpdedtypes->data[k] != best->data[k]) best->data[k] = dedtypes->data[k]; } ++numBaseClassMatches; } } // Now recursively test the inherited interfaces for (size_t j = 0; j < b->baseInterfaces_dim; ++j) { deduceBaseClassParameters( &(b->baseInterfaces)[j], sc, tparam, parameters, dedtypes, best, numBaseClassMatches); } } MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) { //printf("TypeClass::deduceType(this = %s)\n", toChars()); /* If this class is a template class, and we're matching * it against a template instance, convert the class type * to a template instance, too, and try again. */ TemplateInstance *ti = sym->parent->isTemplateInstance(); if (tparam && tparam->ty == Tinstance) { if (ti && ti->toAlias() == sym) { TypeInstance *t = new TypeInstance(0, ti); MATCH m = t->deduceType(sc, tparam, parameters, dedtypes); // Even if the match fails, there is still a chance it could match // a base class. if (m != MATCHnomatch) return m; } /* Match things like: * S!(T).foo */ TypeInstance *tpi = (TypeInstance *)tparam; if (tpi->idents.dim) { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1]; if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) { Type *tparent = sym->parent->getType(); if (tparent) { /* Slice off the .foo in S!(T).foo */ tpi->idents.dim--; MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes); tpi->idents.dim++; return m; } } } // If it matches exactly or via implicit conversion, we're done MATCH m = Type::deduceType(sc, tparam, parameters, dedtypes); if (m != MATCHnomatch) return m; /* There is still a chance to match via implicit conversion to * a base class or interface. Because there could be more than one such * match, we need to check them all. */ int numBaseClassMatches = 0; // Have we found an interface match? // Our best guess at dedtypes Objects *best = new Objects(); best->setDim(dedtypes->dim); ClassDeclaration *s = sym; while(s && s->baseclasses->dim > 0) { // Test the base class deduceBaseClassParameters((BaseClass *)(s->baseclasses->data[0]), sc, tparam, parameters, dedtypes, best, numBaseClassMatches); // Test the interfaces inherited by the base class for (size_t i = 0; i < s->interfaces_dim; ++i) { BaseClass *b = s->interfaces[i]; deduceBaseClassParameters(b, sc, tparam, parameters, dedtypes, best, numBaseClassMatches); } s = ((BaseClass *)(s->baseclasses->data[0]))->base; } if (numBaseClassMatches == 0) return MATCHnomatch; // If we got at least one match, copy the known types into dedtypes memcpy(dedtypes->data, best->data, best->dim * sizeof(void *)); return MATCHconvert; } // Extra check if (tparam && tparam->ty == Tclass) { TypeClass *tp = (TypeClass *)tparam; //printf("\t%d\n", (MATCH) implicitConvTo(tp)); return implicitConvTo(tp); } return Type::deduceType(sc, tparam, parameters, dedtypes); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 03 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4173 Created an attachment (id=745) Template Interface tests for test suite These 16 tests are for both D1 and D2. Compile with dmd -c templiface.d -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 03 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4173 Walter Bright <bugzilla digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED CC| |bugzilla digitalmars.com Resolution| |FIXED 17:51:22 PDT --- http://www.dsource.org/projects/dmd/changeset/675 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 11 2010