diff --git a/src/clone.c b/src/clone.c index dad73ada083d..883cc0173904 100644 --- a/src/clone.c +++ b/src/clone.c @@ -76,6 +76,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc) unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; sc = sc->push(); + sc->tinst = NULL; sc->speculative = true; for (size_t i = 0; i < 2; i++) @@ -419,6 +420,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc) unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; sc = sc->push(); + sc->tinst = NULL; sc->speculative = true; for (size_t j = 0; j < 2; j++) diff --git a/src/template.c b/src/template.c index 394916343466..8f6a58aa4b25 100644 --- a/src/template.c +++ b/src/template.c @@ -5198,6 +5198,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->instantiatingModule = NULL; this->inst = NULL; this->tinst = NULL; + this->deferred = NULL; this->argsym = NULL; this->aliasdecl = NULL; this->semantictiargsdone = false; @@ -5228,6 +5229,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->instantiatingModule = NULL; this->inst = NULL; this->tinst = NULL; + this->deferred = NULL; this->argsym = NULL; this->aliasdecl = NULL; this->semantictiargsdone = true; @@ -5773,9 +5775,63 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) semantic2(sc2); } - if (sc->func) + if (sc->func && aliasdecl && aliasdecl->toAlias()->isFuncDeclaration()) { + /* Template function instantiation should run semantic3 immediately + * for attribute inference. + */ + //printf("function semantic3 %s inside %s\n", toChars(), sc->func->toChars()); + trySemantic3(sc2); + } + else if (sc->func && !tinst) + { + /* If a template is instantiated inside function, the whole instantiation + * should be done at that position. But, immediate running semantic3 of + * dependent templates may cause unresolved forward reference (Bugzilla 9050). + * To avoid the issue, don't run semantic3 until semantic and semantic2 done. + */ + TemplateInstances deferred; + this->deferred = &deferred; + + //printf("Run semantic3 on %s\n", toChars()); trySemantic3(sc2); + + for (size_t i = 0; i < deferred.dim; i++) + { + //printf("+ run deferred semantic3 on %s\n", deferred[i]->toChars()); + deferred[i]->semantic3(NULL); + } + + this->deferred = NULL; + } + else if (tinst) + { + TemplateInstance *ti = tinst; + int nest = 0; + while (ti && !ti->deferred && ti->tinst) + { + ti = ti->tinst; + if (++nest > 500) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + } + if (ti && ti->deferred) + { + //printf("deferred semantic3 of %p %s, ti = %s, ti->deferred = %p\n", this, toChars(), ti->toChars()); + for (size_t i = 0; ; i++) + { + if (i == ti->deferred->dim) + { + ti->deferred->push(this); + break; + } + if ((*ti->deferred)[i] == this) + break; + } + } } Laftersemantic: diff --git a/src/template.h b/src/template.h index 883708fdd6ae..e40cf3b9f1f7 100644 --- a/src/template.h +++ b/src/template.h @@ -315,6 +315,8 @@ class TemplateInstance : public ScopeDsymbol Expressions *fargs; // for function template, these are the function arguments Module *instantiatingModule; // the top module that instantiated this instance + TemplateInstances* deferred; + TemplateInstance(Loc loc, Identifier *temp_id); TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs); static Objects *arraySyntaxCopy(Objects *objs); diff --git a/test/runnable/template9.d b/test/runnable/template9.d index 5c0a45af1c56..a6d2458f2e73 100644 --- a/test/runnable/template9.d +++ b/test/runnable/template9.d @@ -1913,6 +1913,42 @@ void test9038() check_data9038!(bar.f)(bar); } +/**********************************/ +// 9050 + +struct A9050(T) {} + +struct B9050(T) +{ + void f() { foo9050(A9050!int()); } +} + +auto foo9050()(A9050!int base) pure +{ + return B9050!int(); +} + +auto s9050 = foo9050(A9050!int()); + +/**********************************/ +// 10936 (dup of 9050) + +struct Vec10936(string s) +{ + auto foo(string v)() + { + return Vec10936!(v)(); + } + + static void bar() + { + Vec10936!"" v; + auto p = v.foo!"sup"; + } +} + +Vec10936!"" v; + /**********************************/ // 9076