1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Template implementation.
6  *
7  * Copyright:   Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved
8  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
9  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
10  * Source:      $(DMDSRC _dtemplate.d)
11  */
12 
13 module ddmd.dtemplate;
14 
15 import core.stdc.stdio;
16 import core.stdc..string;
17 import ddmd.aggregate;
18 import ddmd.aliasthis;
19 import ddmd.arraytypes;
20 import ddmd.attrib;
21 import ddmd.dcast;
22 import ddmd.dclass;
23 import ddmd.declaration;
24 import ddmd.dmangle;
25 import ddmd.dmodule;
26 import ddmd.dscope;
27 import ddmd.dsymbol;
28 import ddmd.errors;
29 import ddmd.expression;
30 import ddmd.func;
31 import ddmd.globals;
32 import ddmd.hdrgen;
33 import ddmd.id;
34 import ddmd.identifier;
35 import ddmd.init;
36 import ddmd.mtype;
37 import ddmd.opover;
38 import ddmd.root.aav;
39 import ddmd.root.outbuffer;
40 import ddmd.root.rootobject;
41 import ddmd.tokens;
42 import ddmd.visitor;
43 
44 private enum LOG = false;
45 
46 enum IDX_NOTFOUND = 0x12345678;
47 
48 /********************************************
49  * These functions substitute for dynamic_cast. dynamic_cast does not work
50  * on earlier versions of gcc.
51  */
52 extern (C++) Expression isExpression(RootObject o)
53 {
54     //return dynamic_cast<Expression *>(o);
55     if (!o || o.dyncast() != DYNCAST_EXPRESSION)
56         return null;
57     return cast(Expression)o;
58 }
59 
60 extern (C++) Dsymbol isDsymbol(RootObject o)
61 {
62     //return dynamic_cast<Dsymbol *>(o);
63     if (!o || o.dyncast() != DYNCAST_DSYMBOL)
64         return null;
65     return cast(Dsymbol)o;
66 }
67 
68 extern (C++) Type isType(RootObject o)
69 {
70     //return dynamic_cast<Type *>(o);
71     if (!o || o.dyncast() != DYNCAST_TYPE)
72         return null;
73     return cast(Type)o;
74 }
75 
76 extern (C++) Tuple isTuple(RootObject o)
77 {
78     //return dynamic_cast<Tuple *>(o);
79     if (!o || o.dyncast() != DYNCAST_TUPLE)
80         return null;
81     return cast(Tuple)o;
82 }
83 
84 extern (C++) Parameter isParameter(RootObject o)
85 {
86     //return dynamic_cast<Parameter *>(o);
87     if (!o || o.dyncast() != DYNCAST_PARAMETER)
88         return null;
89     return cast(Parameter)o;
90 }
91 
92 /**************************************
93  * Is this Object an error?
94  */
95 extern (C++) bool isError(RootObject o)
96 {
97     Type t = isType(o);
98     if (t)
99         return (t.ty == Terror);
100     Expression e = isExpression(o);
101     if (e)
102         return (e.op == TOKerror || !e.type || e.type.ty == Terror);
103     Tuple v = isTuple(o);
104     if (v)
105         return arrayObjectIsError(&v.objects);
106     Dsymbol s = isDsymbol(o);
107     assert(s);
108     if (s.errors)
109         return true;
110     return s.parent ? isError(s.parent) : false;
111 }
112 
113 /**************************************
114  * Are any of the Objects an error?
115  */
116 extern (C++) bool arrayObjectIsError(Objects* args)
117 {
118     for (size_t i = 0; i < args.dim; i++)
119     {
120         RootObject o = (*args)[i];
121         if (isError(o))
122             return true;
123     }
124     return false;
125 }
126 
127 /***********************
128  * Try to get arg as a type.
129  */
130 extern (C++) Type getType(RootObject o)
131 {
132     Type t = isType(o);
133     if (!t)
134     {
135         Expression e = isExpression(o);
136         if (e)
137             t = e.type;
138     }
139     return t;
140 }
141 
142 extern (C++) Dsymbol getDsymbol(RootObject oarg)
143 {
144     //printf("getDsymbol()\n");
145     //printf("e %p s %p t %p v %p\n", isExpression(oarg), isDsymbol(oarg), isType(oarg), isTuple(oarg));
146     Dsymbol sa;
147     Expression ea = isExpression(oarg);
148     if (ea)
149     {
150         // Try to convert Expression to symbol
151         if (ea.op == TOKvar)
152             sa = (cast(VarExp)ea).var;
153         else if (ea.op == TOKfunction)
154         {
155             if ((cast(FuncExp)ea).td)
156                 sa = (cast(FuncExp)ea).td;
157             else
158                 sa = (cast(FuncExp)ea).fd;
159         }
160         else if (ea.op == TOKtemplate)
161             sa = (cast(TemplateExp)ea).td;
162         else
163             sa = null;
164     }
165     else
166     {
167         // Try to convert Type to symbol
168         Type ta = isType(oarg);
169         if (ta)
170             sa = ta.toDsymbol(null);
171         else
172             sa = isDsymbol(oarg); // if already a symbol
173     }
174     return sa;
175 }
176 
177 private Expression getValue(ref Dsymbol s)
178 {
179     Expression e = null;
180     if (s)
181     {
182         VarDeclaration v = s.isVarDeclaration();
183         if (v && v.storage_class & STCmanifest)
184         {
185             e = v.getConstInitializer();
186         }
187     }
188     return e;
189 }
190 
191 /***********************
192  * Try to get value from manifest constant
193  */
194 private Expression getValue(Expression e)
195 {
196     if (e && e.op == TOKvar)
197     {
198         VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
199         if (v && v.storage_class & STCmanifest)
200         {
201             e = v.getConstInitializer();
202         }
203     }
204     return e;
205 }
206 
207 /******************************
208  * If o1 matches o2, return true.
209  * Else, return false.
210  */
211 private bool match(RootObject o1, RootObject o2)
212 {
213     static Expression getExpression(RootObject o)
214     {
215         auto s = isDsymbol(o);
216         return s ? .getValue(s) : .getValue(isExpression(o));
217     }
218 
219     enum debugPrint = 0;
220 
221     static if (debugPrint)
222     {
223         printf("match() o1 = %p %s (%d), o2 = %p %s (%d)\n",
224             o1, o1.toChars(), o1.dyncast(), o2, o2.toChars(), o2.dyncast());
225     }
226 
227     /* A proper implementation of the various equals() overrides
228      * should make it possible to just do o1.equals(o2), but
229      * we'll do that another day.
230      */
231     /* Manifest constants should be compared by their values,
232      * at least in template arguments.
233      */
234 
235     if (auto t1 = isType(o1))
236     {
237         auto t2 = isType(o2);
238         if (!t2)
239             goto Lnomatch;
240 
241         static if (debugPrint)
242         {
243             printf("\tt1 = %s\n", t1.toChars());
244             printf("\tt2 = %s\n", t2.toChars());
245         }
246         if (!t1.equals(t2))
247             goto Lnomatch;
248 
249         goto Lmatch;
250     }
251     if (auto e1 = getExpression(o1))
252     {
253         auto e2 = getExpression(o2);
254         if (!e2)
255             goto Lnomatch;
256 
257         static if (debugPrint)
258         {
259             printf("\te1 = %s '%s' %s\n", e1.type.toChars(), Token.toChars(e1.op), e1.toChars());
260             printf("\te2 = %s '%s' %s\n", e2.type.toChars(), Token.toChars(e2.op), e2.toChars());
261         }
262         if (!e1.equals(e2))
263             goto Lnomatch;
264 
265         goto Lmatch;
266     }
267     if (auto s1 = isDsymbol(o1))
268     {
269         auto s2 = isDsymbol(o2);
270         if (!s2)
271             goto Lnomatch;
272 
273         static if (debugPrint)
274         {
275             printf("\ts1 = %s \n", s1.kind(), s1.toChars());
276             printf("\ts2 = %s \n", s2.kind(), s2.toChars());
277         }
278         if (!s1.equals(s2))
279             goto Lnomatch;
280         if (s1.parent != s2.parent && !s1.isFuncDeclaration() && !s2.isFuncDeclaration())
281             goto Lnomatch;
282 
283         goto Lmatch;
284     }
285     if (auto u1 = isTuple(o1))
286     {
287         auto u2 = isTuple(o2);
288         if (!u2)
289             goto Lnomatch;
290 
291         static if (debugPrint)
292         {
293             printf("\tu1 = %s\n", u1.toChars());
294             printf("\tu2 = %s\n", u2.toChars());
295         }
296         if (!arrayObjectMatch(&u1.objects, &u2.objects))
297             goto Lnomatch;
298 
299         goto Lmatch;
300     }
301 Lmatch:
302     static if (debugPrint)
303         printf("\t-> match\n");
304     return true;
305 
306 Lnomatch:
307     static if (debugPrint)
308         printf("\t-> nomatch\n");
309     return false;
310 }
311 
312 /************************************
313  * Match an array of them.
314  */
315 private int arrayObjectMatch(Objects* oa1, Objects* oa2)
316 {
317     if (oa1 == oa2)
318         return 1;
319     if (oa1.dim != oa2.dim)
320         return 0;
321     for (size_t j = 0; j < oa1.dim; j++)
322     {
323         RootObject o1 = (*oa1)[j];
324         RootObject o2 = (*oa2)[j];
325         if (!match(o1, o2))
326         {
327             return 0;
328         }
329     }
330     return 1;
331 }
332 
333 /************************************
334  * Return hash of Objects.
335  */
336 private hash_t arrayObjectHash(Objects* oa1)
337 {
338     hash_t hash = 0;
339     for (size_t j = 0; j < oa1.dim; j++)
340     {
341         /* Must follow the logic of match()
342          */
343         RootObject o1 = (*oa1)[j];
344         if (Type t1 = isType(o1))
345             hash += cast(size_t)t1.deco;
346         else
347         {
348             Dsymbol s1 = isDsymbol(o1);
349             Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
350             if (e1)
351             {
352                 if (e1.op == TOKint64)
353                 {
354                     IntegerExp ne = cast(IntegerExp)e1;
355                     hash += cast(size_t)ne.getInteger();
356                 }
357             }
358             else if (s1)
359             {
360                 FuncAliasDeclaration fa1 = s1.isFuncAliasDeclaration();
361                 if (fa1)
362                     s1 = fa1.toAliasFunc();
363                 hash += cast(size_t)cast(void*)s1.getIdent() + cast(size_t)cast(void*)s1.parent;
364             }
365             else if (Tuple u1 = isTuple(o1))
366                 hash += arrayObjectHash(&u1.objects);
367         }
368     }
369     return hash;
370 }
371 
372 RootObject objectSyntaxCopy(RootObject o)
373 {
374     if (!o)
375         return null;
376     if (Type t = isType(o))
377         return t.syntaxCopy();
378     if (Expression e = isExpression(o))
379         return e.syntaxCopy();
380     return o;
381 }
382 
383 extern (C++) final class Tuple : RootObject
384 {
385     Objects objects;
386 
387     // kludge for template.isType()
388     override int dyncast()
389     {
390         return DYNCAST_TUPLE;
391     }
392 
393     override const(char)* toChars()
394     {
395         return objects.toChars();
396     }
397 }
398 
399 struct TemplatePrevious
400 {
401     TemplatePrevious* prev;
402     Scope* sc;
403     Objects* dedargs;
404 }
405 
406 /***********************************************************
407  */
408 extern (C++) final class TemplateDeclaration : ScopeDsymbol
409 {
410     TemplateParameters* parameters;     // array of TemplateParameter's
411     TemplateParameters* origParameters; // originals for Ddoc
412 
413     Expression constraint;
414 
415     // Hash table to look up TemplateInstance's of this TemplateDeclaration
416     TemplateInstance[TemplateInstanceBox] instances;
417 
418     TemplateDeclaration overnext;       // next overloaded TemplateDeclaration
419     TemplateDeclaration overroot;       // first in overnext list
420     FuncDeclaration funcroot;           // first function in unified overload list
421 
422     Dsymbol onemember;      // if !=null then one member of this template
423 
424     bool literal;           // this template declaration is a literal
425     bool ismixin;           // template declaration is only to be used as a mixin
426     bool isstatic;          // this is static template declaration
427     Prot protection;
428 
429     // threaded list of previous instantiation attempts on stack
430     TemplatePrevious* previous;
431 
432     extern (D) this(Loc loc, Identifier id, TemplateParameters* parameters, Expression constraint, Dsymbols* decldefs, bool ismixin = false, bool literal = false)
433     {
434         super(id);
435         static if (LOG)
436         {
437             printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id.toChars());
438         }
439         version (none)
440         {
441             if (parameters)
442                 for (int i = 0; i < parameters.dim; i++)
443                 {
444                     TemplateParameter tp = (*parameters)[i];
445                     //printf("\tparameter[%d] = %p\n", i, tp);
446                     TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
447                     if (ttp)
448                     {
449                         printf("\tparameter[%d] = %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
450                     }
451                 }
452         }
453         this.loc = loc;
454         this.parameters = parameters;
455         this.origParameters = parameters;
456         this.constraint = constraint;
457         this.members = decldefs;
458         this.literal = literal;
459         this.ismixin = ismixin;
460         this.isstatic = true;
461         this.protection = Prot(PROTundefined);
462 
463         // Compute in advance for Ddoc's use
464         // https://issues.dlang.org/show_bug.cgi?id=11153: ident could be NULL if parsing fails.
465         if (members && ident)
466         {
467             Dsymbol s;
468             if (Dsymbol.oneMembers(members, &s, ident) && s)
469             {
470                 onemember = s;
471                 s.parent = this;
472             }
473         }
474     }
475 
476     override Dsymbol syntaxCopy(Dsymbol)
477     {
478         //printf("TemplateDeclaration.syntaxCopy()\n");
479         TemplateParameters* p = null;
480         if (parameters)
481         {
482             p = new TemplateParameters();
483             p.setDim(parameters.dim);
484             for (size_t i = 0; i < p.dim; i++)
485                 (*p)[i] = (*parameters)[i].syntaxCopy();
486         }
487         return new TemplateDeclaration(loc, ident, p, constraint ? constraint.syntaxCopy() : null, Dsymbol.arraySyntaxCopy(members), ismixin, literal);
488     }
489 
490     override void semantic(Scope* sc)
491     {
492         static if (LOG)
493         {
494             printf("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars());
495             printf("sc.stc = %llx\n", sc.stc);
496             printf("sc.module = %s\n", sc._module.toChars());
497         }
498         if (semanticRun != PASSinit)
499             return; // semantic() already run
500         semanticRun = PASSsemantic;
501 
502         // Remember templates defined in module object that we need to know about
503         if (sc._module && sc._module.ident == Id.object)
504         {
505             if (ident == Id.RTInfo)
506                 Type.rtinfo = this;
507         }
508 
509         /* Remember Scope for later instantiations, but make
510          * a copy since attributes can change.
511          */
512         if (!this._scope)
513         {
514             this._scope = sc.copy();
515             this._scope.setNoFree();
516         }
517 
518         parent = sc.parent;
519         protection = sc.protection;
520         isstatic = toParent().isModule() || (_scope.stc & STCstatic);
521 
522         if (!isstatic)
523         {
524             if (auto ad = parent.pastMixin().isAggregateDeclaration())
525                 ad.makeNested();
526         }
527 
528         // Set up scope for parameters
529         auto paramsym = new ScopeDsymbol();
530         paramsym.parent = parent;
531         Scope* paramscope = sc.push(paramsym);
532         paramscope.stc = 0;
533 
534         if (global.params.doDocComments)
535         {
536             origParameters = new TemplateParameters();
537             origParameters.setDim(parameters.dim);
538             for (size_t i = 0; i < parameters.dim; i++)
539             {
540                 TemplateParameter tp = (*parameters)[i];
541                 (*origParameters)[i] = tp.syntaxCopy();
542             }
543         }
544 
545         for (size_t i = 0; i < parameters.dim; i++)
546         {
547             TemplateParameter tp = (*parameters)[i];
548             if (!tp.declareParameter(paramscope))
549             {
550                 error(tp.loc, "parameter '%s' multiply defined", tp.ident.toChars());
551                 errors = true;
552             }
553             if (!tp.semantic(paramscope, parameters))
554             {
555                 errors = true;
556             }
557             if (i + 1 != parameters.dim && tp.isTemplateTupleParameter())
558             {
559                 error("template tuple parameter must be last one");
560                 errors = true;
561             }
562         }
563 
564         /* Calculate TemplateParameter.dependent
565          */
566         TemplateParameters tparams;
567         tparams.setDim(1);
568         for (size_t i = 0; i < parameters.dim; i++)
569         {
570             TemplateParameter tp = (*parameters)[i];
571             tparams[0] = tp;
572 
573             for (size_t j = 0; j < parameters.dim; j++)
574             {
575                 // Skip cases like: X(T : T)
576                 if (i == j)
577                     continue;
578 
579                 if (TemplateTypeParameter ttp = (*parameters)[j].isTemplateTypeParameter())
580                 {
581                     if (reliesOnTident(ttp.specType, &tparams))
582                         tp.dependent = true;
583                 }
584                 else if (TemplateAliasParameter tap = (*parameters)[j].isTemplateAliasParameter())
585                 {
586                     if (reliesOnTident(tap.specType, &tparams) ||
587                         reliesOnTident(isType(tap.specAlias), &tparams))
588                     {
589                         tp.dependent = true;
590                     }
591                 }
592             }
593         }
594 
595         paramscope.pop();
596 
597         // Compute again
598         onemember = null;
599         if (members)
600         {
601             Dsymbol s;
602             if (Dsymbol.oneMembers(members, &s, ident) && s)
603             {
604                 onemember = s;
605                 s.parent = this;
606             }
607         }
608 
609         /* BUG: should check:
610          *  o no virtual functions or non-static data members of classes
611          */
612     }
613 
614     /**********************************
615      * Overload existing TemplateDeclaration 'this' with the new one 's'.
616      * Return true if successful; i.e. no conflict.
617      */
618     override bool overloadInsert(Dsymbol s)
619     {
620         static if (LOG)
621         {
622             printf("TemplateDeclaration.overloadInsert('%s')\n", s.toChars());
623         }
624         FuncDeclaration fd = s.isFuncDeclaration();
625         if (fd)
626         {
627             if (funcroot)
628                 return funcroot.overloadInsert(fd);
629             funcroot = fd;
630             return funcroot.overloadInsert(this);
631         }
632 
633         TemplateDeclaration td = s.isTemplateDeclaration();
634         if (!td)
635             return false;
636 
637         TemplateDeclaration pthis = this;
638         TemplateDeclaration* ptd;
639         for (ptd = &pthis; *ptd; ptd = &(*ptd).overnext)
640         {
641         }
642 
643         td.overroot = this;
644         *ptd = td;
645         static if (LOG)
646         {
647             printf("\ttrue: no conflict\n");
648         }
649         return true;
650     }
651 
652     override bool hasStaticCtorOrDtor()
653     {
654         return false; // don't scan uninstantiated templates
655     }
656 
657     override const(char)* kind() const
658     {
659         return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template";
660     }
661 
662     override const(char)* toChars()
663     {
664         if (literal)
665             return Dsymbol.toChars();
666 
667         OutBuffer buf;
668         HdrGenState hgs;
669 
670         buf.writestring(ident.toChars());
671         buf.writeByte('(');
672         for (size_t i = 0; i < parameters.dim; i++)
673         {
674             TemplateParameter tp = (*parameters)[i];
675             if (i)
676                 buf.writestring(", ");
677             .toCBuffer(tp, &buf, &hgs);
678         }
679         buf.writeByte(')');
680 
681         if (onemember)
682         {
683             FuncDeclaration fd = onemember.isFuncDeclaration();
684             if (fd && fd.type)
685             {
686                 TypeFunction tf = cast(TypeFunction)fd.type;
687                 buf.writestring(parametersTypeToChars(tf.parameters, tf.varargs));
688             }
689         }
690 
691         if (constraint)
692         {
693             buf.writestring(" if (");
694             .toCBuffer(constraint, &buf, &hgs);
695             buf.writeByte(')');
696         }
697         return buf.extractString();
698     }
699 
700     override Prot prot()
701     {
702         return protection;
703     }
704 
705     /****************************
706      * Check to see if constraint is satisfied.
707      */
708     bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
709     {
710         /* Detect recursive attempts to instantiate this template declaration,
711          * https://issues.dlang.org/show_bug.cgi?id=4072
712          *  void foo(T)(T x) if (is(typeof(foo(x)))) { }
713          *  static assert(!is(typeof(foo(7))));
714          * Recursive attempts are regarded as a constraint failure.
715          */
716         /* There's a chicken-and-egg problem here. We don't know yet if this template
717          * instantiation will be a local one (enclosing is set), and we won't know until
718          * after selecting the correct template. Thus, function we're nesting inside
719          * is not on the sc scope chain, and this can cause errors in FuncDeclaration.getLevel().
720          * Workaround the problem by setting a flag to relax the checking on frame errors.
721          */
722 
723         for (TemplatePrevious* p = previous; p; p = p.prev)
724         {
725             if (arrayObjectMatch(p.dedargs, dedargs))
726             {
727                 //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
728                 /* It must be a subscope of p.sc, other scope chains are not recursive
729                  * instantiations.
730                  */
731                 for (Scope* scx = sc; scx; scx = scx.enclosing)
732                 {
733                     if (scx == p.sc)
734                         return false;
735                 }
736             }
737             /* BUG: should also check for ref param differences
738              */
739         }
740 
741         TemplatePrevious pr;
742         pr.prev = previous;
743         pr.sc = paramscope;
744         pr.dedargs = dedargs;
745         previous = &pr; // add this to threaded list
746 
747         uint nerrors = global.errors;
748 
749         Scope* scx = paramscope.push(ti);
750         scx.parent = ti;
751         scx.tinst = null;
752         scx.minst = null;
753 
754         assert(!ti.symtab);
755         if (fd)
756         {
757             /* Declare all the function parameters as variables and add them to the scope
758              * Making parameters is similar to FuncDeclaration.semantic3
759              */
760             TypeFunction tf = cast(TypeFunction)fd.type;
761             assert(tf.ty == Tfunction);
762 
763             scx.parent = fd;
764 
765             Parameters* fparameters = tf.parameters;
766             int fvarargs = tf.varargs;
767             size_t nfparams = Parameter.dim(fparameters);
768             for (size_t i = 0; i < nfparams; i++)
769             {
770                 Parameter fparam = Parameter.getNth(fparameters, i);
771                 fparam.storageClass &= (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
772                 fparam.storageClass |= STCparameter;
773                 if (fvarargs == 2 && i + 1 == nfparams)
774                     fparam.storageClass |= STCvariadic;
775             }
776             for (size_t i = 0; i < fparameters.dim; i++)
777             {
778                 Parameter fparam = (*fparameters)[i];
779                 if (!fparam.ident)
780                     continue;
781                 // don't add it, if it has no name
782                 auto v = new VarDeclaration(loc, fparam.type, fparam.ident, null);
783                 v.storage_class = fparam.storageClass;
784                 v.semantic(scx);
785                 if (!ti.symtab)
786                     ti.symtab = new DsymbolTable();
787                 if (!scx.insert(v))
788                     error("parameter %s.%s is already defined", toChars(), v.toChars());
789                 else
790                     v.parent = fd;
791             }
792             if (isstatic)
793                 fd.storage_class |= STCstatic;
794             fd.vthis = fd.declareThis(scx, fd.isThis());
795         }
796 
797         Expression e = constraint.syntaxCopy();
798 
799         scx = scx.startCTFE();
800         scx.flags |= SCOPEcondition | SCOPEconstraint;
801         assert(ti.inst is null);
802         ti.inst = ti; // temporary instantiation to enable genIdent()
803 
804         //printf("\tscx.parent = %s %s\n", scx.parent.kind(), scx.parent.toPrettyChars());
805         e = e.semantic(scx);
806         e = resolveProperties(scx, e);
807 
808         ti.inst = null;
809         ti.symtab = null;
810         scx = scx.endCTFE();
811 
812         scx = scx.pop();
813         previous = pr.prev; // unlink from threaded list
814 
815         if (nerrors != global.errors) // if any errors from evaluating the constraint, no match
816             return false;
817         if (e.op == TOKerror)
818             return false;
819 
820         e = e.ctfeInterpret();
821         if (e.isBool(true))
822         {
823         }
824         else if (e.isBool(false))
825             return false;
826         else
827         {
828             e.error("constraint %s is not constant or does not evaluate to a bool", e.toChars());
829         }
830         return true;
831     }
832 
833     /***************************************
834      * Given that ti is an instance of this TemplateDeclaration,
835      * deduce the types of the parameters to this, and store
836      * those deduced types in dedtypes[].
837      * Input:
838      *      flag    1: don't do semantic() because of dummy types
839      *              2: don't change types in matchArg()
840      * Output:
841      *      dedtypes        deduced arguments
842      * Return match level.
843      */
844     MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, Expressions* fargs, int flag)
845     {
846         enum LOGM = 0;
847         static if (LOGM)
848         {
849             printf("\n+TemplateDeclaration.matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti.toChars(), flag);
850         }
851         version (none)
852         {
853             printf("dedtypes.dim = %d, parameters.dim = %d\n", dedtypes.dim, parameters.dim);
854             if (ti.tiargs.dim)
855                 printf("ti.tiargs.dim = %d, [0] = %p\n", ti.tiargs.dim, (*ti.tiargs)[0]);
856         }
857         MATCH m;
858         size_t dedtypes_dim = dedtypes.dim;
859 
860         dedtypes.zero();
861 
862         if (errors)
863             return MATCHnomatch;
864 
865         size_t parameters_dim = parameters.dim;
866         int variadic = isVariadic() !is null;
867 
868         // If more arguments than parameters, no match
869         if (ti.tiargs.dim > parameters_dim && !variadic)
870         {
871             static if (LOGM)
872             {
873                 printf(" no match: more arguments than parameters\n");
874             }
875             return MATCHnomatch;
876         }
877 
878         assert(dedtypes_dim == parameters_dim);
879         assert(dedtypes_dim >= ti.tiargs.dim || variadic);
880 
881         assert(_scope);
882 
883         // Set up scope for template parameters
884         auto paramsym = new ScopeDsymbol();
885         paramsym.parent = _scope.parent;
886         Scope* paramscope = _scope.push(paramsym);
887         paramscope.tinst = ti;
888         paramscope.minst = sc.minst;
889         paramscope.callsc = sc;
890         paramscope.stc = 0;
891 
892         // Attempt type deduction
893         m = MATCHexact;
894         for (size_t i = 0; i < dedtypes_dim; i++)
895         {
896             MATCH m2;
897             TemplateParameter tp = (*parameters)[i];
898             Declaration sparam;
899 
900             //printf("\targument [%d]\n", i);
901             static if (LOGM)
902             {
903                 //printf("\targument [%d] is %s\n", i, oarg ? oarg.toChars() : "null");
904                 TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
905                 if (ttp)
906                     printf("\tparameter[%d] is %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
907             }
908 
909             m2 = tp.matchArg(ti.loc, paramscope, ti.tiargs, i, parameters, dedtypes, &sparam);
910             //printf("\tm2 = %d\n", m2);
911             if (m2 == MATCHnomatch)
912             {
913                 version (none)
914                 {
915                     printf("\tmatchArg() for parameter %i failed\n", i);
916                 }
917                 goto Lnomatch;
918             }
919 
920             if (m2 < m)
921                 m = m2;
922 
923             if (!flag)
924                 sparam.semantic(paramscope);
925             if (!paramscope.insert(sparam)) // TODO: This check can make more early
926             {
927                 // in TemplateDeclaration.semantic, and
928                 // then we don't need to make sparam if flags == 0
929                 goto Lnomatch;
930             }
931         }
932 
933         if (!flag)
934         {
935             /* Any parameter left without a type gets the type of
936              * its corresponding arg
937              */
938             for (size_t i = 0; i < dedtypes_dim; i++)
939             {
940                 if (!(*dedtypes)[i])
941                 {
942                     assert(i < ti.tiargs.dim);
943                     (*dedtypes)[i] = cast(Type)(*ti.tiargs)[i];
944                 }
945             }
946         }
947 
948         if (m > MATCHnomatch && constraint && !flag)
949         {
950             if (ti.hasNestedArgs(ti.tiargs, this.isstatic)) // TODO: should gag error
951                 ti.parent = ti.enclosing;
952             else
953                 ti.parent = this.parent;
954 
955             // Similar to doHeaderInstantiation
956             FuncDeclaration fd = onemember ? onemember.isFuncDeclaration() : null;
957             if (fd)
958             {
959                 assert(fd.type.ty == Tfunction);
960                 TypeFunction tf = cast(TypeFunction)fd.type.syntaxCopy();
961 
962                 fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf);
963                 fd.parent = ti;
964                 fd.inferRetType = true;
965 
966                 // Shouldn't run semantic on default arguments and return type.
967                 for (size_t i = 0; i < tf.parameters.dim; i++)
968                     (*tf.parameters)[i].defaultArg = null;
969                 tf.next = null;
970 
971                 // Resolve parameter types and 'auto ref's.
972                 tf.fargs = fargs;
973                 uint olderrors = global.startGagging();
974                 fd.type = tf.semantic(loc, paramscope);
975                 if (global.endGagging(olderrors))
976                 {
977                     assert(fd.type.ty != Tfunction);
978                     goto Lnomatch;
979                 }
980                 assert(fd.type.ty == Tfunction);
981                 fd.originalType = fd.type; // for mangling
982             }
983 
984             // TODO: dedtypes => ti.tiargs ?
985             if (!evaluateConstraint(ti, sc, paramscope, dedtypes, fd))
986                 goto Lnomatch;
987         }
988 
989         static if (LOGM)
990         {
991             // Print out the results
992             printf("--------------------------\n");
993             printf("template %s\n", toChars());
994             printf("instance %s\n", ti.toChars());
995             if (m > MATCHnomatch)
996             {
997                 for (size_t i = 0; i < dedtypes_dim; i++)
998                 {
999                     TemplateParameter tp = (*parameters)[i];
1000                     RootObject oarg;
1001                     printf(" [%d]", i);
1002                     if (i < ti.tiargs.dim)
1003                         oarg = (*ti.tiargs)[i];
1004                     else
1005                         oarg = null;
1006                     tp.print(oarg, (*dedtypes)[i]);
1007                 }
1008             }
1009             else
1010                 goto Lnomatch;
1011         }
1012         static if (LOGM)
1013         {
1014             printf(" match = %d\n", m);
1015         }
1016         goto Lret;
1017 
1018     Lnomatch:
1019         static if (LOGM)
1020         {
1021             printf(" no match\n");
1022         }
1023         m = MATCHnomatch;
1024 
1025     Lret:
1026         paramscope.pop();
1027         static if (LOGM)
1028         {
1029             printf("-TemplateDeclaration.matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
1030         }
1031         return m;
1032     }
1033 
1034     /********************************************
1035      * Determine partial specialization order of 'this' vs td2.
1036      * Returns:
1037      *      match   this is at least as specialized as td2
1038      *      0       td2 is more specialized than this
1039      */
1040     MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, Expressions* fargs)
1041     {
1042         enum LOG_LEASTAS = 0;
1043         static if (LOG_LEASTAS)
1044         {
1045             printf("%s.leastAsSpecialized(%s)\n", toChars(), td2.toChars());
1046         }
1047 
1048         /* This works by taking the template parameters to this template
1049          * declaration and feeding them to td2 as if it were a template
1050          * instance.
1051          * If it works, then this template is at least as specialized
1052          * as td2.
1053          */
1054 
1055         // Set type arguments to dummy template instance to be types
1056         // generated from the parameters to this template declaration
1057         auto tiargs = new Objects();
1058         tiargs.reserve(parameters.dim);
1059         for (size_t i = 0; i < parameters.dim; i++)
1060         {
1061             TemplateParameter tp = (*parameters)[i];
1062             if (tp.dependent)
1063                 break;
1064             RootObject p = cast(RootObject)tp.dummyArg();
1065             if (!p)
1066                 break;
1067 
1068             tiargs.push(p);
1069         }
1070         scope TemplateInstance ti = new TemplateInstance(Loc(), ident, tiargs); // create dummy template instance
1071 
1072         // Temporary Array to hold deduced types
1073         Objects dedtypes;
1074         dedtypes.setDim(td2.parameters.dim);
1075 
1076         // Attempt a type deduction
1077         MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, fargs, 1);
1078         if (m > MATCHnomatch)
1079         {
1080             /* A non-variadic template is more specialized than a
1081              * variadic one.
1082              */
1083             TemplateTupleParameter tp = isVariadic();
1084             if (tp && !tp.dependent && !td2.isVariadic())
1085                 goto L1;
1086 
1087             static if (LOG_LEASTAS)
1088             {
1089                 printf("  matches %d, so is least as specialized\n", m);
1090             }
1091             return m;
1092         }
1093     L1:
1094         static if (LOG_LEASTAS)
1095         {
1096             printf("  doesn't match, so is not as specialized\n");
1097         }
1098         return MATCHnomatch;
1099     }
1100 
1101     /*************************************************
1102      * Match function arguments against a specific template function.
1103      * Input:
1104      *      ti
1105      *      sc              instantiation scope
1106      *      fd
1107      *      tthis           'this' argument if !NULL
1108      *      fargs           arguments to function
1109      * Output:
1110      *      fd              Partially instantiated function declaration
1111      *      ti.tdtypes     Expression/Type deduced template arguments
1112      * Returns:
1113      *      match level
1114      *          bit 0-3     Match template parameters by inferred template arguments
1115      *          bit 4-7     Match template parameters by initial template arguments
1116      */
1117     MATCH deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, Expressions* fargs)
1118     {
1119         size_t nfparams;
1120         size_t nfargs;
1121         size_t ntargs; // array size of tiargs
1122         size_t fptupindex = IDX_NOTFOUND;
1123         MATCH match = MATCHexact;
1124         MATCH matchTiargs = MATCHexact;
1125         Parameters* fparameters; // function parameter list
1126         int fvarargs; // function varargs
1127         uint wildmatch = 0;
1128         size_t inferStart = 0;
1129 
1130         Loc instLoc = ti.loc;
1131         Objects* tiargs = ti.tiargs;
1132         auto dedargs = new Objects();
1133         Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
1134 
1135         version (none)
1136         {
1137             printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars());
1138             for (size_t i = 0; i < (fargs ? fargs.dim : 0); i++)
1139             {
1140                 Expression e = (*fargs)[i];
1141                 printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars());
1142             }
1143             printf("fd = %s\n", fd.toChars());
1144             printf("fd.type = %s\n", fd.type.toChars());
1145             if (tthis)
1146                 printf("tthis = %s\n", tthis.toChars());
1147         }
1148 
1149         assert(_scope);
1150 
1151         dedargs.setDim(parameters.dim);
1152         dedargs.zero();
1153 
1154         dedtypes.setDim(parameters.dim);
1155         dedtypes.zero();
1156 
1157         if (errors || fd.errors)
1158             return MATCHnomatch;
1159 
1160         // Set up scope for parameters
1161         auto paramsym = new ScopeDsymbol();
1162         paramsym.parent = _scope.parent; // should use hasnestedArgs and enclosing?
1163         Scope* paramscope = _scope.push(paramsym);
1164         paramscope.tinst = ti;
1165         paramscope.minst = sc.minst;
1166         paramscope.callsc = sc;
1167         paramscope.stc = 0;
1168 
1169         TemplateTupleParameter tp = isVariadic();
1170         Tuple declaredTuple = null;
1171 
1172         version (none)
1173         {
1174             for (size_t i = 0; i < dedargs.dim; i++)
1175             {
1176                 printf("\tdedarg[%d] = ", i);
1177                 RootObject oarg = (*dedargs)[i];
1178                 if (oarg)
1179                     printf("%s", oarg.toChars());
1180                 printf("\n");
1181             }
1182         }
1183 
1184         ntargs = 0;
1185         if (tiargs)
1186         {
1187             // Set initial template arguments
1188             ntargs = tiargs.dim;
1189             size_t n = parameters.dim;
1190             if (tp)
1191                 n--;
1192             if (ntargs > n)
1193             {
1194                 if (!tp)
1195                     goto Lnomatch;
1196 
1197                 /* The extra initial template arguments
1198                  * now form the tuple argument.
1199                  */
1200                 auto t = new Tuple();
1201                 assert(parameters.dim);
1202                 (*dedargs)[parameters.dim - 1] = t;
1203 
1204                 t.objects.setDim(ntargs - n);
1205                 for (size_t i = 0; i < t.objects.dim; i++)
1206                 {
1207                     t.objects[i] = (*tiargs)[n + i];
1208                 }
1209                 declareParameter(paramscope, tp, t);
1210                 declaredTuple = t;
1211             }
1212             else
1213                 n = ntargs;
1214 
1215             memcpy(dedargs.tdata(), tiargs.tdata(), n * (*dedargs.tdata()).sizeof);
1216 
1217             for (size_t i = 0; i < n; i++)
1218             {
1219                 assert(i < parameters.dim);
1220                 Declaration sparam = null;
1221                 MATCH m = (*parameters)[i].matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, &sparam);
1222                 //printf("\tdeduceType m = %d\n", m);
1223                 if (m <= MATCHnomatch)
1224                     goto Lnomatch;
1225                 if (m < matchTiargs)
1226                     matchTiargs = m;
1227 
1228                 sparam.semantic(paramscope);
1229                 if (!paramscope.insert(sparam))
1230                     goto Lnomatch;
1231             }
1232             if (n < parameters.dim && !declaredTuple)
1233             {
1234                 inferStart = n;
1235             }
1236             else
1237                 inferStart = parameters.dim;
1238             //printf("tiargs matchTiargs = %d\n", matchTiargs);
1239         }
1240         version (none)
1241         {
1242             for (size_t i = 0; i < dedargs.dim; i++)
1243             {
1244                 printf("\tdedarg[%d] = ", i);
1245                 RootObject oarg = (*dedargs)[i];
1246                 if (oarg)
1247                     printf("%s", oarg.toChars());
1248                 printf("\n");
1249             }
1250         }
1251 
1252         fparameters = fd.getParameters(&fvarargs);
1253         nfparams = Parameter.dim(fparameters); // number of function parameters
1254         nfargs = fargs ? fargs.dim : 0; // number of function arguments
1255 
1256         /* Check for match of function arguments with variadic template
1257          * parameter, such as:
1258          *
1259          * void foo(T, A...)(T t, A a);
1260          * void main() { foo(1,2,3); }
1261          */
1262         if (tp) // if variadic
1263         {
1264             // TemplateTupleParameter always makes most lesser matching.
1265             matchTiargs = MATCHconvert;
1266 
1267             if (nfparams == 0 && nfargs != 0) // if no function parameters
1268             {
1269                 if (!declaredTuple)
1270                 {
1271                     auto t = new Tuple();
1272                     //printf("t = %p\n", t);
1273                     (*dedargs)[parameters.dim - 1] = t;
1274                     declareParameter(paramscope, tp, t);
1275                     declaredTuple = t;
1276                 }
1277             }
1278             else
1279             {
1280                 /* Figure out which of the function parameters matches
1281                  * the tuple template parameter. Do this by matching
1282                  * type identifiers.
1283                  * Set the index of this function parameter to fptupindex.
1284                  */
1285                 for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
1286                 {
1287                     Parameter fparam = (*fparameters)[fptupindex];
1288                     if (fparam.type.ty != Tident)
1289                         continue;
1290                     TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
1291                     if (!tp.ident.equals(tid.ident) || tid.idents.dim)
1292                         continue;
1293 
1294                     if (fvarargs) // variadic function doesn't
1295                         goto Lnomatch; // go with variadic template
1296 
1297                     goto L1;
1298                 }
1299                 fptupindex = IDX_NOTFOUND;
1300             L1:
1301             }
1302         }
1303 
1304         if (toParent().isModule() || (_scope.stc & STCstatic))
1305             tthis = null;
1306         if (tthis)
1307         {
1308             bool hasttp = false;
1309 
1310             // Match 'tthis' to any TemplateThisParameter's
1311             for (size_t i = 0; i < parameters.dim; i++)
1312             {
1313                 TemplateThisParameter ttp = (*parameters)[i].isTemplateThisParameter();
1314                 if (ttp)
1315                 {
1316                     hasttp = true;
1317 
1318                     Type t = new TypeIdentifier(Loc(), ttp.ident);
1319                     MATCH m = deduceType(tthis, paramscope, t, parameters, dedtypes);
1320                     if (m <= MATCHnomatch)
1321                         goto Lnomatch;
1322                     if (m < match)
1323                         match = m; // pick worst match
1324                 }
1325             }
1326 
1327             // Match attributes of tthis against attributes of fd
1328             if (fd.type && !fd.isCtorDeclaration())
1329             {
1330                 StorageClass stc = _scope.stc | fd.storage_class2;
1331                 // Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
1332                 Dsymbol p = parent;
1333                 while (p.isTemplateDeclaration() || p.isTemplateInstance())
1334                     p = p.parent;
1335                 AggregateDeclaration ad = p.isAggregateDeclaration();
1336                 if (ad)
1337                     stc |= ad.storage_class;
1338 
1339                 ubyte mod = fd.type.mod;
1340                 if (stc & STCimmutable)
1341                     mod = MODimmutable;
1342                 else
1343                 {
1344                     if (stc & (STCshared | STCsynchronized))
1345                         mod |= MODshared;
1346                     if (stc & STCconst)
1347                         mod |= MODconst;
1348                     if (stc & STCwild)
1349                         mod |= MODwild;
1350                 }
1351 
1352                 ubyte thismod = tthis.mod;
1353                 if (hasttp)
1354                     mod = MODmerge(thismod, mod);
1355                 MATCH m = MODmethodConv(thismod, mod);
1356                 if (m <= MATCHnomatch)
1357                     goto Lnomatch;
1358                 if (m < match)
1359                     match = m;
1360             }
1361         }
1362 
1363         // Loop through the function parameters
1364         {
1365             //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.dim : 0);
1366             //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL);
1367             size_t argi = 0;
1368             size_t nfargs2 = nfargs; // nfargs + supplied defaultArgs
1369             for (size_t parami = 0; parami < nfparams; parami++)
1370             {
1371                 Parameter fparam = Parameter.getNth(fparameters, parami);
1372 
1373                 // Apply function parameter storage classes to parameter types
1374                 Type prmtype = fparam.type.addStorageClass(fparam.storageClass);
1375 
1376                 Expression farg;
1377 
1378                 /* See function parameters which wound up
1379                  * as part of a template tuple parameter.
1380                  */
1381                 if (fptupindex != IDX_NOTFOUND && parami == fptupindex)
1382                 {
1383                     assert(prmtype.ty == Tident);
1384                     TypeIdentifier tid = cast(TypeIdentifier)prmtype;
1385                     if (!declaredTuple)
1386                     {
1387                         /* The types of the function arguments
1388                          * now form the tuple argument.
1389                          */
1390                         declaredTuple = new Tuple();
1391                         (*dedargs)[parameters.dim - 1] = declaredTuple;
1392 
1393                         /* Count function parameters following a tuple parameter.
1394                          * void foo(U, T...)(int y, T, U, int) {}  // rem == 2 (U, int)
1395                          */
1396                         size_t rem = 0;
1397                         for (size_t j = parami + 1; j < nfparams; j++)
1398                         {
1399                             Parameter p = Parameter.getNth(fparameters, j);
1400                             if (!reliesOnTident(p.type, parameters, inferStart))
1401                             {
1402                                 Type pt = p.type.syntaxCopy().semantic(fd.loc, paramscope);
1403                                 rem += pt.ty == Ttuple ? (cast(TypeTuple)pt).arguments.dim : 1;
1404                             }
1405                             else
1406                             {
1407                                 ++rem;
1408                             }
1409                         }
1410 
1411                         if (nfargs2 - argi < rem)
1412                             goto Lnomatch;
1413                         declaredTuple.objects.setDim(nfargs2 - argi - rem);
1414                         for (size_t i = 0; i < declaredTuple.objects.dim; i++)
1415                         {
1416                             farg = (*fargs)[argi + i];
1417 
1418                             // Check invalid arguments to detect errors early.
1419                             if (farg.op == TOKerror || farg.type.ty == Terror)
1420                                 goto Lnomatch;
1421 
1422                             if (!(fparam.storageClass & STClazy) && farg.type.ty == Tvoid)
1423                                 goto Lnomatch;
1424 
1425                             Type tt;
1426                             MATCH m;
1427                             if (ubyte wm = deduceWildHelper(farg.type, &tt, tid))
1428                             {
1429                                 wildmatch |= wm;
1430                                 m = MATCHconst;
1431                             }
1432                             else
1433                             {
1434                                 m = deduceTypeHelper(farg.type, &tt, tid);
1435                             }
1436                             if (m <= MATCHnomatch)
1437                                 goto Lnomatch;
1438                             if (m < match)
1439                                 match = m;
1440 
1441                             /* Remove top const for dynamic array types and pointer types
1442                              */
1443                             if ((tt.ty == Tarray || tt.ty == Tpointer) && !tt.isMutable() && (!(fparam.storageClass & STCref) || (fparam.storageClass & STCauto) && !farg.isLvalue()))
1444                             {
1445                                 tt = tt.mutableOf();
1446                             }
1447                             declaredTuple.objects[i] = tt;
1448                         }
1449                         declareParameter(paramscope, tp, declaredTuple);
1450                     }
1451                     else
1452                     {
1453                         // https://issues.dlang.org/show_bug.cgi?id=6810
1454                         // If declared tuple is not a type tuple,
1455                         // it cannot be function parameter types.
1456                         for (size_t i = 0; i < declaredTuple.objects.dim; i++)
1457                         {
1458                             if (!isType(declaredTuple.objects[i]))
1459                                 goto Lnomatch;
1460                         }
1461                     }
1462                     assert(declaredTuple);
1463                     argi += declaredTuple.objects.dim;
1464                     continue;
1465                 }
1466 
1467                 // If parameter type doesn't depend on inferred template parameters,
1468                 // semantic it to get actual type.
1469                 if (!reliesOnTident(prmtype, parameters, inferStart))
1470                 {
1471                     // should copy prmtype to avoid affecting semantic result
1472                     prmtype = prmtype.syntaxCopy().semantic(fd.loc, paramscope);
1473 
1474                     if (prmtype.ty == Ttuple)
1475                     {
1476                         TypeTuple tt = cast(TypeTuple)prmtype;
1477                         size_t tt_dim = tt.arguments.dim;
1478                         for (size_t j = 0; j < tt_dim; j++, ++argi)
1479                         {
1480                             Parameter p = (*tt.arguments)[j];
1481                             if (j == tt_dim - 1 && fvarargs == 2 && parami + 1 == nfparams && argi < nfargs)
1482                             {
1483                                 prmtype = p.type;
1484                                 goto Lvarargs;
1485                             }
1486                             if (argi >= nfargs)
1487                             {
1488                                 if (p.defaultArg)
1489                                     continue;
1490                                 goto Lnomatch;
1491                             }
1492                             farg = (*fargs)[argi];
1493                             if (!farg.implicitConvTo(p.type))
1494                                 goto Lnomatch;
1495                         }
1496                         continue;
1497                     }
1498                 }
1499 
1500                 if (argi >= nfargs) // if not enough arguments
1501                 {
1502                     if (!fparam.defaultArg)
1503                         goto Lvarargs;
1504 
1505                     /* https://issues.dlang.org/show_bug.cgi?id=2803
1506                      * Before the starting of type deduction from the function
1507                      * default arguments, set the already deduced parameters into paramscope.
1508                      * It's necessary to avoid breaking existing acceptable code. Cases:
1509                      *
1510                      * 1. Already deduced template parameters can appear in fparam.defaultArg:
1511                      *  auto foo(A, B)(A a, B b = A.stringof);
1512                      *  foo(1);
1513                      *  // at fparam == 'B b = A.string', A is equivalent with the deduced type 'int'
1514                      *
1515                      * 2. If prmtype depends on default-specified template parameter, the
1516                      * default type should be preferred.
1517                      *  auto foo(N = size_t, R)(R r, N start = 0)
1518                      *  foo([1,2,3]);
1519                      *  // at fparam `N start = 0`, N should be 'size_t' before
1520                      *  // the deduction result from fparam.defaultArg.
1521                      */
1522                     if (argi == nfargs)
1523                     {
1524                         for (size_t i = 0; i < dedtypes.dim; i++)
1525                         {
1526                             Type at = isType((*dedtypes)[i]);
1527                             if (at && at.ty == Tnone)
1528                             {
1529                                 TypeDeduced xt = cast(TypeDeduced)at;
1530                                 (*dedtypes)[i] = xt.tded; // 'unbox'
1531                             }
1532                         }
1533                         for (size_t i = ntargs; i < dedargs.dim; i++)
1534                         {
1535                             TemplateParameter tparam = (*parameters)[i];
1536 
1537                             RootObject oarg = (*dedargs)[i];
1538                             RootObject oded = (*dedtypes)[i];
1539                             if (!oarg)
1540                             {
1541                                 if (oded)
1542                                 {
1543                                     if (tparam.specialization() || !tparam.isTemplateTypeParameter())
1544                                     {
1545                                         /* The specialization can work as long as afterwards
1546                                          * the oded == oarg
1547                                          */
1548                                         (*dedargs)[i] = oded;
1549                                         MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
1550                                         //printf("m2 = %d\n", m2);
1551                                         if (m2 <= MATCHnomatch)
1552                                             goto Lnomatch;
1553                                         if (m2 < matchTiargs)
1554                                             matchTiargs = m2; // pick worst match
1555                                         if (!(*dedtypes)[i].equals(oded))
1556                                             error("specialization not allowed for deduced parameter %s", tparam.ident.toChars());
1557                                     }
1558                                     else
1559                                     {
1560                                         if (MATCHconvert < matchTiargs)
1561                                             matchTiargs = MATCHconvert;
1562                                     }
1563                                     (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
1564                                 }
1565                                 else
1566                                 {
1567                                     oded = tparam.defaultArg(instLoc, paramscope);
1568                                     if (oded)
1569                                         (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
1570                                 }
1571                             }
1572                         }
1573                     }
1574                     nfargs2 = argi + 1;
1575 
1576                     /* If prmtype does not depend on any template parameters:
1577                      *
1578                      *  auto foo(T)(T v, double x = 0);
1579                      *  foo("str");
1580                      *  // at fparam == 'double x = 0'
1581                      *
1582                      * or, if all template parameters in the prmtype are already deduced:
1583                      *
1584                      *  auto foo(R)(R range, ElementType!R sum = 0);
1585                      *  foo([1,2,3]);
1586                      *  // at fparam == 'ElementType!R sum = 0'
1587                      *
1588                      * Deducing prmtype from fparam.defaultArg is not necessary.
1589                      */
1590                     if (prmtype.deco || prmtype.syntaxCopy().trySemantic(loc, paramscope))
1591                     {
1592                         ++argi;
1593                         continue;
1594                     }
1595 
1596                     // Deduce prmtype from the defaultArg.
1597                     farg = fparam.defaultArg.syntaxCopy();
1598                     farg = farg.semantic(paramscope);
1599                     farg = resolveProperties(paramscope, farg);
1600                 }
1601                 else
1602                 {
1603                     farg = (*fargs)[argi];
1604                 }
1605                 {
1606                     // Check invalid arguments to detect errors early.
1607                     if (farg.op == TOKerror || farg.type.ty == Terror)
1608                         goto Lnomatch;
1609 
1610                     Type att = null;
1611                 Lretry:
1612                     version (none)
1613                     {
1614                         printf("\tfarg.type   = %s\n", farg.type.toChars());
1615                         printf("\tfparam.type = %s\n", prmtype.toChars());
1616                     }
1617                     Type argtype = farg.type;
1618 
1619                     if (!(fparam.storageClass & STClazy) && argtype.ty == Tvoid && farg.op != TOKfunction)
1620                         goto Lnomatch;
1621 
1622                     // https://issues.dlang.org/show_bug.cgi?id=12876
1623                     // Optimize argument to allow CT-known length matching
1624                     farg = farg.optimize(WANTvalue, (fparam.storageClass & (STCref | STCout)) != 0);
1625                     //printf("farg = %s %s\n", farg.type.toChars(), fargtoChars());
1626 
1627                     RootObject oarg = farg;
1628                     if ((fparam.storageClass & STCref) && (!(fparam.storageClass & STCauto) || farg.isLvalue()))
1629                     {
1630                         /* Allow expressions that have CT-known boundaries and type [] to match with [dim]
1631                          */
1632                         Type taai;
1633                         if (argtype.ty == Tarray && (prmtype.ty == Tsarray || prmtype.ty == Taarray && (taai = (cast(TypeAArray)prmtype).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
1634                         {
1635                             if (farg.op == TOKstring)
1636                             {
1637                                 StringExp se = cast(StringExp)farg;
1638                                 argtype = se.type.nextOf().sarrayOf(se.len);
1639                             }
1640                             else if (farg.op == TOKarrayliteral)
1641                             {
1642                                 ArrayLiteralExp ae = cast(ArrayLiteralExp)farg;
1643                                 argtype = ae.type.nextOf().sarrayOf(ae.elements.dim);
1644                             }
1645                             else if (farg.op == TOKslice)
1646                             {
1647                                 SliceExp se = cast(SliceExp)farg;
1648                                 if (Type tsa = toStaticArrayType(se))
1649                                     argtype = tsa;
1650                             }
1651                         }
1652 
1653                         oarg = argtype;
1654                     }
1655                     else if ((fparam.storageClass & STCout) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && (cast(TypeIdentifier)prmtype).idents.dim == 0)
1656                     {
1657                         /* The farg passing to the prmtype always make a copy. Therefore,
1658                          * we can shrink the set of the deduced type arguments for prmtype
1659                          * by adjusting top-qualifier of the argtype.
1660                          *
1661                          *  prmtype         argtype     ta
1662                          *  T            <- const(E)[]  const(E)[]
1663                          *  T            <- const(E[])  const(E)[]
1664                          *  qualifier(T) <- const(E)[]  const(E[])
1665                          *  qualifier(T) <- const(E[])  const(E[])
1666                          */
1667                         Type ta = argtype.castMod(prmtype.mod ? argtype.nextOf().mod : 0);
1668                         if (ta != argtype)
1669                         {
1670                             Expression ea = farg.copy();
1671                             ea.type = ta;
1672                             oarg = ea;
1673                         }
1674                     }
1675 
1676                     if (fvarargs == 2 && parami + 1 == nfparams && argi + 1 < nfargs)
1677                         goto Lvarargs;
1678 
1679                     uint wm = 0;
1680                     MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &wm, inferStart);
1681                     //printf("\tL%d deduceType m = %d, wm = x%x, wildmatch = x%x\n", __LINE__, m, wm, wildmatch);
1682                     wildmatch |= wm;
1683 
1684                     /* If no match, see if the argument can be matched by using
1685                      * implicit conversions.
1686                      */
1687                     if (m == MATCHnomatch && prmtype.deco)
1688                         m = farg.implicitConvTo(prmtype);
1689 
1690                     if (m == MATCHnomatch)
1691                     {
1692                         AggregateDeclaration ad = isAggregate(farg.type);
1693                         if (ad && ad.aliasthis && argtype != att)
1694                         {
1695                             if (!att && argtype.checkAliasThisRec())   // https://issues.dlang.org/show_bug.cgi?id=12537
1696                                 att = argtype;
1697                             /* If a semantic error occurs while doing alias this,
1698                              * eg purity(https://issues.dlang.org/show_bug.cgi?id=7295),
1699                              * just regard it as not a match.
1700                              */
1701                             if (auto e = resolveAliasThis(sc, farg, true))
1702                             {
1703                                 farg = e;
1704                                 goto Lretry;
1705                             }
1706                         }
1707                     }
1708 
1709                     if (m > MATCHnomatch && (fparam.storageClass & (STCref | STCauto)) == STCref)
1710                     {
1711                         if (!farg.isLvalue())
1712                         {
1713                             if ((farg.op == TOKstring || farg.op == TOKslice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
1714                             {
1715                                 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
1716                             }
1717                             else
1718                                 goto Lnomatch;
1719                         }
1720                     }
1721                     if (m > MATCHnomatch && (fparam.storageClass & STCout))
1722                     {
1723                         if (!farg.isLvalue())
1724                             goto Lnomatch;
1725                         if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
1726                             goto Lnomatch;
1727                     }
1728                     if (m == MATCHnomatch && (fparam.storageClass & STClazy) && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
1729                         m = MATCHconvert;
1730                     if (m != MATCHnomatch)
1731                     {
1732                         if (m < match)
1733                             match = m; // pick worst match
1734                         argi++;
1735                         continue;
1736                     }
1737                 }
1738 
1739             Lvarargs:
1740                 /* The following code for variadic arguments closely
1741                  * matches TypeFunction.callMatch()
1742                  */
1743                 if (!(fvarargs == 2 && parami + 1 == nfparams))
1744                     goto Lnomatch;
1745 
1746                 /* Check for match with function parameter T...
1747                  */
1748                 Type tb = prmtype.toBasetype();
1749                 switch (tb.ty)
1750                 {
1751                     // 6764 fix - TypeAArray may be TypeSArray have not yet run semantic().
1752                 case Tsarray:
1753                 case Taarray:
1754                     {
1755                         // Perhaps we can do better with this, see TypeFunction.callMatch()
1756                         if (tb.ty == Tsarray)
1757                         {
1758                             TypeSArray tsa = cast(TypeSArray)tb;
1759                             dinteger_t sz = tsa.dim.toInteger();
1760                             if (sz != nfargs - argi)
1761                                 goto Lnomatch;
1762                         }
1763                         else if (tb.ty == Taarray)
1764                         {
1765                             TypeAArray taa = cast(TypeAArray)tb;
1766                             Expression dim = new IntegerExp(instLoc, nfargs - argi, Type.tsize_t);
1767 
1768                             size_t i = templateParameterLookup(taa.index, parameters);
1769                             if (i == IDX_NOTFOUND)
1770                             {
1771                                 Expression e;
1772                                 Type t;
1773                                 Dsymbol s;
1774                                 taa.index.resolve(instLoc, sc, &e, &t, &s);
1775                                 if (!e)
1776                                     goto Lnomatch;
1777                                 e = e.ctfeInterpret();
1778                                 e = e.implicitCastTo(sc, Type.tsize_t);
1779                                 e = e.optimize(WANTvalue);
1780                                 if (!dim.equals(e))
1781                                     goto Lnomatch;
1782                             }
1783                             else
1784                             {
1785                                 // This code matches code in TypeInstance.deduceType()
1786                                 TemplateParameter tprm = (*parameters)[i];
1787                                 TemplateValueParameter tvp = tprm.isTemplateValueParameter();
1788                                 if (!tvp)
1789                                     goto Lnomatch;
1790                                 Expression e = cast(Expression)(*dedtypes)[i];
1791                                 if (e)
1792                                 {
1793                                     if (!dim.equals(e))
1794                                         goto Lnomatch;
1795                                 }
1796                                 else
1797                                 {
1798                                     Type vt = tvp.valType.semantic(Loc(), sc);
1799                                     MATCH m = dim.implicitConvTo(vt);
1800                                     if (m <= MATCHnomatch)
1801                                         goto Lnomatch;
1802                                     (*dedtypes)[i] = dim;
1803                                 }
1804                             }
1805                         }
1806                         goto case Tarray;
1807                     }
1808                 case Tarray:
1809                     {
1810                         TypeArray ta = cast(TypeArray)tb;
1811                         Type tret = fparam.isLazyArray();
1812                         for (; argi < nfargs; argi++)
1813                         {
1814                             Expression arg = (*fargs)[argi];
1815                             assert(arg);
1816 
1817                             MATCH m;
1818                             /* If lazy array of delegates,
1819                              * convert arg(s) to delegate(s)
1820                              */
1821                             if (tret)
1822                             {
1823                                 if (ta.next.equals(arg.type))
1824                                 {
1825                                     m = MATCHexact;
1826                                 }
1827                                 else
1828                                 {
1829                                     m = arg.implicitConvTo(tret);
1830                                     if (m == MATCHnomatch)
1831                                     {
1832                                         if (tret.toBasetype().ty == Tvoid)
1833                                             m = MATCHconvert;
1834                                     }
1835                                 }
1836                             }
1837                             else
1838                             {
1839                                 uint wm = 0;
1840                                 m = deduceType(arg, paramscope, ta.next, parameters, dedtypes, &wm, inferStart);
1841                                 wildmatch |= wm;
1842                             }
1843                             if (m == MATCHnomatch)
1844                                 goto Lnomatch;
1845                             if (m < match)
1846                                 match = m;
1847                         }
1848                         goto Lmatch;
1849                     }
1850                 case Tclass:
1851                 case Tident:
1852                     goto Lmatch;
1853 
1854                 default:
1855                     goto Lnomatch;
1856                 }
1857                 assert(0);
1858             }
1859             //printf(". argi = %d, nfargs = %d, nfargs2 = %d\n", argi, nfargs, nfargs2);
1860             if (argi != nfargs2 && !fvarargs)
1861                 goto Lnomatch;
1862         }
1863 
1864     Lmatch:
1865         for (size_t i = 0; i < dedtypes.dim; i++)
1866         {
1867             Type at = isType((*dedtypes)[i]);
1868             if (at)
1869             {
1870                 if (at.ty == Tnone)
1871                 {
1872                     TypeDeduced xt = cast(TypeDeduced)at;
1873                     at = xt.tded; // 'unbox'
1874                 }
1875                 (*dedtypes)[i] = at.merge2();
1876             }
1877         }
1878         for (size_t i = ntargs; i < dedargs.dim; i++)
1879         {
1880             TemplateParameter tparam = (*parameters)[i];
1881             //printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
1882 
1883             /* For T:T*, the dedargs is the T*, dedtypes is the T
1884              * But for function templates, we really need them to match
1885              */
1886             RootObject oarg = (*dedargs)[i];
1887             RootObject oded = (*dedtypes)[i];
1888             //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
1889             //if (oarg) printf("oarg: %s\n", oarg.toChars());
1890             //if (oded) printf("oded: %s\n", oded.toChars());
1891             if (!oarg)
1892             {
1893                 if (oded)
1894                 {
1895                     if (tparam.specialization() || !tparam.isTemplateTypeParameter())
1896                     {
1897                         /* The specialization can work as long as afterwards
1898                          * the oded == oarg
1899                          */
1900                         (*dedargs)[i] = oded;
1901                         MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
1902                         //printf("m2 = %d\n", m2);
1903                         if (m2 <= MATCHnomatch)
1904                             goto Lnomatch;
1905                         if (m2 < matchTiargs)
1906                             matchTiargs = m2; // pick worst match
1907                         if (!(*dedtypes)[i].equals(oded))
1908                             error("specialization not allowed for deduced parameter %s", tparam.ident.toChars());
1909                     }
1910                     else
1911                     {
1912                         if (MATCHconvert < matchTiargs)
1913                             matchTiargs = MATCHconvert;
1914                     }
1915                 }
1916                 else
1917                 {
1918                     oded = tparam.defaultArg(instLoc, paramscope);
1919                     if (!oded)
1920                     {
1921                         // if tuple parameter and
1922                         // tuple parameter was not in function parameter list and
1923                         // we're one or more arguments short (i.e. no tuple argument)
1924                         if (tparam == tp &&
1925                             fptupindex == IDX_NOTFOUND &&
1926                             ntargs <= dedargs.dim - 1)
1927                         {
1928                             // make tuple argument an empty tuple
1929                             oded = cast(RootObject)new Tuple();
1930                         }
1931                         else
1932                             goto Lnomatch;
1933                     }
1934                     if (isError(oded))
1935                         goto Lerror;
1936                     ntargs++;
1937 
1938                     /* At the template parameter T, the picked default template argument
1939                      * X!int should be matched to T in order to deduce dependent
1940                      * template parameter A.
1941                      *  auto foo(T : X!A = X!int, A...)() { ... }
1942                      *  foo();  // T <-- X!int, A <-- (int)
1943                      */
1944                     if (tparam.specialization())
1945                     {
1946                         (*dedargs)[i] = oded;
1947                         MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
1948                         //printf("m2 = %d\n", m2);
1949                         if (m2 <= MATCHnomatch)
1950                             goto Lnomatch;
1951                         if (m2 < matchTiargs)
1952                             matchTiargs = m2; // pick worst match
1953                         if (!(*dedtypes)[i].equals(oded))
1954                             error("specialization not allowed for deduced parameter %s", tparam.ident.toChars());
1955                     }
1956                 }
1957                 oded = declareParameter(paramscope, tparam, oded);
1958                 (*dedargs)[i] = oded;
1959             }
1960         }
1961 
1962         /* https://issues.dlang.org/show_bug.cgi?id=7469
1963          * As same as the code for 7469 in findBestMatch,
1964          * expand a Tuple in dedargs to normalize template arguments.
1965          */
1966         if (auto d = dedargs.dim)
1967         {
1968             if (auto va = isTuple((*dedargs)[d - 1]))
1969             {
1970                 dedargs.setDim(d - 1);
1971                 dedargs.insert(d - 1, &va.objects);
1972             }
1973         }
1974         ti.tiargs = dedargs; // update to the normalized template arguments.
1975 
1976         // Partially instantiate function for constraint and fd.leastAsSpecialized()
1977         {
1978             assert(paramsym);
1979             Scope* sc2 = _scope;
1980             sc2 = sc2.push(paramsym);
1981             sc2 = sc2.push(ti);
1982             sc2.parent = ti;
1983             sc2.tinst = ti;
1984             sc2.minst = sc.minst;
1985 
1986             fd = doHeaderInstantiation(ti, sc2, fd, tthis, fargs);
1987 
1988             sc2 = sc2.pop();
1989             sc2 = sc2.pop();
1990 
1991             if (!fd)
1992                 goto Lnomatch;
1993         }
1994 
1995         if (constraint)
1996         {
1997             if (!evaluateConstraint(ti, sc, paramscope, dedargs, fd))
1998                 goto Lnomatch;
1999         }
2000 
2001         version (none)
2002         {
2003             for (size_t i = 0; i < dedargs.dim; i++)
2004             {
2005                 RootObject o = (*dedargs)[i];
2006                 printf("\tdedargs[%d] = %d, %s\n", i, o.dyncast(), o.toChars());
2007             }
2008         }
2009 
2010         paramscope.pop();
2011         //printf("\tmatch %d\n", match);
2012         return cast(MATCH)(match | (matchTiargs << 4));
2013 
2014     Lnomatch:
2015         paramscope.pop();
2016         //printf("\tnomatch\n");
2017         return MATCHnomatch;
2018 
2019     Lerror:
2020         // todo: for the future improvement
2021         paramscope.pop();
2022         //printf("\terror\n");
2023         return MATCHnomatch;
2024     }
2025 
2026     /**************************************************
2027      * Declare template parameter tp with value o, and install it in the scope sc.
2028      */
2029     RootObject declareParameter(Scope* sc, TemplateParameter tp, RootObject o)
2030     {
2031         //printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o);
2032         Type ta = isType(o);
2033         Expression ea = isExpression(o);
2034         Dsymbol sa = isDsymbol(o);
2035         Tuple va = isTuple(o);
2036 
2037         Declaration d;
2038         VarDeclaration v = null;
2039 
2040         if (ea && ea.op == TOKtype)
2041             ta = ea.type;
2042         else if (ea && ea.op == TOKscope)
2043             sa = (cast(ScopeExp)ea).sds;
2044         else if (ea && (ea.op == TOKthis || ea.op == TOKsuper))
2045             sa = (cast(ThisExp)ea).var;
2046         else if (ea && ea.op == TOKfunction)
2047         {
2048             if ((cast(FuncExp)ea).td)
2049                 sa = (cast(FuncExp)ea).td;
2050             else
2051                 sa = (cast(FuncExp)ea).fd;
2052         }
2053 
2054         if (ta)
2055         {
2056             //printf("type %s\n", ta.toChars());
2057             d = new AliasDeclaration(Loc(), tp.ident, ta);
2058         }
2059         else if (sa)
2060         {
2061             //printf("Alias %s %s;\n", sa.ident.toChars(), tp.ident.toChars());
2062             d = new AliasDeclaration(Loc(), tp.ident, sa);
2063         }
2064         else if (ea)
2065         {
2066             // tdtypes.data[i] always matches ea here
2067             Initializer _init = new ExpInitializer(loc, ea);
2068             TemplateValueParameter tvp = tp.isTemplateValueParameter();
2069             Type t = tvp ? tvp.valType : null;
2070             v = new VarDeclaration(loc, t, tp.ident, _init);
2071             v.storage_class = STCmanifest | STCtemplateparameter;
2072             d = v;
2073         }
2074         else if (va)
2075         {
2076             //printf("\ttuple\n");
2077             d = new TupleDeclaration(loc, tp.ident, &va.objects);
2078         }
2079         else
2080         {
2081             debug
2082             {
2083                 o.print();
2084             }
2085             assert(0);
2086         }
2087         d.storage_class |= STCtemplateparameter;
2088 
2089         if (ta)
2090         {
2091             Type t = ta;
2092             // consistent with Type.checkDeprecated()
2093             while (t.ty != Tenum)
2094             {
2095                 if (!t.nextOf())
2096                     break;
2097                 t = (cast(TypeNext)t).next;
2098             }
2099             if (Dsymbol s = t.toDsymbol(sc))
2100             {
2101                 if (s.isDeprecated())
2102                     d.storage_class |= STCdeprecated;
2103             }
2104         }
2105         else if (sa)
2106         {
2107             if (sa.isDeprecated())
2108                 d.storage_class |= STCdeprecated;
2109         }
2110 
2111         if (!sc.insert(d))
2112             error("declaration %s is already defined", tp.ident.toChars());
2113         d.semantic(sc);
2114         /* So the caller's o gets updated with the result of semantic() being run on o
2115          */
2116         if (v)
2117             o = v._init.toExpression();
2118         return o;
2119     }
2120 
2121     /*************************************************
2122      * Limited function template instantiation for using fd.leastAsSpecialized()
2123      */
2124     FuncDeclaration doHeaderInstantiation(TemplateInstance ti, Scope* sc2, FuncDeclaration fd, Type tthis, Expressions* fargs)
2125     {
2126         assert(fd);
2127         version (none)
2128         {
2129             printf("doHeaderInstantiation this = %s\n", toChars());
2130         }
2131 
2132         // function body and contracts are not need
2133         if (fd.isCtorDeclaration())
2134             fd = new CtorDeclaration(fd.loc, fd.endloc, fd.storage_class, fd.type.syntaxCopy());
2135         else
2136             fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, fd.type.syntaxCopy());
2137         fd.parent = ti;
2138 
2139         assert(fd.type.ty == Tfunction);
2140         TypeFunction tf = cast(TypeFunction)fd.type;
2141         tf.fargs = fargs;
2142 
2143         if (tthis)
2144         {
2145             // Match 'tthis' to any TemplateThisParameter's
2146             bool hasttp = false;
2147             for (size_t i = 0; i < parameters.dim; i++)
2148             {
2149                 TemplateParameter tp = (*parameters)[i];
2150                 TemplateThisParameter ttp = tp.isTemplateThisParameter();
2151                 if (ttp)
2152                     hasttp = true;
2153             }
2154             if (hasttp)
2155             {
2156                 tf = cast(TypeFunction)tf.addSTC(ModToStc(tthis.mod));
2157                 assert(!tf.deco);
2158             }
2159         }
2160 
2161         Scope* scx = sc2.push();
2162 
2163         // Shouldn't run semantic on default arguments and return type.
2164         for (size_t i = 0; i < tf.parameters.dim; i++)
2165             (*tf.parameters)[i].defaultArg = null;
2166         if (fd.isCtorDeclaration())
2167         {
2168             // For constructors, emitting return type is necessary for
2169             // isolateReturn() in functionResolve.
2170             scx.flags |= SCOPEctor;
2171 
2172             Dsymbol parent = toParent2();
2173             Type tret;
2174             AggregateDeclaration ad = parent.isAggregateDeclaration();
2175             if (!ad || parent.isUnionDeclaration())
2176             {
2177                 tret = Type.tvoid;
2178             }
2179             else
2180             {
2181                 tret = ad.handleType();
2182                 assert(tret);
2183                 tret = tret.addStorageClass(fd.storage_class | scx.stc);
2184                 tret = tret.addMod(tf.mod);
2185             }
2186             tf.next = tret;
2187             if (ad && ad.isStructDeclaration())
2188                 tf.isref = 1;
2189             //printf("tf = %s\n", tf.toChars());
2190         }
2191         else
2192             tf.next = null;
2193         fd.type = tf;
2194         fd.type = fd.type.addSTC(scx.stc);
2195         fd.type = fd.type.semantic(fd.loc, scx);
2196         scx = scx.pop();
2197 
2198         if (fd.type.ty != Tfunction)
2199             return null;
2200 
2201         fd.originalType = fd.type; // for mangling
2202         //printf("\t[%s] fd.type = %s, mod = %x, ", loc.toChars(), fd.type.toChars(), fd.type.mod);
2203         //printf("fd.needThis() = %d\n", fd.needThis());
2204 
2205         return fd;
2206     }
2207 
2208     /****************************************************
2209      * Given a new instance tithis of this TemplateDeclaration,
2210      * see if there already exists an instance.
2211      * If so, return that existing instance.
2212      */
2213     TemplateInstance findExistingInstance(TemplateInstance tithis, Expressions* fargs)
2214     {
2215         //printf("findExistingInstance(%p)\n", tithis);
2216         tithis.fargs = fargs;
2217         auto tibox = TemplateInstanceBox(tithis);
2218         auto p = tibox in instances;
2219         //if (p) printf("\tfound %p\n", *p); else printf("\tnot found\n");
2220         return p ? *p : null;
2221     }
2222 
2223     /********************************************
2224      * Add instance ti to TemplateDeclaration's table of instances.
2225      * Return a handle we can use to later remove it if it fails instantiation.
2226      */
2227     TemplateInstance addInstance(TemplateInstance ti)
2228     {
2229         //printf("addInstance() %p %p\n", instances, ti);
2230         auto tibox = TemplateInstanceBox(ti);
2231         instances[tibox] = ti;
2232         return ti;
2233     }
2234 
2235     /*******************************************
2236      * Remove TemplateInstance from table of instances.
2237      * Input:
2238      *      handle returned by addInstance()
2239      */
2240     void removeInstance(TemplateInstance ti)
2241     {
2242         //printf("removeInstance()\n");
2243         auto tibox = TemplateInstanceBox(ti);
2244         instances.remove(tibox);
2245     }
2246 
2247     override inout(TemplateDeclaration) isTemplateDeclaration() inout
2248     {
2249         return this;
2250     }
2251 
2252     /**
2253      * Check if the last template parameter is a tuple one,
2254      * and returns it if so, else returns `null`.
2255      *
2256      * Returns:
2257      *   The last template parameter if it's a `TemplateTupleParameter`
2258      */
2259     TemplateTupleParameter isVariadic()
2260     {
2261         size_t dim = parameters.dim;
2262         if (dim == 0)
2263             return null;
2264         return (*parameters)[dim - 1].isTemplateTupleParameter();
2265     }
2266 
2267     /***********************************
2268      * We can overload templates.
2269      */
2270     override bool isOverloadable()
2271     {
2272         return true;
2273     }
2274 
2275     override void accept(Visitor v)
2276     {
2277         v.visit(this);
2278     }
2279 }
2280 
2281 extern (C++) final class TypeDeduced : Type
2282 {
2283     Type tded;
2284     Expressions argexps; // corresponding expressions
2285     Types tparams; // tparams[i].mod
2286 
2287     extern (D) this(Type tt, Expression e, Type tparam)
2288     {
2289         super(Tnone);
2290         tded = tt;
2291         argexps.push(e);
2292         tparams.push(tparam);
2293     }
2294 
2295     void update(Expression e, Type tparam)
2296     {
2297         argexps.push(e);
2298         tparams.push(tparam);
2299     }
2300 
2301     void update(Type tt, Expression e, Type tparam)
2302     {
2303         tded = tt;
2304         argexps.push(e);
2305         tparams.push(tparam);
2306     }
2307 
2308     MATCH matchAll(Type tt)
2309     {
2310         MATCH match = MATCHexact;
2311         for (size_t j = 0; j < argexps.dim; j++)
2312         {
2313             Expression e = argexps[j];
2314             assert(e);
2315             if (e == emptyArrayElement)
2316                 continue;
2317 
2318             Type t = tt.addMod(tparams[j].mod).substWildTo(MODconst);
2319 
2320             MATCH m = e.implicitConvTo(t);
2321             if (match > m)
2322                 match = m;
2323             if (match <= MATCHnomatch)
2324                 break;
2325         }
2326         return match;
2327     }
2328 }
2329 
2330 
2331 /*************************************************
2332  * Given function arguments, figure out which template function
2333  * to expand, and return matching result.
2334  * Input:
2335  *      m               matching result
2336  *      dstart          the root of overloaded function templates
2337  *      loc             instantiation location
2338  *      sc              instantiation scope
2339  *      tiargs          initial list of template arguments
2340  *      tthis           if !NULL, the 'this' pointer argument
2341  *      fargs           arguments to function
2342  */
2343 void functionResolve(Match* m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, Type tthis, Expressions* fargs)
2344 {
2345     version (none)
2346     {
2347         printf("functionResolve() dstart = %s\n", dstart.toChars());
2348         printf("    tiargs:\n");
2349         if (tiargs)
2350         {
2351             for (size_t i = 0; i < tiargs.dim; i++)
2352             {
2353                 RootObject arg = (*tiargs)[i];
2354                 printf("\t%s\n", arg.toChars());
2355             }
2356         }
2357         printf("    fargs:\n");
2358         for (size_t i = 0; i < (fargs ? fargs.dim : 0); i++)
2359         {
2360             Expression arg = (*fargs)[i];
2361             printf("\t%s %s\n", arg.type.toChars(), arg.toChars());
2362             //printf("\tty = %d\n", arg.type.ty);
2363         }
2364         //printf("stc = %llx\n", dstart.scope.stc);
2365         //printf("match:t/f = %d/%d\n", ta_last, m.last);
2366     }
2367 
2368     // results
2369     int property = 0;   // 0: unintialized
2370                         // 1: seen @property
2371                         // 2: not @property
2372     size_t ov_index = 0;
2373     TemplateDeclaration td_best;
2374     TemplateInstance ti_best;
2375     MATCH ta_last = m.last != MATCHnomatch ? MATCHexact : MATCHnomatch;
2376     Type tthis_best;
2377 
2378     int applyFunction(FuncDeclaration fd)
2379     {
2380         // skip duplicates
2381         if (fd == m.lastf)
2382             return 0;
2383         // explicitly specified tiargs never match to non template function
2384         if (tiargs && tiargs.dim > 0)
2385             return 0;
2386 
2387         if (fd.semanticRun == PASSinit && fd._scope)
2388         {
2389             Ungag ungag = fd.ungagSpeculative();
2390             fd.semantic(fd._scope);
2391         }
2392         if (fd.semanticRun == PASSinit)
2393         {
2394             .error(loc, "forward reference to template %s", fd.toChars());
2395             return 1;
2396         }
2397         //printf("fd = %s %s, fargs = %s\n", fd.toChars(), fd.type.toChars(), fargs.toChars());
2398         m.anyf = fd;
2399         auto tf = cast(TypeFunction)fd.type;
2400 
2401         int prop = tf.isproperty ? 1 : 2;
2402         if (property == 0)
2403             property = prop;
2404         else if (property != prop)
2405             error(fd.loc, "cannot overload both property and non-property functions");
2406 
2407         /* For constructors, qualifier check will be opposite direction.
2408          * Qualified constructor always makes qualified object, then will be checked
2409          * that it is implicitly convertible to tthis.
2410          */
2411         Type tthis_fd = fd.needThis() ? tthis : null;
2412         bool isCtorCall = tthis_fd && fd.isCtorDeclaration();
2413         if (isCtorCall)
2414         {
2415             //printf("%s tf.mod = x%x tthis_fd.mod = x%x %d\n", tf.toChars(),
2416             //        tf.mod, tthis_fd.mod, fd.isolateReturn());
2417             if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
2418                 tf.isWild() && tf.isShared() == tthis_fd.isShared() ||
2419                 fd.isolateReturn())
2420             {
2421                 /* && tf.isShared() == tthis_fd.isShared()*/
2422                 // Uniquely constructed object can ignore shared qualifier.
2423                 // TODO: Is this appropriate?
2424                 tthis_fd = null;
2425             }
2426             else
2427                 return 0;   // MATCHnomatch
2428         }
2429         MATCH mfa = tf.callMatch(tthis_fd, fargs);
2430         //printf("test1: mfa = %d\n", mfa);
2431         if (mfa > MATCHnomatch)
2432         {
2433             if (mfa > m.last) goto LfIsBetter;
2434             if (mfa < m.last) goto LlastIsBetter;
2435 
2436             /* See if one of the matches overrides the other.
2437              */
2438             assert(m.lastf);
2439             if (m.lastf.overrides(fd)) goto LlastIsBetter;
2440             if (fd.overrides(m.lastf)) goto LfIsBetter;
2441 
2442             /* Try to disambiguate using template-style partial ordering rules.
2443              * In essence, if f() and g() are ambiguous, if f() can call g(),
2444              * but g() cannot call f(), then pick f().
2445              * This is because f() is "more specialized."
2446              */
2447             {
2448                 MATCH c1 = fd.leastAsSpecialized(m.lastf);
2449                 MATCH c2 = m.lastf.leastAsSpecialized(fd);
2450                 //printf("c1 = %d, c2 = %d\n", c1, c2);
2451                 if (c1 > c2) goto LfIsBetter;
2452                 if (c1 < c2) goto LlastIsBetter;
2453             }
2454 
2455             /* If the two functions are the same function, like:
2456              *    int foo(int);
2457              *    int foo(int x) { ... }
2458              * then pick the one with the body.
2459              */
2460             if (tf.equals(m.lastf.type) &&
2461                 fd.storage_class == m.lastf.storage_class &&
2462                 fd.parent == m.lastf.parent &&
2463                 fd.protection == m.lastf.protection &&
2464                 fd.linkage == m.lastf.linkage)
2465             {
2466                 if (fd.fbody && !m.lastf.fbody) goto LfIsBetter;
2467                 if (!fd.fbody && m.lastf.fbody) goto LlastIsBetter;
2468             }
2469 
2470             // Bugzilla 14450: Prefer exact qualified constructor for the creating object type
2471             if (isCtorCall && tf.mod != m.lastf.type.mod)
2472             {
2473                 if (tthis.mod == tf.mod) goto LfIsBetter;
2474                 if (tthis.mod == m.lastf.type.mod) goto LlastIsBetter;
2475             }
2476 
2477             m.nextf = fd;
2478             m.count++;
2479             return 0;
2480 
2481         LlastIsBetter:
2482             return 0;
2483 
2484         LfIsBetter:
2485             td_best = null;
2486             ti_best = null;
2487             ta_last = MATCHexact;
2488             m.last = mfa;
2489             m.lastf = fd;
2490             tthis_best = tthis_fd;
2491             ov_index = 0;
2492             m.count = 1;
2493             return 0;
2494         }
2495         return 0;
2496     }
2497 
2498     int applyTemplate(TemplateDeclaration td)
2499     {
2500         // skip duplicates
2501         if (td == td_best)
2502             return 0;
2503 
2504         if (!sc)
2505             sc = td._scope; // workaround for Type.aliasthisOf
2506 
2507         if (td.semanticRun == PASSinit && td._scope)
2508         {
2509             // Try to fix forward reference. Ungag errors while doing so.
2510             Ungag ungag = td.ungagSpeculative();
2511             td.semantic(td._scope);
2512         }
2513         if (td.semanticRun == PASSinit)
2514         {
2515             .error(loc, "forward reference to template %s", td.toChars());
2516         Lerror:
2517             m.lastf = null;
2518             m.count = 0;
2519             m.last = MATCHnomatch;
2520             return 1;
2521         }
2522         //printf("td = %s\n", td.toChars());
2523 
2524         auto f = td.onemember ? td.onemember.isFuncDeclaration() : null;
2525         if (!f)
2526         {
2527             if (!tiargs)
2528                 tiargs = new Objects();
2529             auto ti = new TemplateInstance(loc, td, tiargs);
2530             Objects dedtypes;
2531             dedtypes.setDim(td.parameters.dim);
2532             assert(td.semanticRun != PASSinit);
2533             MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0);
2534             //printf("matchWithInstance = %d\n", mta);
2535             if (mta <= MATCHnomatch || mta < ta_last)   // no match or less match
2536                 return 0;
2537 
2538             ti.semantic(sc, fargs);
2539             if (!ti.inst)               // if template failed to expand
2540                 return 0;
2541 
2542             Dsymbol s = ti.inst.toAlias();
2543             FuncDeclaration fd;
2544             if (auto tdx = s.isTemplateDeclaration())
2545             {
2546                 Objects dedtypesX;      // empty tiargs
2547 
2548                 // https://issues.dlang.org/show_bug.cgi?id=11553
2549                 // Check for recursive instantiation of tdx.
2550                 for (TemplatePrevious* p = tdx.previous; p; p = p.prev)
2551                 {
2552                     if (arrayObjectMatch(p.dedargs, &dedtypesX))
2553                     {
2554                         //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
2555                         /* It must be a subscope of p.sc, other scope chains are not recursive
2556                          * instantiations.
2557                          */
2558                         for (Scope* scx = sc; scx; scx = scx.enclosing)
2559                         {
2560                             if (scx == p.sc)
2561                             {
2562                                 error(loc, "recursive template expansion while looking for %s.%s", ti.toChars(), tdx.toChars());
2563                                 goto Lerror;
2564                             }
2565                         }
2566                     }
2567                     /* BUG: should also check for ref param differences
2568                      */
2569                 }
2570 
2571                 TemplatePrevious pr;
2572                 pr.prev = tdx.previous;
2573                 pr.sc = sc;
2574                 pr.dedargs = &dedtypesX;
2575                 tdx.previous = &pr;             // add this to threaded list
2576 
2577                 fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, 1);
2578 
2579                 tdx.previous = pr.prev;         // unlink from threaded list
2580             }
2581             else if (s.isFuncDeclaration())
2582             {
2583                 fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, 1);
2584             }
2585             else
2586                 goto Lerror;
2587 
2588             if (!fd)
2589                 return 0;
2590 
2591             if (fd.type.ty != Tfunction)
2592             {
2593                 m.lastf = fd;   // to propagate "error match"
2594                 m.count = 1;
2595                 m.last = MATCHnomatch;
2596                 return 1;
2597             }
2598 
2599             Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null;
2600 
2601             auto tf = cast(TypeFunction)fd.type;
2602             MATCH mfa = tf.callMatch(tthis_fd, fargs);
2603             if (mfa < m.last)
2604                 return 0;
2605 
2606             if (mta < ta_last) goto Ltd_best2;
2607             if (mta > ta_last) goto Ltd2;
2608 
2609             if (mfa < m.last) goto Ltd_best2;
2610             if (mfa > m.last) goto Ltd2;
2611 
2612         Lambig2:    // td_best and td are ambiguous
2613             //printf("Lambig2\n");
2614             m.nextf = fd;
2615             m.count++;
2616             return 0;
2617 
2618         Ltd_best2:
2619             return 0;
2620 
2621         Ltd2:
2622             // td is the new best match
2623             assert(td._scope);
2624             td_best = td;
2625             ti_best = null;
2626             property = 0;   // (backward compatibility)
2627             ta_last = mta;
2628             m.last = mfa;
2629             m.lastf = fd;
2630             tthis_best = tthis_fd;
2631             ov_index = 0;
2632             m.nextf = null;
2633             m.count = 1;
2634             return 0;
2635         }
2636 
2637         //printf("td = %s\n", td.toChars());
2638         for (size_t ovi = 0; f; f = f.overnext0, ovi++)
2639         {
2640             if (f.type.ty != Tfunction || f.errors)
2641                 goto Lerror;
2642 
2643             /* This is a 'dummy' instance to evaluate constraint properly.
2644              */
2645             auto ti = new TemplateInstance(loc, td, tiargs);
2646             ti.parent = td.parent;  // Maybe calculating valid 'enclosing' is unnecessary.
2647 
2648             auto fd = f;
2649             int x = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, fargs);
2650             MATCH mta = cast(MATCH)(x >> 4);
2651             MATCH mfa = cast(MATCH)(x & 0xF);
2652             //printf("match:t/f = %d/%d\n", mta, mfa);
2653             if (!fd || mfa == MATCHnomatch)
2654                 continue;
2655 
2656             Type tthis_fd = fd.needThis() ? tthis : null;
2657 
2658             bool isCtorCall = tthis_fd && fd.isCtorDeclaration();
2659             if (isCtorCall)
2660             {
2661                 // Constructor call requires additional check.
2662 
2663                 auto tf = cast(TypeFunction)fd.type;
2664                 assert(tf.next);
2665                 if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
2666                     tf.isWild() && tf.isShared() == tthis_fd.isShared() ||
2667                     fd.isolateReturn())
2668                 {
2669                     tthis_fd = null;
2670                 }
2671                 else
2672                     continue;   // MATCHnomatch
2673             }
2674 
2675             if (mta < ta_last) goto Ltd_best;
2676             if (mta > ta_last) goto Ltd;
2677 
2678             if (mfa < m.last) goto Ltd_best;
2679             if (mfa > m.last) goto Ltd;
2680 
2681             if (td_best)
2682             {
2683                 // Disambiguate by picking the most specialized TemplateDeclaration
2684                 MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs);
2685                 MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs);
2686                 //printf("1: c1 = %d, c2 = %d\n", c1, c2);
2687                 if (c1 > c2) goto Ltd;
2688                 if (c1 < c2) goto Ltd_best;
2689             }
2690             assert(fd && m.lastf);
2691             {
2692                 // Disambiguate by tf.callMatch
2693                 auto tf1 = cast(TypeFunction)fd.type;
2694                 assert(tf1.ty == Tfunction);
2695                 auto tf2 = cast(TypeFunction)m.lastf.type;
2696                 assert(tf2.ty == Tfunction);
2697                 MATCH c1 = tf1.callMatch(tthis_fd, fargs);
2698                 MATCH c2 = tf2.callMatch(tthis_best, fargs);
2699                 //printf("2: c1 = %d, c2 = %d\n", c1, c2);
2700                 if (c1 > c2) goto Ltd;
2701                 if (c1 < c2) goto Ltd_best;
2702             }
2703             {
2704                 // Disambiguate by picking the most specialized FunctionDeclaration
2705                 MATCH c1 = fd.leastAsSpecialized(m.lastf);
2706                 MATCH c2 = m.lastf.leastAsSpecialized(fd);
2707                 //printf("3: c1 = %d, c2 = %d\n", c1, c2);
2708                 if (c1 > c2) goto Ltd;
2709                 if (c1 < c2) goto Ltd_best;
2710             }
2711 
2712             // Bugzilla 14450: Prefer exact qualified constructor for the creating object type
2713             if (isCtorCall && fd.type.mod != m.lastf.type.mod)
2714             {
2715                 if (tthis.mod == fd.type.mod) goto Ltd;
2716                 if (tthis.mod == m.lastf.type.mod) goto Ltd_best;
2717             }
2718 
2719             m.nextf = fd;
2720             m.count++;
2721             continue;
2722 
2723         Ltd_best:           // td_best is the best match so far
2724             //printf("Ltd_best\n");
2725             continue;
2726 
2727         Ltd:                // td is the new best match
2728             //printf("Ltd\n");
2729             assert(td._scope);
2730             td_best = td;
2731             ti_best = ti;
2732             property = 0;   // (backward compatibility)
2733             ta_last = mta;
2734             m.last = mfa;
2735             m.lastf = fd;
2736             tthis_best = tthis_fd;
2737             ov_index = ovi;
2738             m.nextf = null;
2739             m.count = 1;
2740             continue;
2741         }
2742         return 0;
2743     }
2744 
2745     auto td = dstart.isTemplateDeclaration();
2746     if (td && td.funcroot)
2747         dstart = td.funcroot;
2748     overloadApply(dstart, (Dsymbol s)
2749     {
2750         if (s.errors)
2751             return 0;
2752         if (auto fd = s.isFuncDeclaration())
2753             return applyFunction(fd);
2754         if (auto td = s.isTemplateDeclaration())
2755             return applyTemplate(td);
2756         return 0;
2757     });
2758 
2759     //printf("td_best = %p, m.lastf = %p\n", td_best, m.lastf);
2760     if (td_best && ti_best && m.count == 1)
2761     {
2762         // Matches to template function
2763         assert(td_best.onemember && td_best.onemember.isFuncDeclaration());
2764         /* The best match is td_best with arguments tdargs.
2765          * Now instantiate the template.
2766          */
2767         assert(td_best._scope);
2768         if (!sc)
2769             sc = td_best._scope; // workaround for Type.aliasthisOf
2770 
2771         auto ti = new TemplateInstance(loc, td_best, ti_best.tiargs);
2772         ti.semantic(sc, fargs);
2773 
2774         m.lastf = ti.toAlias().isFuncDeclaration();
2775         if (!m.lastf)
2776             goto Lnomatch;
2777         if (ti.errors)
2778         {
2779         Lerror:
2780             m.count = 1;
2781             assert(m.lastf);
2782             m.last = MATCHnomatch;
2783             return;
2784         }
2785 
2786         // look forward instantiated overload function
2787         // Dsymbol.oneMembers is alredy called in TemplateInstance.semantic.
2788         // it has filled overnext0d
2789         while (ov_index--)
2790         {
2791             m.lastf = m.lastf.overnext0;
2792             assert(m.lastf);
2793         }
2794 
2795         tthis_best = m.lastf.needThis() && !m.lastf.isCtorDeclaration() ? tthis : null;
2796 
2797         auto tf = cast(TypeFunction)m.lastf.type;
2798         if (tf.ty == Terror)
2799             goto Lerror;
2800         assert(tf.ty == Tfunction);
2801         if (!tf.callMatch(tthis_best, fargs))
2802             goto Lnomatch;
2803 
2804         /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows,
2805          * a template instance can be matched while instantiating
2806          * that same template. Thus, the function type can be incomplete. Complete it.
2807          *
2808          * https://issues.dlang.org/show_bug.cgi?id=9208
2809          * For auto function, completion should be deferred to the end of
2810          * its semantic3. Should not complete it in here.
2811          */
2812         if (tf.next && !m.lastf.inferRetType)
2813         {
2814             m.lastf.type = tf.semantic(loc, sc);
2815         }
2816     }
2817     else if (m.lastf)
2818     {
2819         // Matches to non template function,
2820         // or found matches were ambiguous.
2821         assert(m.count >= 1);
2822     }
2823     else
2824     {
2825     Lnomatch:
2826         m.count = 0;
2827         m.lastf = null;
2828         m.last = MATCHnomatch;
2829     }
2830 }
2831 
2832 /* ======================== Type ============================================ */
2833 
2834 /****
2835  * Given an identifier, figure out which TemplateParameter it is.
2836  * Return IDX_NOTFOUND if not found.
2837  */
2838 private size_t templateIdentifierLookup(Identifier id, TemplateParameters* parameters)
2839 {
2840     for (size_t i = 0; i < parameters.dim; i++)
2841     {
2842         TemplateParameter tp = (*parameters)[i];
2843         if (tp.ident.equals(id))
2844             return i;
2845     }
2846     return IDX_NOTFOUND;
2847 }
2848 
2849 private size_t templateParameterLookup(Type tparam, TemplateParameters* parameters)
2850 {
2851     if (tparam.ty == Tident)
2852     {
2853         TypeIdentifier tident = cast(TypeIdentifier)tparam;
2854         //printf("\ttident = '%s'\n", tident.toChars());
2855         return templateIdentifierLookup(tident.ident, parameters);
2856     }
2857     return IDX_NOTFOUND;
2858 }
2859 
2860 private ubyte deduceWildHelper(Type t, Type* at, Type tparam)
2861 {
2862     if ((tparam.mod & MODwild) == 0)
2863         return 0;
2864 
2865     *at = null;
2866 
2867     auto X(T, U)(T U, U T)
2868     {
2869         return (U << 4) | T;
2870     }
2871 
2872     switch (X(tparam.mod, t.mod))
2873     {
2874     case X(MODwild, 0):
2875     case X(MODwild, MODconst):
2876     case X(MODwild, MODshared):
2877     case X(MODwild, MODshared | MODconst):
2878     case X(MODwild, MODimmutable):
2879     case X(MODwildconst, 0):
2880     case X(MODwildconst, MODconst):
2881     case X(MODwildconst, MODshared):
2882     case X(MODwildconst, MODshared | MODconst):
2883     case X(MODwildconst, MODimmutable):
2884     case X(MODshared | MODwild, MODshared):
2885     case X(MODshared | MODwild, MODshared | MODconst):
2886     case X(MODshared | MODwild, MODimmutable):
2887     case X(MODshared | MODwildconst, MODshared):
2888     case X(MODshared | MODwildconst, MODshared | MODconst):
2889     case X(MODshared | MODwildconst, MODimmutable):
2890         {
2891             ubyte wm = (t.mod & ~MODshared);
2892             if (wm == 0)
2893                 wm = MODmutable;
2894             ubyte m = (t.mod & (MODconst | MODimmutable)) | (tparam.mod & t.mod & MODshared);
2895             *at = t.unqualify(m);
2896             return wm;
2897         }
2898     case X(MODwild, MODwild):
2899     case X(MODwild, MODwildconst):
2900     case X(MODwild, MODshared | MODwild):
2901     case X(MODwild, MODshared | MODwildconst):
2902     case X(MODwildconst, MODwild):
2903     case X(MODwildconst, MODwildconst):
2904     case X(MODwildconst, MODshared | MODwild):
2905     case X(MODwildconst, MODshared | MODwildconst):
2906     case X(MODshared | MODwild, MODshared | MODwild):
2907     case X(MODshared | MODwild, MODshared | MODwildconst):
2908     case X(MODshared | MODwildconst, MODshared | MODwild):
2909     case X(MODshared | MODwildconst, MODshared | MODwildconst):
2910         {
2911             *at = t.unqualify(tparam.mod & t.mod);
2912             return MODwild;
2913         }
2914     default:
2915         return 0;
2916     }
2917 }
2918 
2919 private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
2920 {
2921     // 9*9 == 81 cases
2922 
2923     auto X(T, U)(T U, U T)
2924     {
2925         return (U << 4) | T;
2926     }
2927 
2928     switch (X(tparam.mod, t.mod))
2929     {
2930     case X(0, 0):
2931     case X(0, MODconst):
2932     case X(0, MODwild):
2933     case X(0, MODwildconst):
2934     case X(0, MODshared):
2935     case X(0, MODshared | MODconst):
2936     case X(0, MODshared | MODwild):
2937     case X(0, MODshared | MODwildconst):
2938     case X(0, MODimmutable):
2939         // foo(U)                       T                       => T
2940         // foo(U)                       const(T)                => const(T)
2941         // foo(U)                       inout(T)                => inout(T)
2942         // foo(U)                       inout(const(T))         => inout(const(T))
2943         // foo(U)                       shared(T)               => shared(T)
2944         // foo(U)                       shared(const(T))        => shared(const(T))
2945         // foo(U)                       shared(inout(T))        => shared(inout(T))
2946         // foo(U)                       shared(inout(const(T))) => shared(inout(const(T)))
2947         // foo(U)                       immutable(T)            => immutable(T)
2948         {
2949             *at = t;
2950             return MATCHexact;
2951         }
2952     case X(MODconst, MODconst):
2953     case X(MODwild, MODwild):
2954     case X(MODwildconst, MODwildconst):
2955     case X(MODshared, MODshared):
2956     case X(MODshared | MODconst, MODshared | MODconst):
2957     case X(MODshared | MODwild, MODshared | MODwild):
2958     case X(MODshared | MODwildconst, MODshared | MODwildconst):
2959     case X(MODimmutable, MODimmutable):
2960         // foo(const(U))                const(T)                => T
2961         // foo(inout(U))                inout(T)                => T
2962         // foo(inout(const(U)))         inout(const(T))         => T
2963         // foo(shared(U))               shared(T)               => T
2964         // foo(shared(const(U)))        shared(const(T))        => T
2965         // foo(shared(inout(U)))        shared(inout(T))        => T
2966         // foo(shared(inout(const(U)))) shared(inout(const(T))) => T
2967         // foo(immutable(U))            immutable(T)            => T
2968         {
2969             *at = t.mutableOf().unSharedOf();
2970             return MATCHexact;
2971         }
2972     case X(MODconst, 0):
2973     case X(MODconst, MODwild):
2974     case X(MODconst, MODwildconst):
2975     case X(MODconst, MODshared | MODconst):
2976     case X(MODconst, MODshared | MODwild):
2977     case X(MODconst, MODshared | MODwildconst):
2978     case X(MODconst, MODimmutable):
2979     case X(MODwild, MODshared | MODwild):
2980     case X(MODwildconst, MODshared | MODwildconst):
2981     case X(MODshared | MODconst, MODimmutable):
2982         // foo(const(U))                T                       => T
2983         // foo(const(U))                inout(T)                => T
2984         // foo(const(U))                inout(const(T))         => T
2985         // foo(const(U))                shared(const(T))        => shared(T)
2986         // foo(const(U))                shared(inout(T))        => shared(T)
2987         // foo(const(U))                shared(inout(const(T))) => shared(T)
2988         // foo(const(U))                immutable(T)            => T
2989         // foo(inout(U))                shared(inout(T))        => shared(T)
2990         // foo(inout(const(U)))         shared(inout(const(T))) => shared(T)
2991         // foo(shared(const(U)))        immutable(T)            => T
2992         {
2993             *at = t.mutableOf();
2994             return MATCHconst;
2995         }
2996     case X(MODconst, MODshared):
2997         // foo(const(U))                shared(T)               => shared(T)
2998         {
2999             *at = t;
3000             return MATCHconst;
3001         }
3002     case X(MODshared, MODshared | MODconst):
3003     case X(MODshared, MODshared | MODwild):
3004     case X(MODshared, MODshared | MODwildconst):
3005     case X(MODshared | MODconst, MODshared):
3006         // foo(shared(U))               shared(const(T))        => const(T)
3007         // foo(shared(U))               shared(inout(T))        => inout(T)
3008         // foo(shared(U))               shared(inout(const(T))) => inout(const(T))
3009         // foo(shared(const(U)))        shared(T)               => T
3010         {
3011             *at = t.unSharedOf();
3012             return MATCHconst;
3013         }
3014     case X(MODwildconst, MODimmutable):
3015     case X(MODshared | MODconst, MODshared | MODwildconst):
3016     case X(MODshared | MODwildconst, MODimmutable):
3017     case X(MODshared | MODwildconst, MODshared | MODwild):
3018         // foo(inout(const(U)))         immutable(T)            => T
3019         // foo(shared(const(U)))        shared(inout(const(T))) => T
3020         // foo(shared(inout(const(U)))) immutable(T)            => T
3021         // foo(shared(inout(const(U)))) shared(inout(T))        => T
3022         {
3023             *at = t.unSharedOf().mutableOf();
3024             return MATCHconst;
3025         }
3026     case X(MODshared | MODconst, MODshared | MODwild):
3027         // foo(shared(const(U)))        shared(inout(T))        => T
3028         {
3029             *at = t.unSharedOf().mutableOf();
3030             return MATCHconst;
3031         }
3032     case X(MODwild, 0):
3033     case X(MODwild, MODconst):
3034     case X(MODwild, MODwildconst):
3035     case X(MODwild, MODimmutable):
3036     case X(MODwild, MODshared):
3037     case X(MODwild, MODshared | MODconst):
3038     case X(MODwild, MODshared | MODwildconst):
3039     case X(MODwildconst, 0):
3040     case X(MODwildconst, MODconst):
3041     case X(MODwildconst, MODwild):
3042     case X(MODwildconst, MODshared):
3043     case X(MODwildconst, MODshared | MODconst):
3044     case X(MODwildconst, MODshared | MODwild):
3045     case X(MODshared, 0):
3046     case X(MODshared, MODconst):
3047     case X(MODshared, MODwild):
3048     case X(MODshared, MODwildconst):
3049     case X(MODshared, MODimmutable):
3050     case X(MODshared | MODconst, 0):
3051     case X(MODshared | MODconst, MODconst):
3052     case X(MODshared | MODconst, MODwild):
3053     case X(MODshared | MODconst, MODwildconst):
3054     case X(MODshared | MODwild, 0):
3055     case X(MODshared | MODwild, MODconst):
3056     case X(MODshared | MODwild, MODwild):
3057     case X(MODshared | MODwild, MODwildconst):
3058     case X(MODshared | MODwild, MODimmutable):
3059     case X(MODshared | MODwild, MODshared):
3060     case X(MODshared | MODwild, MODshared | MODconst):
3061     case X(MODshared | MODwild, MODshared | MODwildconst):
3062     case X(MODshared | MODwildconst, 0):
3063     case X(MODshared | MODwildconst, MODconst):
3064     case X(MODshared | MODwildconst, MODwild):
3065     case X(MODshared | MODwildconst, MODwildconst):
3066     case X(MODshared | MODwildconst, MODshared):
3067     case X(MODshared | MODwildconst, MODshared | MODconst):
3068     case X(MODimmutable, 0):
3069     case X(MODimmutable, MODconst):
3070     case X(MODimmutable, MODwild):
3071     case X(MODimmutable, MODwildconst):
3072     case X(MODimmutable, MODshared):
3073     case X(MODimmutable, MODshared | MODconst):
3074     case X(MODimmutable, MODshared | MODwild):
3075     case X(MODimmutable, MODshared | MODwildconst):
3076         // foo(inout(U))                T                       => nomatch
3077         // foo(inout(U))                const(T)                => nomatch
3078         // foo(inout(U))                inout(const(T))         => nomatch
3079         // foo(inout(U))                immutable(T)            => nomatch
3080         // foo(inout(U))                shared(T)               => nomatch
3081         // foo(inout(U))                shared(const(T))        => nomatch
3082         // foo(inout(U))                shared(inout(const(T))) => nomatch
3083         // foo(inout(const(U)))         T                       => nomatch
3084         // foo(inout(const(U)))         const(T)                => nomatch
3085         // foo(inout(const(U)))         inout(T)                => nomatch
3086         // foo(inout(const(U)))         shared(T)               => nomatch
3087         // foo(inout(const(U)))         shared(const(T))        => nomatch
3088         // foo(inout(const(U)))         shared(inout(T))        => nomatch
3089         // foo(shared(U))               T                       => nomatch
3090         // foo(shared(U))               const(T)                => nomatch
3091         // foo(shared(U))               inout(T)                => nomatch
3092         // foo(shared(U))               inout(const(T))         => nomatch
3093         // foo(shared(U))               immutable(T)            => nomatch
3094         // foo(shared(const(U)))        T                       => nomatch
3095         // foo(shared(const(U)))        const(T)                => nomatch
3096         // foo(shared(const(U)))        inout(T)                => nomatch
3097         // foo(shared(const(U)))        inout(const(T))         => nomatch
3098         // foo(shared(inout(U)))        T                       => nomatch
3099         // foo(shared(inout(U)))        const(T)                => nomatch
3100         // foo(shared(inout(U)))        inout(T)                => nomatch
3101         // foo(shared(inout(U)))        inout(const(T))         => nomatch
3102         // foo(shared(inout(U)))        immutable(T)            => nomatch
3103         // foo(shared(inout(U)))        shared(T)               => nomatch
3104         // foo(shared(inout(U)))        shared(const(T))        => nomatch
3105         // foo(shared(inout(U)))        shared(inout(const(T))) => nomatch
3106         // foo(shared(inout(const(U)))) T                       => nomatch
3107         // foo(shared(inout(const(U)))) const(T)                => nomatch
3108         // foo(shared(inout(const(U)))) inout(T)                => nomatch
3109         // foo(shared(inout(const(U)))) inout(const(T))         => nomatch
3110         // foo(shared(inout(const(U)))) shared(T)               => nomatch
3111         // foo(shared(inout(const(U)))) shared(const(T))        => nomatch
3112         // foo(immutable(U))            T                       => nomatch
3113         // foo(immutable(U))            const(T)                => nomatch
3114         // foo(immutable(U))            inout(T)                => nomatch
3115         // foo(immutable(U))            inout(const(T))         => nomatch
3116         // foo(immutable(U))            shared(T)               => nomatch
3117         // foo(immutable(U))            shared(const(T))        => nomatch
3118         // foo(immutable(U))            shared(inout(T))        => nomatch
3119         // foo(immutable(U))            shared(inout(const(T))) => nomatch
3120         return MATCHnomatch;
3121 
3122     default:
3123         assert(0);
3124     }
3125 }
3126 
3127 __gshared Expression emptyArrayElement = null;
3128 
3129 /* These form the heart of template argument deduction.
3130  * Given 'this' being the type argument to the template instance,
3131  * it is matched against the template declaration parameter specialization
3132  * 'tparam' to determine the type to be used for the parameter.
3133  * Example:
3134  *      template Foo(T:T*)      // template declaration
3135  *      Foo!(int*)              // template instantiation
3136  * Input:
3137  *      this = int*
3138  *      tparam = T*
3139  *      parameters = [ T:T* ]   // Array of TemplateParameter's
3140  * Output:
3141  *      dedtypes = [ int ]      // Array of Expression/Type's
3142  */
3143 MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm = null, size_t inferStart = 0)
3144 {
3145     extern (C++) final class DeduceType : Visitor
3146     {
3147         alias visit = super.visit;
3148     public:
3149         Scope* sc;
3150         Type tparam;
3151         TemplateParameters* parameters;
3152         Objects* dedtypes;
3153         uint* wm;
3154         size_t inferStart;
3155         MATCH result;
3156 
3157         extern (D) this(Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm, size_t inferStart)
3158         {
3159             this.sc = sc;
3160             this.tparam = tparam;
3161             this.parameters = parameters;
3162             this.dedtypes = dedtypes;
3163             this.wm = wm;
3164             this.inferStart = inferStart;
3165             result = MATCHnomatch;
3166         }
3167 
3168         override void visit(Type t)
3169         {
3170             version (none)
3171             {
3172                 printf("Type.deduceType()\n");
3173                 printf("\tthis   = %d, ", t.ty);
3174                 t.print();
3175                 printf("\ttparam = %d, ", tparam.ty);
3176                 tparam.print();
3177             }
3178             if (!tparam)
3179                 goto Lnomatch;
3180 
3181             if (t == tparam)
3182                 goto Lexact;
3183 
3184             if (tparam.ty == Tident)
3185             {
3186                 // Determine which parameter tparam is
3187                 size_t i = templateParameterLookup(tparam, parameters);
3188                 if (i == IDX_NOTFOUND)
3189                 {
3190                     if (!sc)
3191                         goto Lnomatch;
3192 
3193                     /* Need a loc to go with the semantic routine.
3194                      */
3195                     Loc loc;
3196                     if (parameters.dim)
3197                     {
3198                         TemplateParameter tp = (*parameters)[0];
3199                         loc = tp.loc;
3200                     }
3201 
3202                     /* BUG: what if tparam is a template instance, that
3203                      * has as an argument another Tident?
3204                      */
3205                     tparam = tparam.semantic(loc, sc);
3206                     assert(tparam.ty != Tident);
3207                     result = deduceType(t, sc, tparam, parameters, dedtypes, wm);
3208                     return;
3209                 }
3210 
3211                 TemplateParameter tp = (*parameters)[i];
3212 
3213                 TypeIdentifier tident = cast(TypeIdentifier)tparam;
3214                 if (tident.idents.dim > 0)
3215                 {
3216                     //printf("matching %s to %s\n", tparam.toChars(), t.toChars());
3217                     Dsymbol s = t.toDsymbol(sc);
3218                     for (size_t j = tident.idents.dim; j-- > 0;)
3219                     {
3220                         RootObject id = tident.idents[j];
3221                         if (id.dyncast() == DYNCAST_IDENTIFIER)
3222                         {
3223                             if (!s || !s.parent)
3224                                 goto Lnomatch;
3225                             Dsymbol s2 = s.parent.search(Loc(), cast(Identifier)id);
3226                             if (!s2)
3227                                 goto Lnomatch;
3228                             s2 = s2.toAlias();
3229                             //printf("[%d] s = %s %s, s2 = %s %s\n", j, s.kind(), s.toChars(), s2.kind(), s2.toChars());
3230                             if (s != s2)
3231                             {
3232                                 if (Type tx = s2.getType())
3233                                 {
3234                                     if (s != tx.toDsymbol(sc))
3235                                         goto Lnomatch;
3236                                 }
3237                                 else
3238                                     goto Lnomatch;
3239                             }
3240                             s = s.parent;
3241                         }
3242                         else
3243                             goto Lnomatch;
3244                     }
3245                     //printf("[e] s = %s\n", s?s.toChars():"(null)");
3246                     if (tp.isTemplateTypeParameter())
3247                     {
3248                         Type tt = s.getType();
3249                         if (!tt)
3250                             goto Lnomatch;
3251                         Type at = cast(Type)(*dedtypes)[i];
3252                         if (at && at.ty == Tnone)
3253                             at = (cast(TypeDeduced)at).tded;
3254                         if (!at || tt.equals(at))
3255                         {
3256                             (*dedtypes)[i] = tt;
3257                             goto Lexact;
3258                         }
3259                     }
3260                     if (tp.isTemplateAliasParameter())
3261                     {
3262                         Dsymbol s2 = cast(Dsymbol)(*dedtypes)[i];
3263                         if (!s2 || s == s2)
3264                         {
3265                             (*dedtypes)[i] = s;
3266                             goto Lexact;
3267                         }
3268                     }
3269                     goto Lnomatch;
3270                 }
3271 
3272                 // Found the corresponding parameter tp
3273                 if (!tp.isTemplateTypeParameter())
3274                     goto Lnomatch;
3275 
3276                 Type at = cast(Type)(*dedtypes)[i];
3277                 Type tt;
3278                 if (ubyte wx = wm ? deduceWildHelper(t, &tt, tparam) : 0)
3279                 {
3280                     // type vs (none)
3281                     if (!at)
3282                     {
3283                         (*dedtypes)[i] = tt;
3284                         *wm |= wx;
3285                         result = MATCHconst;
3286                         return;
3287                     }
3288 
3289                     // type vs expressions
3290                     if (at.ty == Tnone)
3291                     {
3292                         TypeDeduced xt = cast(TypeDeduced)at;
3293                         result = xt.matchAll(tt);
3294                         if (result > MATCHnomatch)
3295                         {
3296                             (*dedtypes)[i] = tt;
3297                             if (result > MATCHconst)
3298                                 result = MATCHconst; // limit level for inout matches
3299                         }
3300                         return;
3301                     }
3302 
3303                     // type vs type
3304                     if (tt.equals(at))
3305                     {
3306                         (*dedtypes)[i] = tt; // Prefer current type match
3307                         goto Lconst;
3308                     }
3309                     if (tt.implicitConvTo(at.constOf()))
3310                     {
3311                         (*dedtypes)[i] = at.constOf().mutableOf();
3312                         *wm |= MODconst;
3313                         goto Lconst;
3314                     }
3315                     if (at.implicitConvTo(tt.constOf()))
3316                     {
3317                         (*dedtypes)[i] = tt.constOf().mutableOf();
3318                         *wm |= MODconst;
3319                         goto Lconst;
3320                     }
3321                     goto Lnomatch;
3322                 }
3323                 else if (MATCH m = deduceTypeHelper(t, &tt, tparam))
3324                 {
3325                     // type vs (none)
3326                     if (!at)
3327                     {
3328                         (*dedtypes)[i] = tt;
3329                         result = m;
3330                         return;
3331                     }
3332 
3333                     // type vs expressions
3334                     if (at.ty == Tnone)
3335                     {
3336                         TypeDeduced xt = cast(TypeDeduced)at;
3337                         result = xt.matchAll(tt);
3338                         if (result > MATCHnomatch)
3339                         {
3340                             (*dedtypes)[i] = tt;
3341                         }
3342                         return;
3343                     }
3344 
3345                     // type vs type
3346                     if (tt.equals(at))
3347                     {
3348                         goto Lexact;
3349                     }
3350                     if (tt.ty == Tclass && at.ty == Tclass)
3351                     {
3352                         result = tt.implicitConvTo(at);
3353                         return;
3354                     }
3355                     if (tt.ty == Tsarray && at.ty == Tarray && tt.nextOf().implicitConvTo(at.nextOf()) >= MATCHconst)
3356                     {
3357                         goto Lexact;
3358                     }
3359                 }
3360                 goto Lnomatch;
3361             }
3362 
3363             if (tparam.ty == Ttypeof)
3364             {
3365                 /* Need a loc to go with the semantic routine.
3366                  */
3367                 Loc loc;
3368                 if (parameters.dim)
3369                 {
3370                     TemplateParameter tp = (*parameters)[0];
3371                     loc = tp.loc;
3372                 }
3373 
3374                 tparam = tparam.semantic(loc, sc);
3375             }
3376             if (t.ty != tparam.ty)
3377             {
3378                 if (Dsymbol sym = t.toDsymbol(sc))
3379                 {
3380                     if (sym.isforwardRef() && !tparam.deco)
3381                         goto Lnomatch;
3382                 }
3383 
3384                 MATCH m = t.implicitConvTo(tparam);
3385                 if (m == MATCHnomatch)
3386                 {
3387                     if (t.ty == Tclass)
3388                     {
3389                         TypeClass tc = cast(TypeClass)t;
3390                         if (tc.sym.aliasthis && !(tc.att & RECtracingDT))
3391                         {
3392                             tc.att = cast(AliasThisRec)(tc.att | RECtracingDT);
3393                             m = deduceType(t.aliasthisOf(), sc, tparam, parameters, dedtypes, wm);
3394                             tc.att = cast(AliasThisRec)(tc.att & ~RECtracingDT);
3395                         }
3396                     }
3397                     else if (t.ty == Tstruct)
3398                     {
3399                         TypeStruct ts = cast(TypeStruct)t;
3400                         if (ts.sym.aliasthis && !(ts.att & RECtracingDT))
3401                         {
3402                             ts.att = cast(AliasThisRec)(ts.att | RECtracingDT);
3403                             m = deduceType(t.aliasthisOf(), sc, tparam, parameters, dedtypes, wm);
3404                             ts.att = cast(AliasThisRec)(ts.att & ~RECtracingDT);
3405                         }
3406                     }
3407                 }
3408                 result = m;
3409                 return;
3410             }
3411 
3412             if (t.nextOf())
3413             {
3414                 if (tparam.deco && !tparam.hasWild())
3415                 {
3416                     result = t.implicitConvTo(tparam);
3417                     return;
3418                 }
3419 
3420                 Type tpn = tparam.nextOf();
3421                 if (wm && t.ty == Taarray && tparam.isWild())
3422                 {
3423                     // https://issues.dlang.org/show_bug.cgi?id=12403
3424                     // In IFTI, stop inout matching on transitive part of AA types.
3425                     tpn = tpn.substWildTo(MODmutable);
3426                 }
3427 
3428                 result = deduceType(t.nextOf(), sc, tpn, parameters, dedtypes, wm);
3429                 return;
3430             }
3431 
3432         Lexact:
3433             result = MATCHexact;
3434             return;
3435 
3436         Lnomatch:
3437             result = MATCHnomatch;
3438             return;
3439 
3440         Lconst:
3441             result = MATCHconst;
3442         }
3443 
3444         override void visit(TypeVector t)
3445         {
3446             version (none)
3447             {
3448                 printf("TypeVector.deduceType()\n");
3449                 printf("\tthis   = %d, ", t.ty);
3450                 t.print();
3451                 printf("\ttparam = %d, ", tparam.ty);
3452                 tparam.print();
3453             }
3454             if (tparam.ty == Tvector)
3455             {
3456                 TypeVector tp = cast(TypeVector)tparam;
3457                 result = deduceType(t.basetype, sc, tp.basetype, parameters, dedtypes, wm);
3458                 return;
3459             }
3460             visit(cast(Type)t);
3461         }
3462 
3463         override void visit(TypeDArray t)
3464         {
3465             version (none)
3466             {
3467                 printf("TypeDArray.deduceType()\n");
3468                 printf("\tthis   = %d, ", t.ty);
3469                 t.print();
3470                 printf("\ttparam = %d, ", tparam.ty);
3471                 tparam.print();
3472             }
3473             visit(cast(Type)t);
3474         }
3475 
3476         override void visit(TypeSArray t)
3477         {
3478             version (none)
3479             {
3480                 printf("TypeSArray.deduceType()\n");
3481                 printf("\tthis   = %d, ", t.ty);
3482                 t.print();
3483                 printf("\ttparam = %d, ", tparam.ty);
3484                 tparam.print();
3485             }
3486 
3487             // Extra check that array dimensions must match
3488             if (tparam)
3489             {
3490                 if (tparam.ty == Tarray)
3491                 {
3492                     MATCH m = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
3493                     result = (m >= MATCHconst) ? MATCHconvert : MATCHnomatch;
3494                     return;
3495                 }
3496 
3497                 TemplateParameter tp = null;
3498                 Expression edim = null;
3499                 size_t i;
3500                 if (tparam.ty == Tsarray)
3501                 {
3502                     TypeSArray tsa = cast(TypeSArray)tparam;
3503                     if (tsa.dim.op == TOKvar && (cast(VarExp)tsa.dim).var.storage_class & STCtemplateparameter)
3504                     {
3505                         Identifier id = (cast(VarExp)tsa.dim).var.ident;
3506                         i = templateIdentifierLookup(id, parameters);
3507                         assert(i != IDX_NOTFOUND);
3508                         tp = (*parameters)[i];
3509                     }
3510                     else
3511                         edim = tsa.dim;
3512                 }
3513                 else if (tparam.ty == Taarray)
3514                 {
3515                     TypeAArray taa = cast(TypeAArray)tparam;
3516                     i = templateParameterLookup(taa.index, parameters);
3517                     if (i != IDX_NOTFOUND)
3518                         tp = (*parameters)[i];
3519                     else
3520                     {
3521                         Expression e;
3522                         Type tx;
3523                         Dsymbol s;
3524                         taa.index.resolve(Loc(), sc, &e, &tx, &s);
3525                         edim = s ? getValue(s) : getValue(e);
3526                     }
3527                 }
3528                 if (tp && tp.matchArg(sc, t.dim, i, parameters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
3529                 {
3530                     result = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
3531                     return;
3532                 }
3533             }
3534             visit(cast(Type)t);
3535         }
3536 
3537         override void visit(TypeAArray t)
3538         {
3539             version (none)
3540             {
3541                 printf("TypeAArray.deduceType()\n");
3542                 printf("\tthis   = %d, ", t.ty);
3543                 t.print();
3544                 printf("\ttparam = %d, ", tparam.ty);
3545                 tparam.print();
3546             }
3547 
3548             // Extra check that index type must match
3549             if (tparam && tparam.ty == Taarray)
3550             {
3551                 TypeAArray tp = cast(TypeAArray)tparam;
3552                 if (!deduceType(t.index, sc, tp.index, parameters, dedtypes))
3553                 {
3554                     result = MATCHnomatch;
3555                     return;
3556                 }
3557             }
3558             visit(cast(Type)t);
3559         }
3560 
3561         override void visit(TypeFunction t)
3562         {
3563             //printf("TypeFunction.deduceType()\n");
3564             //printf("\tthis   = %d, ", t.ty); t.print();
3565             //printf("\ttparam = %d, ", tparam.ty); tparam.print();
3566 
3567             // Extra check that function characteristics must match
3568             if (tparam && tparam.ty == Tfunction)
3569             {
3570                 TypeFunction tp = cast(TypeFunction)tparam;
3571                 if (t.varargs != tp.varargs || t.linkage != tp.linkage)
3572                 {
3573                     result = MATCHnomatch;
3574                     return;
3575                 }
3576 
3577                 size_t nfargs = Parameter.dim(t.parameters);
3578                 size_t nfparams = Parameter.dim(tp.parameters);
3579 
3580                 // https://issues.dlang.org/show_bug.cgi?id=2579
3581                 // Apply function parameter storage classes to parameter types
3582                 for (size_t i = 0; i < nfparams; i++)
3583                 {
3584                     Parameter fparam = Parameter.getNth(tp.parameters, i);
3585                     fparam.type = fparam.type.addStorageClass(fparam.storageClass);
3586                     fparam.storageClass &= ~(STC_TYPECTOR | STCin);
3587                 }
3588                 //printf("\t. this   = %d, ", t.ty); t.print();
3589                 //printf("\t. tparam = %d, ", tparam.ty); tparam.print();
3590 
3591                 /* See if tuple match
3592                  */
3593                 if (nfparams > 0 && nfargs >= nfparams - 1)
3594                 {
3595                     /* See if 'A' of the template parameter matches 'A'
3596                      * of the type of the last function parameter.
3597                      */
3598                     Parameter fparam = Parameter.getNth(tp.parameters, nfparams - 1);
3599                     assert(fparam);
3600                     assert(fparam.type);
3601                     if (fparam.type.ty != Tident)
3602                         goto L1;
3603                     TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
3604                     if (tid.idents.dim)
3605                         goto L1;
3606 
3607                     /* Look through parameters to find tuple matching tid.ident
3608                      */
3609                     size_t tupi = 0;
3610                     for (; 1; tupi++)
3611                     {
3612                         if (tupi == parameters.dim)
3613                             goto L1;
3614                         TemplateParameter tx = (*parameters)[tupi];
3615                         TemplateTupleParameter tup = tx.isTemplateTupleParameter();
3616                         if (tup && tup.ident.equals(tid.ident))
3617                             break;
3618                     }
3619 
3620                     /* The types of the function arguments [nfparams - 1 .. nfargs]
3621                      * now form the tuple argument.
3622                      */
3623                     size_t tuple_dim = nfargs - (nfparams - 1);
3624 
3625                     /* See if existing tuple, and whether it matches or not
3626                      */
3627                     RootObject o = (*dedtypes)[tupi];
3628                     if (o)
3629                     {
3630                         // Existing deduced argument must be a tuple, and must match
3631                         Tuple tup = isTuple(o);
3632                         if (!tup || tup.objects.dim != tuple_dim)
3633                         {
3634                             result = MATCHnomatch;
3635                             return;
3636                         }
3637                         for (size_t i = 0; i < tuple_dim; i++)
3638                         {
3639                             Parameter arg = Parameter.getNth(t.parameters, nfparams - 1 + i);
3640                             if (!arg.type.equals(tup.objects[i]))
3641                             {
3642                                 result = MATCHnomatch;
3643                                 return;
3644                             }
3645                         }
3646                     }
3647                     else
3648                     {
3649                         // Create new tuple
3650                         auto tup = new Tuple();
3651                         tup.objects.setDim(tuple_dim);
3652                         for (size_t i = 0; i < tuple_dim; i++)
3653                         {
3654                             Parameter arg = Parameter.getNth(t.parameters, nfparams - 1 + i);
3655                             tup.objects[i] = arg.type;
3656                         }
3657                         (*dedtypes)[tupi] = tup;
3658                     }
3659                     nfparams--; // don't consider the last parameter for type deduction
3660                     goto L2;
3661                 }
3662 
3663             L1:
3664                 if (nfargs != nfparams)
3665                 {
3666                     result = MATCHnomatch;
3667                     return;
3668                 }
3669             L2:
3670                 for (size_t i = 0; i < nfparams; i++)
3671                 {
3672                     Parameter a = Parameter.getNth(t.parameters, i);
3673                     Parameter ap = Parameter.getNth(tp.parameters, i);
3674                     if (a.storageClass != ap.storageClass || !deduceType(a.type, sc, ap.type, parameters, dedtypes))
3675                     {
3676                         result = MATCHnomatch;
3677                         return;
3678                     }
3679                 }
3680             }
3681             visit(cast(Type)t);
3682         }
3683 
3684         override void visit(TypeIdentifier t)
3685         {
3686             // Extra check
3687             if (tparam && tparam.ty == Tident)
3688             {
3689                 TypeIdentifier tp = cast(TypeIdentifier)tparam;
3690                 for (size_t i = 0; i < t.idents.dim; i++)
3691                 {
3692                     RootObject id1 = t.idents[i];
3693                     RootObject id2 = tp.idents[i];
3694                     if (!id1.equals(id2))
3695                     {
3696                         result = MATCHnomatch;
3697                         return;
3698                     }
3699                 }
3700             }
3701             visit(cast(Type)t);
3702         }
3703 
3704         override void visit(TypeInstance t)
3705         {
3706             version (none)
3707             {
3708                 printf("TypeInstance.deduceType()\n");
3709                 printf("\tthis   = %d, ", t.ty);
3710                 t.print();
3711                 printf("\ttparam = %d, ", tparam.ty);
3712                 tparam.print();
3713             }
3714             // Extra check
3715             if (tparam && tparam.ty == Tinstance && t.tempinst.tempdecl)
3716             {
3717                 TemplateDeclaration tempdecl = t.tempinst.tempdecl.isTemplateDeclaration();
3718                 assert(tempdecl);
3719 
3720                 TypeInstance tp = cast(TypeInstance)tparam;
3721 
3722                 //printf("tempinst.tempdecl = %p\n", tempdecl);
3723                 //printf("tp.tempinst.tempdecl = %p\n", tp.tempinst.tempdecl);
3724                 if (!tp.tempinst.tempdecl)
3725                 {
3726                     //printf("tp.tempinst.name = '%s'\n", tp.tempinst.name.toChars());
3727 
3728                     /* Handle case of:
3729                      *  template Foo(T : sa!(T), alias sa)
3730                      */
3731                     size_t i = templateIdentifierLookup(tp.tempinst.name, parameters);
3732                     if (i == IDX_NOTFOUND)
3733                     {
3734                         /* Didn't find it as a parameter identifier. Try looking
3735                          * it up and seeing if is an alias.
3736                          * https://issues.dlang.org/show_bug.cgi?id=1454
3737                          */
3738                         auto tid = new TypeIdentifier(tp.loc, tp.tempinst.name);
3739                         Type tx;
3740                         Expression e;
3741                         Dsymbol s;
3742                         tid.resolve(tp.loc, sc, &e, &tx, &s);
3743                         if (tx)
3744                         {
3745                             s = tx.toDsymbol(sc);
3746                             if (TemplateInstance ti = s ? s.parent.isTemplateInstance() : null)
3747                             {
3748                                 // https://issues.dlang.org/show_bug.cgi?id=14290
3749                                 // Try to match with ti.tempecl,
3750                                 // only when ti is an enclosing instance.
3751                                 Dsymbol p = sc.parent;
3752                                 while (p && p != ti)
3753                                     p = p.parent;
3754                                 if (p)
3755                                     s = ti.tempdecl;
3756                             }
3757                         }
3758                         if (s)
3759                         {
3760                             s = s.toAlias();
3761                             TemplateDeclaration td = s.isTemplateDeclaration();
3762                             if (td)
3763                             {
3764                                 if (td.overroot)
3765                                     td = td.overroot;
3766                                 for (; td; td = td.overnext)
3767                                 {
3768                                     if (td == tempdecl)
3769                                         goto L2;
3770                                 }
3771                             }
3772                         }
3773                         goto Lnomatch;
3774                     }
3775                     TemplateParameter tpx = (*parameters)[i];
3776                     if (!tpx.matchArg(sc, tempdecl, i, parameters, dedtypes, null))
3777                         goto Lnomatch;
3778                 }
3779                 else if (tempdecl != tp.tempinst.tempdecl)
3780                     goto Lnomatch;
3781 
3782             L2:
3783                 for (size_t i = 0; 1; i++)
3784                 {
3785                     //printf("\ttest: tempinst.tiargs[%d]\n", i);
3786                     RootObject o1 = null;
3787                     if (i < t.tempinst.tiargs.dim)
3788                         o1 = (*t.tempinst.tiargs)[i];
3789                     else if (i < t.tempinst.tdtypes.dim && i < tp.tempinst.tiargs.dim)
3790                     {
3791                         // Pick up default arg
3792                         o1 = t.tempinst.tdtypes[i];
3793                     }
3794                     else if (i >= tp.tempinst.tiargs.dim)
3795                         break;
3796 
3797                     if (i >= tp.tempinst.tiargs.dim)
3798                     {
3799                         size_t dim = tempdecl.parameters.dim - (tempdecl.isVariadic() ? 1 : 0);
3800                         while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
3801                         {
3802                             i++;
3803                         }
3804                         if (i >= dim)
3805                             break; // match if all remained parameters are dependent
3806                         goto Lnomatch;
3807                     }
3808 
3809                     RootObject o2 = (*tp.tempinst.tiargs)[i];
3810                     Type t2 = isType(o2);
3811 
3812                     size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.dim - 1)
3813                         ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
3814                     if (j != IDX_NOTFOUND && j == parameters.dim - 1 &&
3815                         (*parameters)[j].isTemplateTupleParameter())
3816                     {
3817                         /* Given:
3818                          *  struct A(B...) {}
3819                          *  alias A!(int, float) X;
3820                          *  static if (is(X Y == A!(Z), Z...)) {}
3821                          * deduce that Z is a tuple(int, float)
3822                          */
3823 
3824                         /* Create tuple from remaining args
3825                          */
3826                         auto vt = new Tuple();
3827                         size_t vtdim = (tempdecl.isVariadic() ? t.tempinst.tiargs.dim : t.tempinst.tdtypes.dim) - i;
3828                         vt.objects.setDim(vtdim);
3829                         for (size_t k = 0; k < vtdim; k++)
3830                         {
3831                             RootObject o;
3832                             if (k < t.tempinst.tiargs.dim)
3833                                 o = (*t.tempinst.tiargs)[i + k];
3834                             else // Pick up default arg
3835                                 o = t.tempinst.tdtypes[i + k];
3836                             vt.objects[k] = o;
3837                         }
3838 
3839                         Tuple v = cast(Tuple)(*dedtypes)[j];
3840                         if (v)
3841                         {
3842                             if (!match(v, vt))
3843                                 goto Lnomatch;
3844                         }
3845                         else
3846                             (*dedtypes)[j] = vt;
3847                         break;
3848                     }
3849                     else if (!o1)
3850                         break;
3851 
3852                     Type t1 = isType(o1);
3853                     Dsymbol s1 = isDsymbol(o1);
3854                     Dsymbol s2 = isDsymbol(o2);
3855                     Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
3856                     Expression e2 = isExpression(o2);
3857                     version (none)
3858                     {
3859                         Tuple v1 = isTuple(o1);
3860                         Tuple v2 = isTuple(o2);
3861                         if (t1)
3862                             printf("t1 = %s\n", t1.toChars());
3863                         if (t2)
3864                             printf("t2 = %s\n", t2.toChars());
3865                         if (e1)
3866                             printf("e1 = %s\n", e1.toChars());
3867                         if (e2)
3868                             printf("e2 = %s\n", e2.toChars());
3869                         if (s1)
3870                             printf("s1 = %s\n", s1.toChars());
3871                         if (s2)
3872                             printf("s2 = %s\n", s2.toChars());
3873                         if (v1)
3874                             printf("v1 = %s\n", v1.toChars());
3875                         if (v2)
3876                             printf("v2 = %s\n", v2.toChars());
3877                     }
3878 
3879                     if (t1 && t2)
3880                     {
3881                         if (!deduceType(t1, sc, t2, parameters, dedtypes))
3882                             goto Lnomatch;
3883                     }
3884                     else if (e1 && e2)
3885                     {
3886                     Le:
3887                         e1 = e1.ctfeInterpret();
3888 
3889                         /* If it is one of the template parameters for this template,
3890                          * we should not attempt to interpret it. It already has a value.
3891                          */
3892                         if (e2.op == TOKvar && ((cast(VarExp)e2).var.storage_class & STCtemplateparameter))
3893                         {
3894                             /*
3895                              * (T:Number!(e2), int e2)
3896                              */
3897                             j = templateIdentifierLookup((cast(VarExp)e2).var.ident, parameters);
3898                             if (j != IDX_NOTFOUND)
3899                                 goto L1;
3900                             // The template parameter was not from this template
3901                             // (it may be from a parent template, for example)
3902                         }
3903 
3904                         e2 = e2.semantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
3905                         e2 = e2.ctfeInterpret();
3906 
3907                         //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
3908                         //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
3909                         if (!e1.equals(e2))
3910                         {
3911                             if (!e2.implicitConvTo(e1.type))
3912                                 goto Lnomatch;
3913 
3914                             e2 = e2.implicitCastTo(sc, e1.type);
3915                             e2 = e2.ctfeInterpret();
3916                             if (!e1.equals(e2))
3917                                 goto Lnomatch;
3918                         }
3919                     }
3920                     else if (e1 && t2 && t2.ty == Tident)
3921                     {
3922                         j = templateParameterLookup(t2, parameters);
3923                     L1:
3924                         if (j == IDX_NOTFOUND)
3925                         {
3926                             t2.resolve((cast(TypeIdentifier)t2).loc, sc, &e2, &t2, &s2);
3927                             if (e2)
3928                                 goto Le;
3929                             goto Lnomatch;
3930                         }
3931                         if (!(*parameters)[j].matchArg(sc, e1, j, parameters, dedtypes, null))
3932                             goto Lnomatch;
3933                     }
3934                     else if (s1 && s2)
3935                     {
3936                     Ls:
3937                         if (!s1.equals(s2))
3938                             goto Lnomatch;
3939                     }
3940                     else if (s1 && t2 && t2.ty == Tident)
3941                     {
3942                         j = templateParameterLookup(t2, parameters);
3943                         if (j == IDX_NOTFOUND)
3944                         {
3945                             t2.resolve((cast(TypeIdentifier)t2).loc, sc, &e2, &t2, &s2);
3946                             if (s2)
3947                                 goto Ls;
3948                             goto Lnomatch;
3949                         }
3950                         if (!(*parameters)[j].matchArg(sc, s1, j, parameters, dedtypes, null))
3951                             goto Lnomatch;
3952                     }
3953                     else
3954                         goto Lnomatch;
3955                 }
3956             }
3957             visit(cast(Type)t);
3958             return;
3959 
3960         Lnomatch:
3961             //printf("no match\n");
3962             result = MATCHnomatch;
3963         }
3964 
3965         override void visit(TypeStruct t)
3966         {
3967             version (none)
3968             {
3969                 printf("TypeStruct.deduceType()\n");
3970                 printf("\tthis.parent   = %s, ", t.sym.parent.toChars());
3971                 t.print();
3972                 printf("\ttparam = %d, ", tparam.ty);
3973                 tparam.print();
3974             }
3975 
3976             /* If this struct is a template struct, and we're matching
3977              * it against a template instance, convert the struct type
3978              * to a template instance, too, and try again.
3979              */
3980             TemplateInstance ti = t.sym.parent.isTemplateInstance();
3981 
3982             if (tparam && tparam.ty == Tinstance)
3983             {
3984                 if (ti && ti.toAlias() == t.sym)
3985                 {
3986                     auto tx = new TypeInstance(Loc(), ti);
3987                     result = deduceType(tx, sc, tparam, parameters, dedtypes, wm);
3988                     return;
3989                 }
3990 
3991                 /* Match things like:
3992                  *  S!(T).foo
3993                  */
3994                 TypeInstance tpi = cast(TypeInstance)tparam;
3995                 if (tpi.idents.dim)
3996                 {
3997                     RootObject id = tpi.idents[tpi.idents.dim - 1];
3998                     if (id.dyncast() == DYNCAST_IDENTIFIER && t.sym.ident.equals(cast(Identifier)id))
3999                     {
4000                         Type tparent = t.sym.parent.getType();
4001                         if (tparent)
4002                         {
4003                             /* Slice off the .foo in S!(T).foo
4004                              */
4005                             tpi.idents.dim--;
4006                             result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
4007                             tpi.idents.dim++;
4008                             return;
4009                         }
4010                     }
4011                 }
4012             }
4013 
4014             // Extra check
4015             if (tparam && tparam.ty == Tstruct)
4016             {
4017                 TypeStruct tp = cast(TypeStruct)tparam;
4018 
4019                 //printf("\t%d\n", (MATCH) t.implicitConvTo(tp));
4020                 if (wm && t.deduceWild(tparam, false))
4021                 {
4022                     result = MATCHconst;
4023                     return;
4024                 }
4025                 result = t.implicitConvTo(tp);
4026                 return;
4027             }
4028             visit(cast(Type)t);
4029         }
4030 
4031         override void visit(TypeEnum t)
4032         {
4033             // Extra check
4034             if (tparam && tparam.ty == Tenum)
4035             {
4036                 TypeEnum tp = cast(TypeEnum)tparam;
4037                 if (t.sym == tp.sym)
4038                     visit(cast(Type)t);
4039                 else
4040                     result = MATCHnomatch;
4041                 return;
4042             }
4043             Type tb = t.toBasetype();
4044             if (tb.ty == tparam.ty || tb.ty == Tsarray && tparam.ty == Taarray)
4045             {
4046                 result = deduceType(tb, sc, tparam, parameters, dedtypes, wm);
4047                 return;
4048             }
4049             visit(cast(Type)t);
4050         }
4051 
4052         /* Helper for TypeClass.deduceType().
4053          * Classes can match with implicit conversion to a base class or interface.
4054          * This is complicated, because there may be more than one base class which
4055          * matches. In such cases, one or more parameters remain ambiguous.
4056          * For example,
4057          *
4058          *   interface I(X, Y) {}
4059          *   class C : I(uint, double), I(char, double) {}
4060          *   C x;
4061          *   foo(T, U)( I!(T, U) x)
4062          *
4063          *   deduces that U is double, but T remains ambiguous (could be char or uint).
4064          *
4065          * Given a baseclass b, and initial deduced types 'dedtypes', this function
4066          * tries to match tparam with b, and also tries all base interfaces of b.
4067          * If a match occurs, numBaseClassMatches is incremented, and the new deduced
4068          * types are ANDed with the current 'best' estimate for dedtypes.
4069          */
4070         static void deduceBaseClassParameters(ref BaseClass b, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, Objects* best, ref int numBaseClassMatches)
4071         {
4072             TemplateInstance parti = b.sym ? b.sym.parent.isTemplateInstance() : null;
4073             if (parti)
4074             {
4075                 // Make a temporary copy of dedtypes so we don't destroy it
4076                 auto tmpdedtypes = new Objects();
4077                 tmpdedtypes.setDim(dedtypes.dim);
4078                 memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.dim * (void*).sizeof);
4079 
4080                 auto t = new TypeInstance(Loc(), parti);
4081                 MATCH m = deduceType(t, sc, tparam, parameters, tmpdedtypes);
4082                 if (m > MATCHnomatch)
4083                 {
4084                     // If this is the first ever match, it becomes our best estimate
4085                     if (numBaseClassMatches == 0)
4086                         memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.dim * (void*).sizeof);
4087                     else
4088                         for (size_t k = 0; k < tmpdedtypes.dim; ++k)
4089                         {
4090                             // If we've found more than one possible type for a parameter,
4091                             // mark it as unknown.
4092                             if ((*tmpdedtypes)[k] != (*best)[k])
4093                                 (*best)[k] = (*dedtypes)[k];
4094                         }
4095                     ++numBaseClassMatches;
4096                 }
4097             }
4098 
4099             // Now recursively test the inherited interfaces
4100             foreach (ref bi; b.baseInterfaces)
4101             {
4102                 deduceBaseClassParameters(bi, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4103             }
4104         }
4105 
4106         override void visit(TypeClass t)
4107         {
4108             //printf("TypeClass.deduceType(this = %s)\n", t.toChars());
4109 
4110             /* If this class is a template class, and we're matching
4111              * it against a template instance, convert the class type
4112              * to a template instance, too, and try again.
4113              */
4114             TemplateInstance ti = t.sym.parent.isTemplateInstance();
4115 
4116             if (tparam && tparam.ty == Tinstance)
4117             {
4118                 if (ti && ti.toAlias() == t.sym)
4119                 {
4120                     auto tx = new TypeInstance(Loc(), ti);
4121                     MATCH m = deduceType(tx, sc, tparam, parameters, dedtypes, wm);
4122                     // Even if the match fails, there is still a chance it could match
4123                     // a base class.
4124                     if (m != MATCHnomatch)
4125                     {
4126                         result = m;
4127                         return;
4128                     }
4129                 }
4130 
4131                 /* Match things like:
4132                  *  S!(T).foo
4133                  */
4134                 TypeInstance tpi = cast(TypeInstance)tparam;
4135                 if (tpi.idents.dim)
4136                 {
4137                     RootObject id = tpi.idents[tpi.idents.dim - 1];
4138                     if (id.dyncast() == DYNCAST_IDENTIFIER && t.sym.ident.equals(cast(Identifier)id))
4139                     {
4140                         Type tparent = t.sym.parent.getType();
4141                         if (tparent)
4142                         {
4143                             /* Slice off the .foo in S!(T).foo
4144                              */
4145                             tpi.idents.dim--;
4146                             result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
4147                             tpi.idents.dim++;
4148                             return;
4149                         }
4150                     }
4151                 }
4152 
4153                 // If it matches exactly or via implicit conversion, we're done
4154                 visit(cast(Type)t);
4155                 if (result != MATCHnomatch)
4156                     return;
4157 
4158                 /* There is still a chance to match via implicit conversion to
4159                  * a base class or interface. Because there could be more than one such
4160                  * match, we need to check them all.
4161                  */
4162 
4163                 int numBaseClassMatches = 0; // Have we found an interface match?
4164 
4165                 // Our best guess at dedtypes
4166                 auto best = new Objects();
4167                 best.setDim(dedtypes.dim);
4168 
4169                 ClassDeclaration s = t.sym;
4170                 while (s && s.baseclasses.dim > 0)
4171                 {
4172                     // Test the base class
4173                     deduceBaseClassParameters(*(*s.baseclasses)[0], sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4174 
4175                     // Test the interfaces inherited by the base class
4176                     foreach (b; s.interfaces)
4177                     {
4178                         deduceBaseClassParameters(*b, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4179                     }
4180                     s = (*s.baseclasses)[0].sym;
4181                 }
4182 
4183                 if (numBaseClassMatches == 0)
4184                 {
4185                     result = MATCHnomatch;
4186                     return;
4187                 }
4188 
4189                 // If we got at least one match, copy the known types into dedtypes
4190                 memcpy(dedtypes.tdata(), best.tdata(), best.dim * (void*).sizeof);
4191                 result = MATCHconvert;
4192                 return;
4193             }
4194 
4195             // Extra check
4196             if (tparam && tparam.ty == Tclass)
4197             {
4198                 TypeClass tp = cast(TypeClass)tparam;
4199 
4200                 //printf("\t%d\n", (MATCH) t.implicitConvTo(tp));
4201                 if (wm && t.deduceWild(tparam, false))
4202                 {
4203                     result = MATCHconst;
4204                     return;
4205                 }
4206                 result = t.implicitConvTo(tp);
4207                 return;
4208             }
4209             visit(cast(Type)t);
4210         }
4211 
4212         override void visit(Expression e)
4213         {
4214             //printf("Expression.deduceType(e = %s)\n", e.toChars());
4215             size_t i = templateParameterLookup(tparam, parameters);
4216             if (i == IDX_NOTFOUND || (cast(TypeIdentifier)tparam).idents.dim > 0)
4217             {
4218                 if (e == emptyArrayElement && tparam.ty == Tarray)
4219                 {
4220                     Type tn = (cast(TypeNext)tparam).next;
4221                     result = deduceType(emptyArrayElement, sc, tn, parameters, dedtypes, wm);
4222                     return;
4223                 }
4224                 e.type.accept(this);
4225                 return;
4226             }
4227 
4228             TemplateTypeParameter tp = (*parameters)[i].isTemplateTypeParameter();
4229             if (!tp)
4230                 return; // nomatch
4231 
4232             if (e == emptyArrayElement)
4233             {
4234                 if ((*dedtypes)[i])
4235                 {
4236                     result = MATCHexact;
4237                     return;
4238                 }
4239                 if (tp.defaultType)
4240                 {
4241                     tp.defaultType.accept(this);
4242                     return;
4243                 }
4244             }
4245 
4246             Type at = cast(Type)(*dedtypes)[i];
4247             Type tt;
4248             if (ubyte wx = deduceWildHelper(e.type, &tt, tparam))
4249             {
4250                 *wm |= wx;
4251                 result = MATCHconst;
4252             }
4253             else if (MATCH m = deduceTypeHelper(e.type, &tt, tparam))
4254             {
4255                 result = m;
4256             }
4257             else
4258                 return; // nomatch
4259 
4260             // expression vs (none)
4261             if (!at)
4262             {
4263                 (*dedtypes)[i] = new TypeDeduced(tt, e, tparam);
4264                 return;
4265             }
4266 
4267             TypeDeduced xt = null;
4268             if (at.ty == Tnone)
4269             {
4270                 xt = cast(TypeDeduced)at;
4271                 at = xt.tded;
4272             }
4273 
4274             // From previous matched expressions to current deduced type
4275             MATCH match1 = xt ? xt.matchAll(tt) : MATCHnomatch;
4276 
4277             // From current expresssion to previous deduced type
4278             Type pt = at.addMod(tparam.mod);
4279             if (*wm)
4280                 pt = pt.substWildTo(*wm);
4281             MATCH match2 = e.implicitConvTo(pt);
4282 
4283             if (match1 > MATCHnomatch && match2 > MATCHnomatch)
4284             {
4285                 if (at.implicitConvTo(tt) <= MATCHnomatch)
4286                     match1 = MATCHnomatch; // Prefer at
4287                 else if (tt.implicitConvTo(at) <= MATCHnomatch)
4288                     match2 = MATCHnomatch; // Prefer tt
4289                 else if (tt.isTypeBasic() && tt.ty == at.ty && tt.mod != at.mod)
4290                 {
4291                     if (!tt.isMutable() && !at.isMutable())
4292                         tt = tt.mutableOf().addMod(MODmerge(tt.mod, at.mod));
4293                     else if (tt.isMutable())
4294                     {
4295                         if (at.mod == 0) // Prefer unshared
4296                             match1 = MATCHnomatch;
4297                         else
4298                             match2 = MATCHnomatch;
4299                     }
4300                     else if (at.isMutable())
4301                     {
4302                         if (tt.mod == 0) // Prefer unshared
4303                             match2 = MATCHnomatch;
4304                         else
4305                             match1 = MATCHnomatch;
4306                     }
4307                     //printf("tt = %s, at = %s\n", tt.toChars(), at.toChars());
4308                 }
4309                 else
4310                 {
4311                     match1 = MATCHnomatch;
4312                     match2 = MATCHnomatch;
4313                 }
4314             }
4315             if (match1 > MATCHnomatch)
4316             {
4317                 // Prefer current match: tt
4318                 if (xt)
4319                     xt.update(tt, e, tparam);
4320                 else
4321                     (*dedtypes)[i] = tt;
4322                 result = match1;
4323                 return;
4324             }
4325             if (match2 > MATCHnomatch)
4326             {
4327                 // Prefer previous match: (*dedtypes)[i]
4328                 if (xt)
4329                     xt.update(e, tparam);
4330                 result = match2;
4331                 return;
4332             }
4333 
4334             /* Deduce common type
4335              */
4336             if (Type t = rawTypeMerge(at, tt))
4337             {
4338                 if (xt)
4339                     xt.update(t, e, tparam);
4340                 else
4341                     (*dedtypes)[i] = t;
4342 
4343                 pt = tt.addMod(tparam.mod);
4344                 if (*wm)
4345                     pt = pt.substWildTo(*wm);
4346                 result = e.implicitConvTo(pt);
4347                 return;
4348             }
4349 
4350             result = MATCHnomatch;
4351         }
4352 
4353         MATCH deduceEmptyArrayElement()
4354         {
4355             if (!emptyArrayElement)
4356             {
4357                 emptyArrayElement = new IdentifierExp(Loc(), Id.p); // dummy
4358                 emptyArrayElement.type = Type.tvoid;
4359             }
4360             assert(tparam.ty == Tarray);
4361 
4362             Type tn = (cast(TypeNext)tparam).next;
4363             return deduceType(emptyArrayElement, sc, tn, parameters, dedtypes, wm);
4364         }
4365 
4366         override void visit(NullExp e)
4367         {
4368             if (tparam.ty == Tarray && e.type.ty == Tnull)
4369             {
4370                 // tparam:T[] <- e:null (void[])
4371                 result = deduceEmptyArrayElement();
4372                 return;
4373             }
4374             visit(cast(Expression)e);
4375         }
4376 
4377         override void visit(StringExp e)
4378         {
4379             Type taai;
4380             if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
4381             {
4382                 // Consider compile-time known boundaries
4383                 e.type.nextOf().sarrayOf(e.len).accept(this);
4384                 return;
4385             }
4386             visit(cast(Expression)e);
4387         }
4388 
4389         override void visit(ArrayLiteralExp e)
4390         {
4391             if ((!e.elements || !e.elements.dim) && e.type.toBasetype().nextOf().ty == Tvoid && tparam.ty == Tarray)
4392             {
4393                 // tparam:T[] <- e:[] (void[])
4394                 result = deduceEmptyArrayElement();
4395                 return;
4396             }
4397 
4398             if (tparam.ty == Tarray && e.elements && e.elements.dim)
4399             {
4400                 Type tn = (cast(TypeDArray)tparam).next;
4401                 result = MATCHexact;
4402                 if (e.basis)
4403                 {
4404                     MATCH m = deduceType(e.basis, sc, tn, parameters, dedtypes, wm);
4405                     if (m < result)
4406                         result = m;
4407                 }
4408                 for (size_t i = 0; i < e.elements.dim; i++)
4409                 {
4410                     if (result <= MATCHnomatch)
4411                         break;
4412                     auto el = (*e.elements)[i];
4413                     if (!el)
4414                         continue;
4415                     MATCH m = deduceType(el, sc, tn, parameters, dedtypes, wm);
4416                     if (m < result)
4417                         result = m;
4418                 }
4419                 return;
4420             }
4421 
4422             Type taai;
4423             if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
4424             {
4425                 // Consider compile-time known boundaries
4426                 e.type.nextOf().sarrayOf(e.elements.dim).accept(this);
4427                 return;
4428             }
4429             visit(cast(Expression)e);
4430         }
4431 
4432         override void visit(AssocArrayLiteralExp e)
4433         {
4434             if (tparam.ty == Taarray && e.keys && e.keys.dim)
4435             {
4436                 TypeAArray taa = cast(TypeAArray)tparam;
4437                 result = MATCHexact;
4438                 for (size_t i = 0; i < e.keys.dim; i++)
4439                 {
4440                     MATCH m1 = deduceType((*e.keys)[i], sc, taa.index, parameters, dedtypes, wm);
4441                     if (m1 < result)
4442                         result = m1;
4443                     if (result <= MATCHnomatch)
4444                         break;
4445                     MATCH m2 = deduceType((*e.values)[i], sc, taa.next, parameters, dedtypes, wm);
4446                     if (m2 < result)
4447                         result = m2;
4448                     if (result <= MATCHnomatch)
4449                         break;
4450                 }
4451                 return;
4452             }
4453             visit(cast(Expression)e);
4454         }
4455 
4456         override void visit(FuncExp e)
4457         {
4458             //printf("e.type = %s, tparam = %s\n", e.type.toChars(), tparam.toChars());
4459             if (e.td)
4460             {
4461                 Type to = tparam;
4462                 if (!to.nextOf() || to.nextOf().ty != Tfunction)
4463                     return;
4464                 TypeFunction tof = cast(TypeFunction)to.nextOf();
4465 
4466                 // Parameter types inference from 'tof'
4467                 assert(e.td._scope);
4468                 TypeFunction tf = cast(TypeFunction)e.fd.type;
4469                 //printf("\ttof = %s\n", tof.toChars());
4470                 //printf("\ttf  = %s\n", tf.toChars());
4471                 size_t dim = Parameter.dim(tf.parameters);
4472 
4473                 if (Parameter.dim(tof.parameters) != dim || tof.varargs != tf.varargs)
4474                     return;
4475 
4476                 auto tiargs = new Objects();
4477                 tiargs.reserve(e.td.parameters.dim);
4478 
4479                 for (size_t i = 0; i < e.td.parameters.dim; i++)
4480                 {
4481                     TemplateParameter tp = (*e.td.parameters)[i];
4482                     size_t u = 0;
4483                     for (; u < dim; u++)
4484                     {
4485                         Parameter p = Parameter.getNth(tf.parameters, u);
4486                         if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4487                         {
4488                             break;
4489                         }
4490                     }
4491                     assert(u < dim);
4492                     Parameter pto = Parameter.getNth(tof.parameters, u);
4493                     if (!pto)
4494                         break;
4495                     Type t = pto.type.syntaxCopy(); // https://issues.dlang.org/show_bug.cgi?id=11774
4496                     if (reliesOnTident(t, parameters, inferStart))
4497                         return;
4498                     t = t.semantic(e.loc, sc);
4499                     if (t.ty == Terror)
4500                         return;
4501                     tiargs.push(t);
4502                 }
4503 
4504                 // Set target of return type inference
4505                 if (!tf.next && tof.next)
4506                     e.fd.treq = tparam;
4507 
4508                 auto ti = new TemplateInstance(e.loc, e.td, tiargs);
4509                 Expression ex = (new ScopeExp(e.loc, ti)).semantic(e.td._scope);
4510 
4511                 // Reset inference target for the later re-semantic
4512                 e.fd.treq = null;
4513 
4514                 if (ex.op == TOKerror)
4515                     return;
4516                 if (ex.op != TOKfunction)
4517                     return;
4518                 visit(ex.type);
4519                 return;
4520             }
4521 
4522             Type t = e.type;
4523 
4524             if (t.ty == Tdelegate && tparam.ty == Tpointer)
4525                 return;
4526 
4527             // Allow conversion from implicit function pointer to delegate
4528             if (e.tok == TOKreserved && t.ty == Tpointer && tparam.ty == Tdelegate)
4529             {
4530                 TypeFunction tf = cast(TypeFunction)t.nextOf();
4531                 t = (new TypeDelegate(tf)).merge();
4532             }
4533             //printf("tparam = %s <= e.type = %s, t = %s\n", tparam.toChars(), e.type.toChars(), t.toChars());
4534             visit(t);
4535         }
4536 
4537         override void visit(SliceExp e)
4538         {
4539             Type taai;
4540             if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
4541             {
4542                 // Consider compile-time known boundaries
4543                 if (Type tsa = toStaticArrayType(e))
4544                 {
4545                     tsa.accept(this);
4546                     return;
4547                 }
4548             }
4549             visit(cast(Expression)e);
4550         }
4551 
4552         override void visit(CommaExp e)
4553         {
4554             e.e2.accept(this);
4555         }
4556     }
4557 
4558     scope DeduceType v = new DeduceType(sc, tparam, parameters, dedtypes, wm, inferStart);
4559     if (Type t = isType(o))
4560         t.accept(v);
4561     else
4562     {
4563         assert(isExpression(o) && wm);
4564         (cast(Expression)o).accept(v);
4565     }
4566     return v.result;
4567 }
4568 
4569 /***********************************************************
4570  * Check whether the type t representation relies on one or more the template parameters.
4571  * Params:
4572  *      t           = Tested type, if null, returns false.
4573  *      tparams     = Template parameters.
4574  *      iStart      = Start index of tparams to limit the tested parameters. If it's
4575  *                    nonzero, tparams[0..iStart] will be excluded from the test target.
4576  */
4577 private bool reliesOnTident(Type t, TemplateParameters* tparams = null, size_t iStart = 0)
4578 {
4579     extern (C++) final class ReliesOnTident : Visitor
4580     {
4581         alias visit = super.visit;
4582     public:
4583         TemplateParameters* tparams;
4584         size_t iStart;
4585         bool result;
4586 
4587         extern (D) this(TemplateParameters* tparams, size_t iStart)
4588         {
4589             this.tparams = tparams;
4590             this.iStart = iStart;
4591         }
4592 
4593         override void visit(Type t)
4594         {
4595         }
4596 
4597         override void visit(TypeNext t)
4598         {
4599             t.next.accept(this);
4600         }
4601 
4602         override void visit(TypeVector t)
4603         {
4604             t.basetype.accept(this);
4605         }
4606 
4607         override void visit(TypeAArray t)
4608         {
4609             visit(cast(TypeNext)t);
4610             if (!result)
4611                 t.index.accept(this);
4612         }
4613 
4614         override void visit(TypeFunction t)
4615         {
4616             size_t dim = Parameter.dim(t.parameters);
4617             for (size_t i = 0; i < dim; i++)
4618             {
4619                 Parameter fparam = Parameter.getNth(t.parameters, i);
4620                 fparam.type.accept(this);
4621                 if (result)
4622                     return;
4623             }
4624             if (t.next)
4625                 t.next.accept(this);
4626         }
4627 
4628         override void visit(TypeIdentifier t)
4629         {
4630             for (size_t i = iStart; i < tparams.dim; i++)
4631             {
4632                 TemplateParameter tp = (*tparams)[i];
4633                 if (tp.ident.equals(t.ident))
4634                 {
4635                     result = true;
4636                     return;
4637                 }
4638             }
4639         }
4640 
4641         override void visit(TypeInstance t)
4642         {
4643             for (size_t i = iStart; i < tparams.dim; i++)
4644             {
4645                 TemplateParameter tp = (*tparams)[i];
4646                 if (t.tempinst.name == tp.ident)
4647                 {
4648                     result = true;
4649                     return;
4650                 }
4651             }
4652             if (!t.tempinst.tiargs)
4653                 return;
4654             for (size_t i = 0; i < t.tempinst.tiargs.dim; i++)
4655             {
4656                 Type ta = isType((*t.tempinst.tiargs)[i]);
4657                 if (ta)
4658                 {
4659                     ta.accept(this);
4660                     if (result)
4661                         return;
4662                 }
4663             }
4664         }
4665 
4666         override void visit(TypeTypeof t)
4667         {
4668             //printf("TypeTypeof.reliesOnTident('%s')\n", t.toChars());
4669             t.exp.accept(this);
4670         }
4671 
4672         override void visit(TypeTuple t)
4673         {
4674             if (t.arguments)
4675             {
4676                 for (size_t i = 0; i < t.arguments.dim; i++)
4677                 {
4678                     Parameter arg = (*t.arguments)[i];
4679                     arg.type.accept(this);
4680                     if (result)
4681                         return;
4682                 }
4683             }
4684         }
4685 
4686         override void visit(Expression e)
4687         {
4688             //printf("Expression.reliesOnTident('%s')\n", e.toChars());
4689         }
4690 
4691         override void visit(IdentifierExp e)
4692         {
4693             //printf("IdentifierExp.reliesOnTident('%s')\n", e.toChars());
4694             for (size_t i = iStart; i < tparams.dim; i++)
4695             {
4696                 auto tp = (*tparams)[i];
4697                 if (e.ident == tp.ident)
4698                 {
4699                     result = true;
4700                     return;
4701                 }
4702             }
4703         }
4704 
4705         override void visit(TupleExp e)
4706         {
4707             //printf("TupleExp.reliesOnTident('%s')\n", e.toChars());
4708             if (e.exps)
4709             {
4710                 foreach (ea; *e.exps)
4711                 {
4712                     ea.accept(this);
4713                     if (result)
4714                         return;
4715                 }
4716             }
4717         }
4718 
4719         override void visit(ArrayLiteralExp e)
4720         {
4721             //printf("ArrayLiteralExp.reliesOnTident('%s')\n", e.toChars());
4722             if (e.elements)
4723             {
4724                 foreach (el; *e.elements)
4725                 {
4726                     el.accept(this);
4727                     if (result)
4728                         return;
4729                 }
4730             }
4731         }
4732 
4733         override void visit(AssocArrayLiteralExp e)
4734         {
4735             //printf("AssocArrayLiteralExp.reliesOnTident('%s')\n", e.toChars());
4736             foreach (ek; *e.keys)
4737             {
4738                 ek.accept(this);
4739                 if (result)
4740                     return;
4741             }
4742             foreach (ev; *e.values)
4743             {
4744                 ev.accept(this);
4745                 if (result)
4746                     return;
4747             }
4748         }
4749 
4750         override void visit(StructLiteralExp e)
4751         {
4752             //printf("StructLiteralExp.reliesOnTident('%s')\n", e.toChars());
4753             if (e.elements)
4754             {
4755                 foreach (ea; *e.elements)
4756                 {
4757                     ea.accept(this);
4758                     if (result)
4759                         return;
4760                 }
4761             }
4762         }
4763 
4764         override void visit(TypeExp e)
4765         {
4766             //printf("TypeExp.reliesOnTident('%s')\n", e.toChars());
4767             e.type.accept(this);
4768         }
4769 
4770         override void visit(NewExp e)
4771         {
4772             //printf("NewExp.reliesOnTident('%s')\n", e.toChars());
4773             if (e.thisexp)
4774                 e.thisexp.accept(this);
4775             if (!result && e.newargs)
4776             {
4777                 foreach (ea; *e.newargs)
4778                 {
4779                     ea.accept(this);
4780                     if (result)
4781                         return;
4782                 }
4783             }
4784             e.newtype.accept(this);
4785             if (!result && e.arguments)
4786             {
4787                 foreach (ea; *e.arguments)
4788                 {
4789                     ea.accept(this);
4790                     if (result)
4791                         return;
4792                 }
4793             }
4794         }
4795 
4796         override void visit(NewAnonClassExp e)
4797         {
4798             //printf("NewAnonClassExp.reliesOnTident('%s')\n", e.toChars());
4799             result = true;
4800         }
4801 
4802         override void visit(FuncExp e)
4803         {
4804             //printf("FuncExp.reliesOnTident('%s')\n", e.toChars());
4805             result = true;
4806         }
4807 
4808         override void visit(TypeidExp e)
4809         {
4810             //printf("TypeidExp.reliesOnTident('%s')\n", e.toChars());
4811             if (auto ea = isExpression(e.obj))
4812                 ea.accept(this);
4813             else if (auto ta = isType(e.obj))
4814                 ta.accept(this);
4815         }
4816 
4817         override void visit(TraitsExp e)
4818         {
4819             //printf("TraitsExp.reliesOnTident('%s')\n", e.toChars());
4820             if (e.args)
4821             {
4822                 foreach (oa; *e.args)
4823                 {
4824                     if (auto ea = isExpression(oa))
4825                         ea.accept(this);
4826                     else if (auto ta = isType(oa))
4827                         ta.accept(this);
4828                     if (result)
4829                         return;
4830                 }
4831             }
4832         }
4833 
4834         override void visit(IsExp e)
4835         {
4836             //printf("IsExp.reliesOnTident('%s')\n", e.toChars());
4837             e.targ.accept(this);
4838         }
4839 
4840         override void visit(UnaExp e)
4841         {
4842             //printf("UnaExp.reliesOnTident('%s')\n", e.toChars());
4843             e.e1.accept(this);
4844         }
4845 
4846         override void visit(DotTemplateInstanceExp e)
4847         {
4848             //printf("DotTemplateInstanceExp.reliesOnTident('%s')\n", e.toChars());
4849             visit(cast(UnaExp)e);
4850             if (!result && e.ti.tiargs)
4851             {
4852                 foreach (oa; *e.ti.tiargs)
4853                 {
4854                     if (auto ea = isExpression(oa))
4855                         ea.accept(this);
4856                     else if (auto ta = isType(oa))
4857                         ta.accept(this);
4858                     if (result)
4859                         return;
4860                 }
4861             }
4862         }
4863 
4864         override void visit(CallExp e)
4865         {
4866             //printf("CallExp.reliesOnTident('%s')\n", e.toChars());
4867             visit(cast(UnaExp)e);
4868             if (!result && e.arguments)
4869             {
4870                 foreach (ea; *e.arguments)
4871                 {
4872                     ea.accept(this);
4873                     if (result)
4874                         return;
4875                 }
4876             }
4877         }
4878 
4879         override void visit(CastExp e)
4880         {
4881             //printf("CallExp.reliesOnTident('%s')\n", e.toChars());
4882             visit(cast(UnaExp)e);
4883             if (!result)
4884                 e.to.accept(this);
4885         }
4886 
4887         override void visit(SliceExp e)
4888         {
4889             //printf("SliceExp.reliesOnTident('%s')\n", e.toChars());
4890             visit(cast(UnaExp)e);
4891             if (!result && e.lwr)
4892                 e.lwr.accept(this);
4893             if (!result && e.upr)
4894                 e.upr.accept(this);
4895         }
4896 
4897         override void visit(IntervalExp e)
4898         {
4899             //printf("IntervalExp.reliesOnTident('%s')\n", e.toChars());
4900             e.lwr.accept(this);
4901             if (!result)
4902                 e.upr.accept(this);
4903         }
4904 
4905         override void visit(ArrayExp e)
4906         {
4907             //printf("ArrayExp.reliesOnTident('%s')\n", e.toChars());
4908             visit(cast(UnaExp)e);
4909             if (!result && e.arguments)
4910             {
4911                 foreach (ea; *e.arguments)
4912                     ea.accept(this);
4913             }
4914         }
4915 
4916         override void visit(BinExp e)
4917         {
4918             //printf("BinExp.reliesOnTident('%s')\n", e.toChars());
4919             e.e1.accept(this);
4920             if (!result)
4921                 e.e2.accept(this);
4922         }
4923 
4924         override void visit(CondExp e)
4925         {
4926             //printf("BinExp.reliesOnTident('%s')\n", e.toChars());
4927             e.econd.accept(this);
4928             if (!result)
4929                 visit(cast(BinExp)e);
4930         }
4931     }
4932 
4933     if (!t)
4934         return false;
4935 
4936     assert(tparams);
4937     scope ReliesOnTident v = new ReliesOnTident(tparams, iStart);
4938     t.accept(v);
4939     return v.result;
4940 }
4941 
4942 /***********************************************************
4943  */
4944 extern (C++) class TemplateParameter
4945 {
4946     Loc loc;
4947     Identifier ident;
4948 
4949     /* True if this is a part of precedent parameter specialization pattern.
4950      *
4951      *  template A(T : X!TL, alias X, TL...) {}
4952      *  // X and TL are dependent template parameter
4953      *
4954      * A dependent template parameter should return MATCHexact in matchArg()
4955      * to respect the match level of the corresponding precedent parameter.
4956      */
4957     bool dependent;
4958 
4959     /* ======================== TemplateParameter =============================== */
4960     final extern (D) this(Loc loc, Identifier ident)
4961     {
4962         this.loc = loc;
4963         this.ident = ident;
4964     }
4965 
4966     TemplateTypeParameter isTemplateTypeParameter()
4967     {
4968         return null;
4969     }
4970 
4971     TemplateValueParameter isTemplateValueParameter()
4972     {
4973         return null;
4974     }
4975 
4976     TemplateAliasParameter isTemplateAliasParameter()
4977     {
4978         return null;
4979     }
4980 
4981     TemplateThisParameter isTemplateThisParameter()
4982     {
4983         return null;
4984     }
4985 
4986     TemplateTupleParameter isTemplateTupleParameter()
4987     {
4988         return null;
4989     }
4990 
4991     abstract TemplateParameter syntaxCopy();
4992 
4993     abstract bool declareParameter(Scope* sc);
4994 
4995     abstract bool semantic(Scope* sc, TemplateParameters* parameters);
4996 
4997     abstract void print(RootObject oarg, RootObject oded);
4998 
4999     abstract RootObject specialization();
5000 
5001     abstract RootObject defaultArg(Loc instLoc, Scope* sc);
5002 
5003     abstract bool hasDefaultArg();
5004 
5005     /*******************************************
5006      * Match to a particular TemplateParameter.
5007      * Input:
5008      *      instLoc         location that the template is instantiated.
5009      *      tiargs[]        actual arguments to template instance
5010      *      i               i'th argument
5011      *      parameters[]    template parameters
5012      *      dedtypes[]      deduced arguments to template instance
5013      *      *psparam        set to symbol declared and initialized to dedtypes[i]
5014      */
5015     MATCH matchArg(Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
5016     {
5017         RootObject oarg;
5018 
5019         if (i < tiargs.dim)
5020             oarg = (*tiargs)[i];
5021         else
5022         {
5023             // Get default argument instead
5024             oarg = defaultArg(instLoc, sc);
5025             if (!oarg)
5026             {
5027                 assert(i < dedtypes.dim);
5028                 // It might have already been deduced
5029                 oarg = (*dedtypes)[i];
5030                 if (!oarg)
5031                     goto Lnomatch;
5032             }
5033         }
5034         return matchArg(sc, oarg, i, parameters, dedtypes, psparam);
5035 
5036     Lnomatch:
5037         if (psparam)
5038             *psparam = null;
5039         return MATCHnomatch;
5040     }
5041 
5042     abstract MATCH matchArg(Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam);
5043 
5044     /* Create dummy argument based on parameter.
5045      */
5046     abstract void* dummyArg();
5047 
5048     void accept(Visitor v)
5049     {
5050         v.visit(this);
5051     }
5052 }
5053 
5054 /***********************************************************
5055  * Syntax:
5056  *  ident : specType = defaultType
5057  */
5058 extern (C++) class TemplateTypeParameter : TemplateParameter
5059 {
5060     Type specType;      // if !=null, this is the type specialization
5061     Type defaultType;
5062 
5063     extern (C++) static __gshared Type tdummy = null;
5064 
5065     final extern (D) this(Loc loc, Identifier ident, Type specType, Type defaultType)
5066     {
5067         super(loc, ident);
5068         this.ident = ident;
5069         this.specType = specType;
5070         this.defaultType = defaultType;
5071     }
5072 
5073     override final TemplateTypeParameter isTemplateTypeParameter()
5074     {
5075         return this;
5076     }
5077 
5078     override TemplateParameter syntaxCopy()
5079     {
5080         return new TemplateTypeParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5081     }
5082 
5083     override final bool declareParameter(Scope* sc)
5084     {
5085         //printf("TemplateTypeParameter.declareParameter('%s')\n", ident.toChars());
5086         auto ti = new TypeIdentifier(loc, ident);
5087         Declaration ad = new AliasDeclaration(loc, ident, ti);
5088         return sc.insert(ad) !is null;
5089     }
5090 
5091     override final bool semantic(Scope* sc, TemplateParameters* parameters)
5092     {
5093         //printf("TemplateTypeParameter.semantic('%s')\n", ident.toChars());
5094         if (specType && !reliesOnTident(specType, parameters))
5095         {
5096             specType = specType.semantic(loc, sc);
5097         }
5098         version (none)
5099         {
5100             // Don't do semantic() until instantiation
5101             if (defaultType)
5102             {
5103                 defaultType = defaultType.semantic(loc, sc);
5104             }
5105         }
5106         return !(specType && isError(specType));
5107     }
5108 
5109     override final void print(RootObject oarg, RootObject oded)
5110     {
5111         printf(" %s\n", ident.toChars());
5112 
5113         Type t = isType(oarg);
5114         Type ta = isType(oded);
5115         assert(ta);
5116 
5117         if (specType)
5118             printf("\tSpecialization: %s\n", specType.toChars());
5119         if (defaultType)
5120             printf("\tDefault:        %s\n", defaultType.toChars());
5121         printf("\tParameter:       %s\n", t ? t.toChars() : "NULL");
5122         printf("\tDeduced Type:   %s\n", ta.toChars());
5123     }
5124 
5125     override final RootObject specialization()
5126     {
5127         return specType;
5128     }
5129 
5130     override final RootObject defaultArg(Loc instLoc, Scope* sc)
5131     {
5132         Type t = defaultType;
5133         if (t)
5134         {
5135             t = t.syntaxCopy();
5136             t = t.semantic(loc, sc); // use the parameter loc
5137         }
5138         return t;
5139     }
5140 
5141     override final bool hasDefaultArg()
5142     {
5143         return defaultType !is null;
5144     }
5145 
5146     override final MATCH matchArg(Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
5147     {
5148         //printf("TemplateTypeParameter.matchArg('%s')\n", ident.toChars());
5149         MATCH m = MATCHexact;
5150         Type ta = isType(oarg);
5151         if (!ta)
5152         {
5153             //printf("%s %p %p %p\n", oarg.toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
5154             goto Lnomatch;
5155         }
5156         //printf("ta is %s\n", ta.toChars());
5157 
5158         if (specType)
5159         {
5160             if (!ta || ta == tdummy)
5161                 goto Lnomatch;
5162 
5163             //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta.toChars(), specType.toChars());
5164             MATCH m2 = deduceType(ta, sc, specType, parameters, dedtypes);
5165             if (m2 <= MATCHnomatch)
5166             {
5167                 //printf("\tfailed deduceType\n");
5168                 goto Lnomatch;
5169             }
5170 
5171             if (m2 < m)
5172                 m = m2;
5173             if ((*dedtypes)[i])
5174             {
5175                 Type t = cast(Type)(*dedtypes)[i];
5176 
5177                 if (dependent && !t.equals(ta)) // https://issues.dlang.org/show_bug.cgi?id=14357
5178                     goto Lnomatch;
5179 
5180                 /* This is a self-dependent parameter. For example:
5181                  *  template X(T : T*) {}
5182                  *  template X(T : S!T, alias S) {}
5183                  */
5184                 //printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
5185                 ta = t;
5186             }
5187         }
5188         else
5189         {
5190             if ((*dedtypes)[i])
5191             {
5192                 // Must match already deduced type
5193                 Type t = cast(Type)(*dedtypes)[i];
5194 
5195                 if (!t.equals(ta))
5196                 {
5197                     //printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
5198                     goto Lnomatch;
5199                 }
5200             }
5201             else
5202             {
5203                 // So that matches with specializations are better
5204                 m = MATCHconvert;
5205             }
5206         }
5207         (*dedtypes)[i] = ta;
5208 
5209         if (psparam)
5210             *psparam = new AliasDeclaration(loc, ident, ta);
5211         //printf("\tm = %d\n", m);
5212         return dependent ? MATCHexact : m;
5213 
5214     Lnomatch:
5215         if (psparam)
5216             *psparam = null;
5217         //printf("\tm = %d\n", MATCHnomatch);
5218         return MATCHnomatch;
5219     }
5220 
5221     override final void* dummyArg()
5222     {
5223         Type t = specType;
5224         if (!t)
5225         {
5226             // Use this for alias-parameter's too (?)
5227             if (!tdummy)
5228                 tdummy = new TypeIdentifier(loc, ident);
5229             t = tdummy;
5230         }
5231         return cast(void*)t;
5232     }
5233 
5234     override void accept(Visitor v)
5235     {
5236         v.visit(this);
5237     }
5238 }
5239 
5240 /***********************************************************
5241  * Syntax:
5242  *  this ident : specType = defaultType
5243  */
5244 extern (C++) final class TemplateThisParameter : TemplateTypeParameter
5245 {
5246     extern (D) this(Loc loc, Identifier ident, Type specType, Type defaultType)
5247     {
5248         super(loc, ident, specType, defaultType);
5249     }
5250 
5251     override TemplateThisParameter isTemplateThisParameter()
5252     {
5253         return this;
5254     }
5255 
5256     override TemplateParameter syntaxCopy()
5257     {
5258         return new TemplateThisParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5259     }
5260 
5261     override void accept(Visitor v)
5262     {
5263         v.visit(this);
5264     }
5265 }
5266 
5267 /***********************************************************
5268  * Syntax:
5269  *  valType ident : specValue = defaultValue
5270  */
5271 extern (C++) final class TemplateValueParameter : TemplateParameter
5272 {
5273     Type valType;
5274     Expression specValue;
5275     Expression defaultValue;
5276 
5277     extern (C++) static __gshared AA* edummies = null;
5278 
5279     extern (D) this(Loc loc, Identifier ident, Type valType,
5280         Expression specValue, Expression defaultValue)
5281     {
5282         super(loc, ident);
5283         this.ident = ident;
5284         this.valType = valType;
5285         this.specValue = specValue;
5286         this.defaultValue = defaultValue;
5287     }
5288 
5289     override TemplateValueParameter isTemplateValueParameter()
5290     {
5291         return this;
5292     }
5293 
5294     override TemplateParameter syntaxCopy()
5295     {
5296         return new TemplateValueParameter(loc, ident,
5297             valType.syntaxCopy(),
5298             specValue ? specValue.syntaxCopy() : null,
5299             defaultValue ? defaultValue.syntaxCopy() : null);
5300     }
5301 
5302     override bool declareParameter(Scope* sc)
5303     {
5304         auto v = new VarDeclaration(loc, valType, ident, null);
5305         v.storage_class = STCtemplateparameter;
5306         return sc.insert(v) !is null;
5307     }
5308 
5309     override bool semantic(Scope* sc, TemplateParameters* parameters)
5310     {
5311         valType = valType.semantic(loc, sc);
5312         version (none)
5313         {
5314             // defer semantic analysis to arg match
5315             if (specValue)
5316             {
5317                 Expression e = specValue;
5318                 sc = sc.startCTFE();
5319                 e = e.semantic(sc);
5320                 sc = sc.endCTFE();
5321                 e = e.implicitCastTo(sc, valType);
5322                 e = e.ctfeInterpret();
5323                 if (e.op == TOKint64 || e.op == TOKfloat64 ||
5324                     e.op == TOKcomplex80 || e.op == TOKnull || e.op == TOKstring)
5325                     specValue = e;
5326             }
5327 
5328             if (defaultValue)
5329             {
5330                 Expression e = defaultValue;
5331                 sc = sc.startCTFE();
5332                 e = e.semantic(sc);
5333                 sc = sc.endCTFE();
5334                 e = e.implicitCastTo(sc, valType);
5335                 e = e.ctfeInterpret();
5336                 if (e.op == TOKint64)
5337                     defaultValue = e;
5338             }
5339         }
5340         return !isError(valType);
5341     }
5342 
5343     override void print(RootObject oarg, RootObject oded)
5344     {
5345         printf(" %s\n", ident.toChars());
5346         Expression ea = isExpression(oded);
5347         if (specValue)
5348             printf("\tSpecialization: %s\n", specValue.toChars());
5349         printf("\tParameter Value: %s\n", ea ? ea.toChars() : "NULL");
5350     }
5351 
5352     override RootObject specialization()
5353     {
5354         return specValue;
5355     }
5356 
5357     override RootObject defaultArg(Loc instLoc, Scope* sc)
5358     {
5359         Expression e = defaultValue;
5360         if (e)
5361         {
5362             e = e.syntaxCopy();
5363             e = e.semantic(sc);
5364             e = resolveProperties(sc, e);
5365             e = e.resolveLoc(instLoc, sc); // use the instantiated loc
5366             e = e.optimize(WANTvalue);
5367         }
5368         return e;
5369     }
5370 
5371     override bool hasDefaultArg()
5372     {
5373         return defaultValue !is null;
5374     }
5375 
5376     override MATCH matchArg(Scope* sc, RootObject oarg,
5377         size_t i, TemplateParameters* parameters, Objects* dedtypes,
5378         Declaration* psparam)
5379     {
5380         //printf("TemplateValueParameter.matchArg('%s')\n", ident.toChars());
5381 
5382         MATCH m = MATCHexact;
5383 
5384         Expression ei = isExpression(oarg);
5385         Type vt;
5386 
5387         if (!ei && oarg)
5388         {
5389             Dsymbol si = isDsymbol(oarg);
5390             FuncDeclaration f = si ? si.isFuncDeclaration() : null;
5391             if (!f || !f.fbody || f.needThis())
5392                 goto Lnomatch;
5393 
5394             ei = new VarExp(loc, f);
5395             ei = ei.semantic(sc);
5396 
5397             /* If a function is really property-like, and then
5398              * it's CTFEable, ei will be a literal expression.
5399              */
5400             uint olderrors = global.startGagging();
5401             ei = resolveProperties(sc, ei);
5402             ei = ei.ctfeInterpret();
5403             if (global.endGagging(olderrors) || ei.op == TOKerror)
5404                 goto Lnomatch;
5405 
5406             /* https://issues.dlang.org/show_bug.cgi?id=14520
5407              * A property-like function can match to both
5408              * TemplateAlias and ValueParameter. But for template overloads,
5409              * it should always prefer alias parameter to be consistent
5410              * template match result.
5411              *
5412              *   template X(alias f) { enum X = 1; }
5413              *   template X(int val) { enum X = 2; }
5414              *   int f1() { return 0; }  // CTFEable
5415              *   int f2();               // body-less function is not CTFEable
5416              *   enum x1 = X!f1;    // should be 1
5417              *   enum x2 = X!f2;    // should be 1
5418              *
5419              * e.g. The x1 value must be same even if the f1 definition will be moved
5420              *      into di while stripping body code.
5421              */
5422             m = MATCHconvert;
5423         }
5424 
5425         if (ei && ei.op == TOKvar)
5426         {
5427             // Resolve const variables that we had skipped earlier
5428             ei = ei.ctfeInterpret();
5429         }
5430 
5431         //printf("\tvalType: %s, ty = %d\n", valType.toChars(), valType.ty);
5432         vt = valType.semantic(loc, sc);
5433         //printf("ei: %s, ei.type: %s\n", ei.toChars(), ei.type.toChars());
5434         //printf("vt = %s\n", vt.toChars());
5435 
5436         if (ei.type)
5437         {
5438             MATCH m2 = ei.implicitConvTo(vt);
5439             //printf("m: %d\n", m);
5440             if (m2 < m)
5441                 m = m2;
5442             if (m <= MATCHnomatch)
5443                 goto Lnomatch;
5444             ei = ei.implicitCastTo(sc, vt);
5445             ei = ei.ctfeInterpret();
5446         }
5447 
5448         if (specValue)
5449         {
5450             if (!ei || cast(Expression)dmd_aaGetRvalue(edummies, cast(void*)ei.type) == ei)
5451                 goto Lnomatch;
5452 
5453             Expression e = specValue;
5454 
5455             sc = sc.startCTFE();
5456             e = e.semantic(sc);
5457             e = resolveProperties(sc, e);
5458             sc = sc.endCTFE();
5459             e = e.implicitCastTo(sc, vt);
5460             e = e.ctfeInterpret();
5461 
5462             ei = ei.syntaxCopy();
5463             sc = sc.startCTFE();
5464             ei = ei.semantic(sc);
5465             sc = sc.endCTFE();
5466             ei = ei.implicitCastTo(sc, vt);
5467             ei = ei.ctfeInterpret();
5468             //printf("\tei: %s, %s\n", ei.toChars(), ei.type.toChars());
5469             //printf("\te : %s, %s\n", e.toChars(), e.type.toChars());
5470             if (!ei.equals(e))
5471                 goto Lnomatch;
5472         }
5473         else
5474         {
5475             if ((*dedtypes)[i])
5476             {
5477                 // Must match already deduced value
5478                 Expression e = cast(Expression)(*dedtypes)[i];
5479                 if (!ei || !ei.equals(e))
5480                     goto Lnomatch;
5481             }
5482         }
5483         (*dedtypes)[i] = ei;
5484 
5485         if (psparam)
5486         {
5487             Initializer _init = new ExpInitializer(loc, ei);
5488             Declaration sparam = new VarDeclaration(loc, vt, ident, _init);
5489             sparam.storage_class = STCmanifest;
5490             *psparam = sparam;
5491         }
5492         return dependent ? MATCHexact : m;
5493 
5494     Lnomatch:
5495         //printf("\tno match\n");
5496         if (psparam)
5497             *psparam = null;
5498         return MATCHnomatch;
5499     }
5500 
5501     override void* dummyArg()
5502     {
5503         Expression e = specValue;
5504         if (!e)
5505         {
5506             // Create a dummy value
5507             Expression* pe = cast(Expression*)dmd_aaGet(&edummies, cast(void*)valType);
5508             if (!*pe)
5509                 *pe = valType.defaultInit();
5510             e = *pe;
5511         }
5512         return cast(void*)e;
5513     }
5514 
5515     override void accept(Visitor v)
5516     {
5517         v.visit(this);
5518     }
5519 }
5520 
5521 private RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplateParameters* parameters)
5522 {
5523     if (o)
5524     {
5525         Expression ea = isExpression(o);
5526         Type ta = isType(o);
5527         if (ta && (!parameters || !reliesOnTident(ta, parameters)))
5528         {
5529             Dsymbol s = ta.toDsymbol(sc);
5530             if (s)
5531                 o = s;
5532             else
5533                 o = ta.semantic(loc, sc);
5534         }
5535         else if (ea)
5536         {
5537             sc = sc.startCTFE();
5538             ea = ea.semantic(sc);
5539             sc = sc.endCTFE();
5540             o = ea.ctfeInterpret();
5541         }
5542     }
5543     return o;
5544 }
5545 
5546 /***********************************************************
5547  * Syntax:
5548  *  specType ident : specAlias = defaultAlias
5549  */
5550 extern (C++) final class TemplateAliasParameter : TemplateParameter
5551 {
5552     Type specType;
5553     RootObject specAlias;
5554     RootObject defaultAlias;
5555 
5556     extern (C++) static __gshared Dsymbol sdummy = null;
5557 
5558     extern (D) this(Loc loc, Identifier ident, Type specType, RootObject specAlias, RootObject defaultAlias)
5559     {
5560         super(loc, ident);
5561         this.ident = ident;
5562         this.specType = specType;
5563         this.specAlias = specAlias;
5564         this.defaultAlias = defaultAlias;
5565     }
5566 
5567     override TemplateAliasParameter isTemplateAliasParameter()
5568     {
5569         return this;
5570     }
5571 
5572     override TemplateParameter syntaxCopy()
5573     {
5574         return new TemplateAliasParameter(loc, ident, specType ? specType.syntaxCopy() : null, objectSyntaxCopy(specAlias), objectSyntaxCopy(defaultAlias));
5575     }
5576 
5577     override bool declareParameter(Scope* sc)
5578     {
5579         auto ti = new TypeIdentifier(loc, ident);
5580         Declaration ad = new AliasDeclaration(loc, ident, ti);
5581         return sc.insert(ad) !is null;
5582     }
5583 
5584     override bool semantic(Scope* sc, TemplateParameters* parameters)
5585     {
5586         if (specType && !reliesOnTident(specType, parameters))
5587         {
5588             specType = specType.semantic(loc, sc);
5589         }
5590         specAlias = aliasParameterSemantic(loc, sc, specAlias, parameters);
5591         version (none)
5592         {
5593             // Don't do semantic() until instantiation
5594             if (defaultAlias)
5595                 defaultAlias = defaultAlias.semantic(loc, sc);
5596         }
5597         return !(specType && isError(specType)) && !(specAlias && isError(specAlias));
5598     }
5599 
5600     override void print(RootObject oarg, RootObject oded)
5601     {
5602         printf(" %s\n", ident.toChars());
5603         Dsymbol sa = isDsymbol(oded);
5604         assert(sa);
5605         printf("\tParameter alias: %s\n", sa.toChars());
5606     }
5607 
5608     override RootObject specialization()
5609     {
5610         return specAlias;
5611     }
5612 
5613     override RootObject defaultArg(Loc instLoc, Scope* sc)
5614     {
5615         RootObject da = defaultAlias;
5616         Type ta = isType(defaultAlias);
5617         if (ta)
5618         {
5619             if (ta.ty == Tinstance)
5620             {
5621                 // If the default arg is a template, instantiate for each type
5622                 da = ta.syntaxCopy();
5623             }
5624         }
5625 
5626         RootObject o = aliasParameterSemantic(loc, sc, da, null); // use the parameter loc
5627         return o;
5628     }
5629 
5630     override bool hasDefaultArg()
5631     {
5632         return defaultAlias !is null;
5633     }
5634 
5635     override MATCH matchArg(Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
5636     {
5637         //printf("TemplateAliasParameter.matchArg('%s')\n", ident.toChars());
5638         MATCH m = MATCHexact;
5639         Type ta = isType(oarg);
5640         RootObject sa = ta && !ta.deco ? null : getDsymbol(oarg);
5641         Expression ea = isExpression(oarg);
5642         if (ea && (ea.op == TOKthis || ea.op == TOKsuper))
5643             sa = (cast(ThisExp)ea).var;
5644         else if (ea && ea.op == TOKscope)
5645             sa = (cast(ScopeExp)ea).sds;
5646         if (sa)
5647         {
5648             if ((cast(Dsymbol)sa).isAggregateDeclaration())
5649                 m = MATCHconvert;
5650 
5651             /* specType means the alias must be a declaration with a type
5652              * that matches specType.
5653              */
5654             if (specType)
5655             {
5656                 Declaration d = (cast(Dsymbol)sa).isDeclaration();
5657                 if (!d)
5658                     goto Lnomatch;
5659                 if (!d.type.equals(specType))
5660                     goto Lnomatch;
5661             }
5662         }
5663         else
5664         {
5665             sa = oarg;
5666             if (ea)
5667             {
5668                 if (specType)
5669                 {
5670                     if (!ea.type.equals(specType))
5671                         goto Lnomatch;
5672                 }
5673             }
5674             else if (ta && ta.ty == Tinstance && !specAlias)
5675             {
5676                 /* Specialized parameter should be preferred
5677                  * match to the template type parameter.
5678                  *  template X(alias a) {}                      // a == this
5679                  *  template X(alias a : B!A, alias B, A...) {} // B!A => ta
5680                  */
5681             }
5682             else if (sa && sa == TemplateTypeParameter.tdummy)
5683             {
5684                 /* https://issues.dlang.org/show_bug.cgi?id=2025
5685                  * Aggregate Types should preferentially
5686                  * match to the template type parameter.
5687                  *  template X(alias a) {}  // a == this
5688                  *  template X(T) {}        // T => sa
5689                  */
5690             }
5691             else
5692                 goto Lnomatch;
5693         }
5694 
5695         if (specAlias)
5696         {
5697             if (sa == sdummy)
5698                 goto Lnomatch;
5699             Dsymbol sx = isDsymbol(sa);
5700             if (sa != specAlias && sx)
5701             {
5702                 Type talias = isType(specAlias);
5703                 if (!talias)
5704                     goto Lnomatch;
5705 
5706                 TemplateInstance ti = sx.isTemplateInstance();
5707                 if (!ti && sx.parent)
5708                 {
5709                     ti = sx.parent.isTemplateInstance();
5710                     if (ti && ti.name != sx.ident)
5711                         goto Lnomatch;
5712                 }
5713                 if (!ti)
5714                     goto Lnomatch;
5715 
5716                 Type t = new TypeInstance(Loc(), ti);
5717                 MATCH m2 = deduceType(t, sc, talias, parameters, dedtypes);
5718                 if (m2 <= MATCHnomatch)
5719                     goto Lnomatch;
5720             }
5721         }
5722         else if ((*dedtypes)[i])
5723         {
5724             // Must match already deduced symbol
5725             RootObject si = (*dedtypes)[i];
5726             if (!sa || si != sa)
5727                 goto Lnomatch;
5728         }
5729         (*dedtypes)[i] = sa;
5730 
5731         if (psparam)
5732         {
5733             if (Dsymbol s = isDsymbol(sa))
5734             {
5735                 *psparam = new AliasDeclaration(loc, ident, s);
5736             }
5737             else if (Type t = isType(sa))
5738             {
5739                 *psparam = new AliasDeclaration(loc, ident, t);
5740             }
5741             else
5742             {
5743                 assert(ea);
5744 
5745                 // Declare manifest constant
5746                 Initializer _init = new ExpInitializer(loc, ea);
5747                 auto v = new VarDeclaration(loc, null, ident, _init);
5748                 v.storage_class = STCmanifest;
5749                 v.semantic(sc);
5750                 *psparam = v;
5751             }
5752         }
5753         return dependent ? MATCHexact : m;
5754 
5755     Lnomatch:
5756         if (psparam)
5757             *psparam = null;
5758         //printf("\tm = %d\n", MATCHnomatch);
5759         return MATCHnomatch;
5760     }
5761 
5762     override void* dummyArg()
5763     {
5764         RootObject s = specAlias;
5765         if (!s)
5766         {
5767             if (!sdummy)
5768                 sdummy = new Dsymbol();
5769             s = sdummy;
5770         }
5771         return cast(void*)s;
5772     }
5773 
5774     override void accept(Visitor v)
5775     {
5776         v.visit(this);
5777     }
5778 }
5779 
5780 /***********************************************************
5781  * Syntax:
5782  *  ident ...
5783  */
5784 extern (C++) final class TemplateTupleParameter : TemplateParameter
5785 {
5786     extern (D) this(Loc loc, Identifier ident)
5787     {
5788         super(loc, ident);
5789         this.ident = ident;
5790     }
5791 
5792     override TemplateTupleParameter isTemplateTupleParameter()
5793     {
5794         return this;
5795     }
5796 
5797     override TemplateParameter syntaxCopy()
5798     {
5799         return new TemplateTupleParameter(loc, ident);
5800     }
5801 
5802     override bool declareParameter(Scope* sc)
5803     {
5804         auto ti = new TypeIdentifier(loc, ident);
5805         Declaration ad = new AliasDeclaration(loc, ident, ti);
5806         return sc.insert(ad) !is null;
5807     }
5808 
5809     override bool semantic(Scope* sc, TemplateParameters* parameters)
5810     {
5811         return true;
5812     }
5813 
5814     override void print(RootObject oarg, RootObject oded)
5815     {
5816         printf(" %s... [", ident.toChars());
5817         Tuple v = isTuple(oded);
5818         assert(v);
5819 
5820         //printf("|%d| ", v.objects.dim);
5821         for (size_t i = 0; i < v.objects.dim; i++)
5822         {
5823             if (i)
5824                 printf(", ");
5825 
5826             RootObject o = v.objects[i];
5827             Dsymbol sa = isDsymbol(o);
5828             if (sa)
5829                 printf("alias: %s", sa.toChars());
5830             Type ta = isType(o);
5831             if (ta)
5832                 printf("type: %s", ta.toChars());
5833             Expression ea = isExpression(o);
5834             if (ea)
5835                 printf("exp: %s", ea.toChars());
5836 
5837             assert(!isTuple(o)); // no nested Tuple arguments
5838         }
5839         printf("]\n");
5840     }
5841 
5842     override RootObject specialization()
5843     {
5844         return null;
5845     }
5846 
5847     override RootObject defaultArg(Loc instLoc, Scope* sc)
5848     {
5849         return null;
5850     }
5851 
5852     override bool hasDefaultArg()
5853     {
5854         return false;
5855     }
5856 
5857     override MATCH matchArg(Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
5858     {
5859         /* The rest of the actual arguments (tiargs[]) form the match
5860          * for the variadic parameter.
5861          */
5862         assert(i + 1 == dedtypes.dim); // must be the last one
5863         Tuple ovar;
5864 
5865         if (Tuple u = isTuple((*dedtypes)[i]))
5866         {
5867             // It has already been deduced
5868             ovar = u;
5869         }
5870         else if (i + 1 == tiargs.dim && isTuple((*tiargs)[i]))
5871             ovar = isTuple((*tiargs)[i]);
5872         else
5873         {
5874             ovar = new Tuple();
5875             //printf("ovar = %p\n", ovar);
5876             if (i < tiargs.dim)
5877             {
5878                 //printf("i = %d, tiargs.dim = %d\n", i, tiargs.dim);
5879                 ovar.objects.setDim(tiargs.dim - i);
5880                 for (size_t j = 0; j < ovar.objects.dim; j++)
5881                     ovar.objects[j] = (*tiargs)[i + j];
5882             }
5883         }
5884         return matchArg(sc, ovar, i, parameters, dedtypes, psparam);
5885     }
5886 
5887     override MATCH matchArg(Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
5888     {
5889         //printf("TemplateTupleParameter.matchArg('%s')\n", ident.toChars());
5890         Tuple ovar = isTuple(oarg);
5891         if (!ovar)
5892             return MATCHnomatch;
5893         if ((*dedtypes)[i])
5894         {
5895             Tuple tup = isTuple((*dedtypes)[i]);
5896             if (!tup)
5897                 return MATCHnomatch;
5898             if (!match(tup, ovar))
5899                 return MATCHnomatch;
5900         }
5901         (*dedtypes)[i] = ovar;
5902 
5903         if (psparam)
5904             *psparam = new TupleDeclaration(loc, ident, &ovar.objects);
5905         return dependent ? MATCHexact : MATCHconvert;
5906     }
5907 
5908     override void* dummyArg()
5909     {
5910         return null;
5911     }
5912 
5913     override void accept(Visitor v)
5914     {
5915         v.visit(this);
5916     }
5917 }
5918 
5919 /***********************************************************
5920  * Given:
5921  *  foo!(args) =>
5922  *      name = foo
5923  *      tiargs = args
5924  */
5925 extern (C++) class TemplateInstance : ScopeDsymbol
5926 {
5927     Identifier name;
5928 
5929     // Array of Types/Expressions of template
5930     // instance arguments [int*, char, 10*10]
5931     Objects* tiargs;
5932 
5933     // Array of Types/Expressions corresponding
5934     // to TemplateDeclaration.parameters
5935     // [int, char, 100]
5936     Objects tdtypes;
5937 
5938     Dsymbol tempdecl;           // referenced by foo.bar.abc
5939     Dsymbol enclosing;          // if referencing local symbols, this is the context
5940     Dsymbol aliasdecl;          // !=null if instance is an alias for its sole member
5941     TemplateInstance inst;      // refer to existing instance
5942     ScopeDsymbol argsym;        // argument symbol table
5943     int inuse;                  // for recursive expansion detection
5944     int nest;                   // for recursive pretty printing detection
5945     bool semantictiargsdone;    // has semanticTiargs() been done?
5946     bool havetempdecl;          // if used second constructor
5947     bool gagged;                // if the instantiation is done with error gagging
5948     hash_t hash;                // cached result of toHash()
5949     Expressions* fargs;         // for function template, these are the function arguments
5950 
5951     TemplateInstances* deferred;
5952 
5953     Module memberOf;            // if !null, then this TemplateInstance appears in memberOf.members[]
5954 
5955     // Used to determine the instance needs code generation.
5956     // Note that these are inaccurate until semantic analysis phase completed.
5957     TemplateInstance tinst;     // enclosing template instance
5958     TemplateInstance tnext;     // non-first instantiated instances
5959     Module minst;               // the top module that instantiated this instance
5960 
5961     final extern (D) this(Loc loc, Identifier ident, Objects* tiargs)
5962     {
5963         super(null);
5964         static if (LOG)
5965         {
5966             printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident.toChars() : "null");
5967         }
5968         this.loc = loc;
5969         this.name = ident;
5970         this.tiargs = tiargs;
5971     }
5972 
5973     /*****************
5974      * This constructor is only called when we figured out which function
5975      * template to instantiate.
5976      */
5977     final extern (D) this(Loc loc, TemplateDeclaration td, Objects* tiargs)
5978     {
5979         super(null);
5980         static if (LOG)
5981         {
5982             printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td.toChars());
5983         }
5984         this.loc = loc;
5985         this.name = td.ident;
5986         this.tiargs = tiargs;
5987         this.tempdecl = td;
5988         this.semantictiargsdone = true;
5989         this.havetempdecl = true;
5990         assert(tempdecl._scope);
5991     }
5992 
5993     static Objects* arraySyntaxCopy(Objects* objs)
5994     {
5995         Objects* a = null;
5996         if (objs)
5997         {
5998             a = new Objects();
5999             a.setDim(objs.dim);
6000             for (size_t i = 0; i < objs.dim; i++)
6001                 (*a)[i] = objectSyntaxCopy((*objs)[i]);
6002         }
6003         return a;
6004     }
6005 
6006     override Dsymbol syntaxCopy(Dsymbol s)
6007     {
6008         TemplateInstance ti = s ? cast(TemplateInstance)s : new TemplateInstance(loc, name, null);
6009         ti.tiargs = arraySyntaxCopy(tiargs);
6010         TemplateDeclaration td;
6011         if (inst && tempdecl && (td = tempdecl.isTemplateDeclaration()) !is null)
6012             td.ScopeDsymbol.syntaxCopy(ti);
6013         else
6014             ScopeDsymbol.syntaxCopy(ti);
6015         return ti;
6016     }
6017 
6018     void semantic(Scope* sc, Expressions* fargs)
6019     {
6020         //printf("[%s] TemplateInstance.semantic('%s', this=%p, gag = %d, sc = %p)\n", loc.toChars(), toChars(), this, global.gag, sc);
6021         version (none)
6022         {
6023             for (Dsymbol s = this; s; s = s.parent)
6024             {
6025                 printf("\t%s\n", s.toChars());
6026             }
6027             printf("Scope\n");
6028             for (Scope* scx = sc; scx; scx = scx.enclosing)
6029             {
6030                 printf("\t%s parent %s\n", scx._module ? scx._module.toChars() : "null", scx.parent ? scx.parent.toChars() : "null");
6031             }
6032         }
6033 
6034         static if (LOG)
6035         {
6036             printf("\n+TemplateInstance.semantic('%s', this=%p)\n", toChars(), this);
6037         }
6038         if (inst) // if semantic() was already run
6039         {
6040             static if (LOG)
6041             {
6042                 printf("-TemplateInstance.semantic('%s', this=%p) already run\n", inst.toChars(), inst);
6043             }
6044             return;
6045         }
6046         if (semanticRun != PASSinit)
6047         {
6048             static if (LOG)
6049             {
6050                 printf("Recursive template expansion\n");
6051             }
6052             auto ungag = Ungag(global.gag);
6053             if (!gagged)
6054                 global.gag = 0;
6055             error(loc, "recursive template expansion");
6056             if (gagged)
6057                 semanticRun = PASSinit;
6058             else
6059                 inst = this;
6060             errors = true;
6061             return;
6062         }
6063 
6064         // Get the enclosing template instance from the scope tinst
6065         tinst = sc.tinst;
6066 
6067         // Get the instantiating module from the scope minst
6068         minst = sc.minst;
6069         // https://issues.dlang.org/show_bug.cgi?id=10920
6070         // If the enclosing function is non-root symbol,
6071         // this instance should be speculative.
6072         if (!tinst && sc.func && sc.func.inNonRoot())
6073         {
6074             minst = null;
6075         }
6076 
6077         gagged = (global.gag > 0);
6078 
6079         semanticRun = PASSsemantic;
6080 
6081         static if (LOG)
6082         {
6083             printf("\tdo semantic\n");
6084         }
6085         /* Find template declaration first,
6086          * then run semantic on each argument (place results in tiargs[]),
6087          * last find most specialized template from overload list/set.
6088          */
6089         if (!findTempDecl(sc, null) || !semanticTiargs(sc) || !findBestMatch(sc, fargs))
6090         {
6091         Lerror:
6092             if (gagged)
6093             {
6094                 // https://issues.dlang.org/show_bug.cgi?id=13220
6095                 // Roll back status for later semantic re-running
6096                 semanticRun = PASSinit;
6097             }
6098             else
6099                 inst = this;
6100             errors = true;
6101             return;
6102         }
6103         TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
6104         assert(tempdecl);
6105 
6106         // If tempdecl is a mixin, disallow it
6107         if (tempdecl.ismixin)
6108         {
6109             error("mixin templates are not regular templates");
6110             goto Lerror;
6111         }
6112 
6113         hasNestedArgs(tiargs, tempdecl.isstatic);
6114         if (errors)
6115             goto Lerror;
6116 
6117         /* See if there is an existing TemplateInstantiation that already
6118          * implements the typeargs. If so, just refer to that one instead.
6119          */
6120         inst = tempdecl.findExistingInstance(this, fargs);
6121         TemplateInstance errinst = null;
6122         if (!inst)
6123         {
6124             // So, we need to implement 'this' instance.
6125         }
6126         else if (inst.gagged && !gagged && inst.errors)
6127         {
6128             // If the first instantiation had failed, re-run semantic,
6129             // so that error messages are shown.
6130             errinst = inst;
6131         }
6132         else
6133         {
6134             // It's a match
6135             parent = inst.parent;
6136             errors = inst.errors;
6137 
6138             // If both this and the previous instantiation were gagged,
6139             // use the number of errors that happened last time.
6140             global.errors += errors;
6141             global.gaggedErrors += errors;
6142 
6143             // If the first instantiation was gagged, but this is not:
6144             if (inst.gagged)
6145             {
6146                 // It had succeeded, mark it is a non-gagged instantiation,
6147                 // and reuse it.
6148                 inst.gagged = gagged;
6149             }
6150 
6151             this.tnext = inst.tnext;
6152             inst.tnext = this;
6153 
6154             /* A module can have explicit template instance and its alias
6155              * in module scope (e,g, `alias Base64 = Base64Impl!('+', '/');`).
6156              * If the first instantiation 'inst' had happened in non-root module,
6157              * compiler can assume that its instantiated code would be included
6158              * in the separately compiled obj/lib file (e.g. phobos.lib).
6159              *
6160              * However, if 'this' second instantiation happened in root module,
6161              * compiler might need to invoke its codegen
6162              * (https://issues.dlang.org/show_bug.cgi?id=2500 & https://issues.dlang.org/show_bug.cgi?id=2644).
6163              * But whole import graph is not determined until all semantic pass finished,
6164              * so 'inst' should conservatively finish the semantic3 pass for the codegen.
6165              */
6166             if (minst && minst.isRoot() && !(inst.minst && inst.minst.isRoot()))
6167             {
6168                 /* Swap the position of 'inst' and 'this' in the instantiation graph.
6169                  * Then, the primary instance `inst` will be changed to a root instance.
6170                  *
6171                  * Before:
6172                  *  non-root -> A!() -> B!()[inst] -> C!()
6173                  *                      |
6174                  *  root     -> D!() -> B!()[this]
6175                  *
6176                  * After:
6177                  *  non-root -> A!() -> B!()[this]
6178                  *                      |
6179                  *  root     -> D!() -> B!()[inst] -> C!()
6180                  */
6181                 Module mi = minst;
6182                 TemplateInstance ti = tinst;
6183                 minst = inst.minst;
6184                 tinst = inst.tinst;
6185                 inst.minst = mi;
6186                 inst.tinst = ti;
6187 
6188                 if (minst) // if inst was not speculative
6189                 {
6190                     /* Add 'inst' once again to the root module members[], then the
6191                      * instance members will get codegen chances.
6192                      */
6193                     inst.appendToModuleMember();
6194                 }
6195             }
6196             static if (LOG)
6197             {
6198                 printf("\tit's a match with instance %p, %d\n", inst, inst.semanticRun);
6199             }
6200             return;
6201         }
6202         static if (LOG)
6203         {
6204             printf("\timplement template instance %s '%s'\n", tempdecl.parent.toChars(), toChars());
6205             printf("\ttempdecl %s\n", tempdecl.toChars());
6206         }
6207         uint errorsave = global.errors;
6208 
6209         inst = this;
6210         parent = enclosing ? enclosing : tempdecl.parent;
6211         //printf("parent = '%s'\n", parent.kind());
6212 
6213         TemplateInstance tempdecl_instance_idx = tempdecl.addInstance(this);
6214 
6215         //getIdent();
6216 
6217         // Store the place we added it to in target_symbol_list(_idx) so we can
6218         // remove it later if we encounter an error.
6219         Dsymbols* target_symbol_list = appendToModuleMember();
6220         size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list.dim - 1 : 0;
6221 
6222         // Copy the syntax trees from the TemplateDeclaration
6223         members = Dsymbol.arraySyntaxCopy(tempdecl.members);
6224 
6225         // resolve TemplateThisParameter
6226         for (size_t i = 0; i < tempdecl.parameters.dim; i++)
6227         {
6228             if ((*tempdecl.parameters)[i].isTemplateThisParameter() is null)
6229                 continue;
6230             Type t = isType((*tiargs)[i]);
6231             assert(t);
6232             if (StorageClass stc = ModToStc(t.mod))
6233             {
6234                 //printf("t = %s, stc = x%llx\n", t.toChars(), stc);
6235                 auto s = new Dsymbols();
6236                 s.push(new StorageClassDeclaration(stc, members));
6237                 members = s;
6238             }
6239             break;
6240         }
6241 
6242         // Create our own scope for the template parameters
6243         Scope* _scope = tempdecl._scope;
6244         if (tempdecl.semanticRun == PASSinit)
6245         {
6246             error("template instantiation %s forward references template declaration %s", toChars(), tempdecl.toChars());
6247             return;
6248         }
6249 
6250         static if (LOG)
6251         {
6252             printf("\tcreate scope for template parameters '%s'\n", toChars());
6253         }
6254         argsym = new ScopeDsymbol();
6255         argsym.parent = _scope.parent;
6256         _scope = _scope.push(argsym);
6257         _scope.tinst = this;
6258         _scope.minst = minst;
6259         //scope.stc = 0;
6260 
6261         // Declare each template parameter as an alias for the argument type
6262         Scope* paramscope = _scope.push();
6263         paramscope.stc = 0;
6264         paramscope.protection = Prot(PROTpublic); // https://issues.dlang.org/show_bug.cgi?id=14169
6265                                                   // template parameters should be public
6266         declareParameters(paramscope);
6267         paramscope.pop();
6268 
6269         // Add members of template instance to template instance symbol table
6270         //parent = scope.scopesym;
6271         symtab = new DsymbolTable();
6272         for (size_t i = 0; i < members.dim; i++)
6273         {
6274             Dsymbol s = (*members)[i];
6275             static if (LOG)
6276             {
6277                 printf("\t[%d] adding member '%s' %p kind %s to '%s'\n", i, s.toChars(), s, s.kind(), this.toChars());
6278             }
6279             s.addMember(_scope, this);
6280         }
6281         static if (LOG)
6282         {
6283             printf("adding members done\n");
6284         }
6285 
6286         /* See if there is only one member of template instance, and that
6287          * member has the same name as the template instance.
6288          * If so, this template instance becomes an alias for that member.
6289          */
6290         //printf("members.dim = %d\n", members.dim);
6291         if (members.dim)
6292         {
6293             Dsymbol s;
6294             if (Dsymbol.oneMembers(members, &s, tempdecl.ident) && s)
6295             {
6296                 //printf("tempdecl.ident = %s, s = '%s'\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
6297                 //printf("setting aliasdecl\n");
6298                 aliasdecl = s;
6299             }
6300         }
6301 
6302         /* If function template declaration
6303          */
6304         if (fargs && aliasdecl)
6305         {
6306             FuncDeclaration fd = aliasdecl.isFuncDeclaration();
6307             if (fd)
6308             {
6309                 /* Transmit fargs to type so that TypeFunction.semantic() can
6310                  * resolve any "auto ref" storage classes.
6311                  */
6312                 TypeFunction tf = cast(TypeFunction)fd.type;
6313                 if (tf && tf.ty == Tfunction)
6314                     tf.fargs = fargs;
6315             }
6316         }
6317 
6318         // Do semantic() analysis on template instance members
6319         static if (LOG)
6320         {
6321             printf("\tdo semantic() on template instance members '%s'\n", toChars());
6322         }
6323         Scope* sc2;
6324         sc2 = _scope.push(this);
6325         //printf("enclosing = %d, sc.parent = %s\n", enclosing, sc.parent.toChars());
6326         sc2.parent = this;
6327         sc2.tinst = this;
6328         sc2.minst = minst;
6329 
6330         tryExpandMembers(sc2);
6331 
6332         semanticRun = PASSsemanticdone;
6333 
6334         /* ConditionalDeclaration may introduce eponymous declaration,
6335          * so we should find it once again after semantic.
6336          */
6337         if (members.dim)
6338         {
6339             Dsymbol s;
6340             if (Dsymbol.oneMembers(members, &s, tempdecl.ident) && s)
6341             {
6342                 if (!aliasdecl || aliasdecl != s)
6343                 {
6344                     //printf("tempdecl.ident = %s, s = '%s'\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
6345                     //printf("setting aliasdecl 2\n");
6346                     aliasdecl = s;
6347                 }
6348             }
6349         }
6350 
6351         if (global.errors != errorsave)
6352             goto Laftersemantic;
6353 
6354         /* If any of the instantiation members didn't get semantic() run
6355          * on them due to forward references, we cannot run semantic2()
6356          * or semantic3() yet.
6357          */
6358         {
6359             bool found_deferred_ad = false;
6360             for (size_t i = 0; i < Module.deferred.dim; i++)
6361             {
6362                 Dsymbol sd = Module.deferred[i];
6363                 AggregateDeclaration ad = sd.isAggregateDeclaration();
6364                 if (ad && ad.parent && ad.parent.isTemplateInstance())
6365                 {
6366                     //printf("deferred template aggregate: %s %s\n",
6367                     //        sd.parent.toChars(), sd.toChars());
6368                     found_deferred_ad = true;
6369                     if (ad.parent == this)
6370                     {
6371                         ad.deferred = this;
6372                         break;
6373                     }
6374                 }
6375             }
6376             if (found_deferred_ad || Module.deferred.dim)
6377                 goto Laftersemantic;
6378         }
6379 
6380         /* The problem is when to parse the initializer for a variable.
6381          * Perhaps VarDeclaration.semantic() should do it like it does
6382          * for initializers inside a function.
6383          */
6384         //if (sc.parent.isFuncDeclaration())
6385         {
6386             /* https://issues.dlang.org/show_bug.cgi?id=782
6387              * this has problems if the classes this depends on
6388              * are forward referenced. Find a way to defer semantic()
6389              * on this template.
6390              */
6391             semantic2(sc2);
6392         }
6393         if (global.errors != errorsave)
6394             goto Laftersemantic;
6395 
6396         if ((sc.func || (sc.flags & SCOPEfullinst)) && !tinst)
6397         {
6398             /* If a template is instantiated inside function, the whole instantiation
6399              * should be done at that position. But, immediate running semantic3 of
6400              * dependent templates may cause unresolved forward reference.
6401              * https://issues.dlang.org/show_bug.cgi?id=9050
6402              * To avoid the issue, don't run semantic3 until semantic and semantic2 done.
6403              */
6404             TemplateInstances deferred;
6405             this.deferred = &deferred;
6406 
6407             //printf("Run semantic3 on %s\n", toChars());
6408             trySemantic3(sc2);
6409 
6410             for (size_t i = 0; i < deferred.dim; i++)
6411             {
6412                 //printf("+ run deferred semantic3 on %s\n", deferred[i].toChars());
6413                 deferred[i].semantic3(null);
6414             }
6415 
6416             this.deferred = null;
6417         }
6418         else if (tinst)
6419         {
6420             bool doSemantic3 = false;
6421             if (sc.func && aliasdecl && aliasdecl.toAlias().isFuncDeclaration())
6422             {
6423                 /* Template function instantiation should run semantic3 immediately
6424                  * for attribute inference.
6425                  */
6426                 doSemantic3 = true;
6427             }
6428             else if (sc.func)
6429             {
6430                 /* A lambda function in template arguments might capture the
6431                  * instantiated scope context. For the correct context inference,
6432                  * all instantiated functions should run the semantic3 immediately.
6433                  * See also compilable/test14973.d
6434                  */
6435                 foreach (oarg; tdtypes)
6436                 {
6437                     auto s = getDsymbol(oarg);
6438                     if (!s)
6439                         continue;
6440 
6441                     if (auto td = s.isTemplateDeclaration())
6442                     {
6443                         if (!td.literal)
6444                             continue;
6445                         assert(td.members && td.members.dim == 1);
6446                         s = (*td.members)[0];
6447                     }
6448                     if (auto fld = s.isFuncLiteralDeclaration())
6449                     {
6450                         if (fld.tok == TOKreserved)
6451                         {
6452                             doSemantic3 = true;
6453                             break;
6454                         }
6455                     }
6456                 }
6457                 //printf("[%s] %s doSemantic3 = %d\n", loc.toChars(), toChars(), doSemantic3);
6458             }
6459             if (doSemantic3)
6460                 trySemantic3(sc2);
6461 
6462             TemplateInstance ti = tinst;
6463             int nest = 0;
6464             while (ti && !ti.deferred && ti.tinst)
6465             {
6466                 ti = ti.tinst;
6467                 if (++nest > 500)
6468                 {
6469                     global.gag = 0; // ensure error message gets printed
6470                     error("recursive expansion");
6471                     fatal();
6472                 }
6473             }
6474             if (ti && ti.deferred)
6475             {
6476                 //printf("deferred semantic3 of %p %s, ti = %s, ti.deferred = %p\n", this, toChars(), ti.toChars());
6477                 for (size_t i = 0;; i++)
6478                 {
6479                     if (i == ti.deferred.dim)
6480                     {
6481                         ti.deferred.push(this);
6482                         break;
6483                     }
6484                     if ((*ti.deferred)[i] == this)
6485                         break;
6486                 }
6487             }
6488         }
6489 
6490         if (aliasdecl)
6491         {
6492             /* https://issues.dlang.org/show_bug.cgi?id=13816
6493              * AliasDeclaration tries to resolve forward reference
6494              * twice (See inuse check in AliasDeclaration.toAlias()). It's
6495              * necessary to resolve mutual references of instantiated symbols, but
6496              * it will left a true recursive alias in tuple declaration - an
6497              * AliasDeclaration A refers TupleDeclaration B, and B contains A
6498              * in its elements.  To correctly make it an error, we strictly need to
6499              * resolve the alias of eponymous member.
6500              */
6501             aliasdecl = aliasdecl.toAlias2();
6502         }
6503 
6504     Laftersemantic:
6505         sc2.pop();
6506         _scope.pop();
6507 
6508         // Give additional context info if error occurred during instantiation
6509         if (global.errors != errorsave)
6510         {
6511             if (!errors)
6512             {
6513                 if (!tempdecl.literal)
6514                     error(loc, "error instantiating");
6515                 if (tinst)
6516                     tinst.printInstantiationTrace();
6517             }
6518             errors = true;
6519             if (gagged)
6520             {
6521                 // Errors are gagged, so remove the template instance from the
6522                 // instance/symbol lists we added it to and reset our state to
6523                 // finish clean and so we can try to instantiate it again later
6524                 // (see https://issues.dlang.org/show_bug.cgi?id=4302 and https://issues.dlang.org/show_bug.cgi?id=6602).
6525                 tempdecl.removeInstance(tempdecl_instance_idx);
6526                 if (target_symbol_list)
6527                 {
6528                     // Because we added 'this' in the last position above, we
6529                     // should be able to remove it without messing other indices up.
6530                     assert((*target_symbol_list)[target_symbol_list_idx] == this);
6531                     target_symbol_list.remove(target_symbol_list_idx);
6532                     memberOf = null;                    // no longer a member
6533                 }
6534                 semanticRun = PASSinit;
6535                 inst = null;
6536                 symtab = null;
6537             }
6538         }
6539         else if (errinst)
6540         {
6541             /* https://issues.dlang.org/show_bug.cgi?id=14541
6542              * If the previous gagged instance had failed by
6543              * circular references, currrent "error reproduction instantiation"
6544              * might succeed, because of the difference of instantiated context.
6545              * On such case, the cached error instance needs to be overridden by the
6546              * succeeded instance.
6547              */
6548             //printf("replaceInstance()\n");
6549             assert(errinst.errors);
6550             auto ti1 = TemplateInstanceBox(errinst);
6551             tempdecl.instances.remove(ti1);
6552 
6553             auto ti2 = TemplateInstanceBox(this);
6554             tempdecl.instances[ti2] = this;
6555         }
6556 
6557         static if (LOG)
6558         {
6559             printf("-TemplateInstance.semantic('%s', this=%p)\n", toChars(), this);
6560         }
6561     }
6562 
6563     override void semantic(Scope* sc)
6564     {
6565         semantic(sc, null);
6566     }
6567 
6568     override void semantic2(Scope* sc)
6569     {
6570         if (semanticRun >= PASSsemantic2)
6571             return;
6572         semanticRun = PASSsemantic2;
6573         static if (LOG)
6574         {
6575             printf("+TemplateInstance.semantic2('%s')\n", toChars());
6576         }
6577         if (!errors && members)
6578         {
6579             TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
6580             assert(tempdecl);
6581 
6582             sc = tempdecl._scope;
6583             assert(sc);
6584             sc = sc.push(argsym);
6585             sc = sc.push(this);
6586             sc.tinst = this;
6587             sc.minst = minst;
6588 
6589             int needGagging = (gagged && !global.gag);
6590             uint olderrors = global.errors;
6591             int oldGaggedErrors = -1; // dead-store to prevent spurious warning
6592             if (needGagging)
6593                 oldGaggedErrors = global.startGagging();
6594 
6595             for (size_t i = 0; i < members.dim; i++)
6596             {
6597                 Dsymbol s = (*members)[i];
6598                 static if (LOG)
6599                 {
6600                     printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
6601                 }
6602                 s.semantic2(sc);
6603                 if (gagged && global.errors != olderrors)
6604                     break;
6605             }
6606 
6607             if (global.errors != olderrors)
6608             {
6609                 if (!errors)
6610                 {
6611                     if (!tempdecl.literal)
6612                         error(loc, "error instantiating");
6613                     if (tinst)
6614                         tinst.printInstantiationTrace();
6615                 }
6616                 errors = true;
6617             }
6618             if (needGagging)
6619                 global.endGagging(oldGaggedErrors);
6620 
6621             sc = sc.pop();
6622             sc.pop();
6623         }
6624         static if (LOG)
6625         {
6626             printf("-TemplateInstance.semantic2('%s')\n", toChars());
6627         }
6628     }
6629 
6630     override void semantic3(Scope* sc)
6631     {
6632         static if (LOG)
6633         {
6634             printf("TemplateInstance.semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
6635         }
6636         //if (toChars()[0] == 'D') *(char*)0=0;
6637         if (semanticRun >= PASSsemantic3)
6638             return;
6639         semanticRun = PASSsemantic3;
6640         if (!errors && members)
6641         {
6642             TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
6643             assert(tempdecl);
6644 
6645             sc = tempdecl._scope;
6646             sc = sc.push(argsym);
6647             sc = sc.push(this);
6648             sc.tinst = this;
6649             sc.minst = minst;
6650 
6651             int needGagging = (gagged && !global.gag);
6652             uint olderrors = global.errors;
6653             int oldGaggedErrors = -1; // dead-store to prevent spurious warning
6654             /* If this is a gagged instantiation, gag errors.
6655              * Future optimisation: If the results are actually needed, errors
6656              * would already be gagged, so we don't really need to run semantic
6657              * on the members.
6658              */
6659             if (needGagging)
6660                 oldGaggedErrors = global.startGagging();
6661 
6662             for (size_t i = 0; i < members.dim; i++)
6663             {
6664                 Dsymbol s = (*members)[i];
6665                 s.semantic3(sc);
6666                 if (gagged && global.errors != olderrors)
6667                     break;
6668             }
6669 
6670             if (global.errors != olderrors)
6671             {
6672                 if (!errors)
6673                 {
6674                     if (!tempdecl.literal)
6675                         error(loc, "error instantiating");
6676                     if (tinst)
6677                         tinst.printInstantiationTrace();
6678                 }
6679                 errors = true;
6680             }
6681             if (needGagging)
6682                 global.endGagging(oldGaggedErrors);
6683 
6684             sc = sc.pop();
6685             sc.pop();
6686         }
6687     }
6688 
6689     // resolve real symbol
6690     override final Dsymbol toAlias()
6691     {
6692         static if (LOG)
6693         {
6694             printf("TemplateInstance.toAlias()\n");
6695         }
6696         if (!inst)
6697         {
6698             // Maybe we can resolve it
6699             if (_scope)
6700             {
6701                 semantic(_scope);
6702             }
6703             if (!inst)
6704             {
6705                 error("cannot resolve forward reference");
6706                 errors = true;
6707                 return this;
6708             }
6709         }
6710 
6711         if (inst != this)
6712             return inst.toAlias();
6713 
6714         if (aliasdecl)
6715         {
6716             return aliasdecl.toAlias();
6717         }
6718 
6719         return inst;
6720     }
6721 
6722     override const(char)* kind() const
6723     {
6724         return "template instance";
6725     }
6726 
6727     override bool oneMember(Dsymbol* ps, Identifier ident)
6728     {
6729         *ps = null;
6730         return true;
6731     }
6732 
6733     override const(char)* toChars()
6734     {
6735         OutBuffer buf;
6736         toCBufferInstance(this, &buf);
6737         return buf.extractString();
6738     }
6739 
6740     override final char* toPrettyCharsHelper()
6741     {
6742         OutBuffer buf;
6743         toCBufferInstance(this, &buf, true);
6744         return buf.extractString();
6745     }
6746 
6747     /**************************************
6748      * Given an error instantiating the TemplateInstance,
6749      * give the nested TemplateInstance instantiations that got
6750      * us here. Those are a list threaded into the nested scopes.
6751      */
6752     final void printInstantiationTrace()
6753     {
6754         if (global.gag)
6755             return;
6756 
6757         const(uint) max_shown = 6;
6758         const(char)* format = "instantiated from here: %s";
6759 
6760         // determine instantiation depth and number of recursive instantiations
6761         int n_instantiations = 1;
6762         int n_totalrecursions = 0;
6763         for (TemplateInstance cur = this; cur; cur = cur.tinst)
6764         {
6765             ++n_instantiations;
6766             // If two instantiations use the same declaration, they are recursive.
6767             // (this works even if they are instantiated from different places in the
6768             // same template).
6769             // In principle, we could also check for multiple-template recursion, but it's
6770             // probably not worthwhile.
6771             if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
6772                 ++n_totalrecursions;
6773         }
6774 
6775         // show full trace only if it's short or verbose is on
6776         if (n_instantiations <= max_shown || global.params.verbose)
6777         {
6778             for (TemplateInstance cur = this; cur; cur = cur.tinst)
6779             {
6780                 cur.errors = true;
6781                 errorSupplemental(cur.loc, format, cur.toChars());
6782             }
6783         }
6784         else if (n_instantiations - n_totalrecursions <= max_shown)
6785         {
6786             // By collapsing recursive instantiations into a single line,
6787             // we can stay under the limit.
6788             int recursionDepth = 0;
6789             for (TemplateInstance cur = this; cur; cur = cur.tinst)
6790             {
6791                 cur.errors = true;
6792                 if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
6793                 {
6794                     ++recursionDepth;
6795                 }
6796                 else
6797                 {
6798                     if (recursionDepth)
6799                         errorSupplemental(cur.loc, "%d recursive instantiations from here: %s", recursionDepth + 2, cur.toChars());
6800                     else
6801                         errorSupplemental(cur.loc, format, cur.toChars());
6802                     recursionDepth = 0;
6803                 }
6804             }
6805         }
6806         else
6807         {
6808             // Even after collapsing the recursions, the depth is too deep.
6809             // Just display the first few and last few instantiations.
6810             uint i = 0;
6811             for (TemplateInstance cur = this; cur; cur = cur.tinst)
6812             {
6813                 cur.errors = true;
6814 
6815                 if (i == max_shown / 2)
6816                     errorSupplemental(cur.loc, "... (%d instantiations, -v to show) ...", n_instantiations - max_shown);
6817 
6818                 if (i < max_shown / 2 || i >= n_instantiations - max_shown + max_shown / 2)
6819                     errorSupplemental(cur.loc, format, cur.toChars());
6820                 ++i;
6821             }
6822         }
6823     }
6824 
6825     /*************************************
6826      * Lazily generate identifier for template instance.
6827      * This is because 75% of the ident's are never needed.
6828      */
6829     override final Identifier getIdent()
6830     {
6831         if (!ident && inst && !errors)
6832             ident = genIdent(tiargs); // need an identifier for name mangling purposes.
6833         return ident;
6834     }
6835 
6836     /*************************************
6837      * Compare proposed template instantiation with existing template instantiation.
6838      * Note that this is not commutative because of the auto ref check.
6839      * Params:
6840      *  this = proposed template instantiation
6841      *  o = existing template instantiation
6842      * Returns:
6843      *  0 for match, 1 for no match
6844      */
6845     override final int compare(RootObject o)
6846     {
6847         TemplateInstance ti = cast(TemplateInstance)o;
6848 
6849         //printf("this = %p, ti = %p\n", this, ti);
6850         assert(tdtypes.dim == ti.tdtypes.dim);
6851 
6852         // Nesting must match
6853         if (enclosing != ti.enclosing)
6854         {
6855             //printf("test2 enclosing %s ti.enclosing %s\n", enclosing ? enclosing.toChars() : "", ti.enclosing ? ti.enclosing.toChars() : "");
6856             goto Lnotequals;
6857         }
6858         //printf("parent = %s, ti.parent = %s\n", parent.toPrettyChars(), ti.parent.toPrettyChars());
6859 
6860         if (!arrayObjectMatch(&tdtypes, &ti.tdtypes))
6861             goto Lnotequals;
6862 
6863         /* Template functions may have different instantiations based on
6864          * "auto ref" parameters.
6865          */
6866         if (auto fd = ti.toAlias().isFuncDeclaration())
6867         {
6868             if (!fd.errors)
6869             {
6870                 auto fparameters = fd.getParameters(null);
6871                 size_t nfparams = Parameter.dim(fparameters);   // Num function parameters
6872                 for (size_t j = 0; j < nfparams; j++)
6873                 {
6874                     Parameter fparam = Parameter.getNth(fparameters, j);
6875                     if (fparam.storageClass & STCautoref)       // if "auto ref"
6876                     {
6877                         if (!fargs)
6878                             goto Lnotequals;
6879                         if (fargs.dim <= j)
6880                             break;
6881                         Expression farg = (*fargs)[j];
6882                         if (farg.isLvalue())
6883                         {
6884                             if (!(fparam.storageClass & STCref))
6885                                 goto Lnotequals; // auto ref's don't match
6886                         }
6887                         else
6888                         {
6889                             if (fparam.storageClass & STCref)
6890                                 goto Lnotequals; // auto ref's don't match
6891                         }
6892                     }
6893                 }
6894             }
6895         }
6896         return 0;
6897 
6898     Lnotequals:
6899         return 1;
6900     }
6901 
6902     final hash_t toHash()
6903     {
6904         if (!hash)
6905         {
6906             hash = cast(size_t)cast(void*)enclosing;
6907             hash += arrayObjectHash(&tdtypes);
6908             hash += hash == 0;
6909         }
6910         return hash;
6911     }
6912 
6913     /***********************************************
6914      * Returns true if this is not instantiated in non-root module, and
6915      * is a part of non-speculative instantiatiation.
6916      *
6917      * Note: minst does not stabilize until semantic analysis is completed,
6918      * so don't call this function during semantic analysis to return precise result.
6919      */
6920     final bool needsCodegen()
6921     {
6922         // Now -allInst is just for the backward compatibility.
6923         if (global.params.allInst)
6924         {
6925             //printf("%s minst = %s, enclosing (%s).isNonRoot = %d\n",
6926             //    toPrettyChars(), minst ? minst.toChars() : NULL,
6927             //    enclosing ? enclosing.toPrettyChars() : NULL, enclosing && enclosing.inNonRoot());
6928             if (enclosing)
6929             {
6930                 /* https://issues.dlang.org/show_bug.cgi?id=14588
6931                  * If the captured context is not a function
6932                  * (e.g. class), the instance layout determination is guaranteed,
6933                  * because the semantic/semantic2 pass will be executed
6934                  * even for non-root instances.
6935                  */
6936                 if (!enclosing.isFuncDeclaration())
6937                     return true;
6938 
6939                 /* https://issues.dlang.org/show_bug.cgi?id=14834
6940                  * If the captured context is a function,
6941                  * this excessive instantiation may cause ODR violation, because
6942                  * -allInst and others doesn't guarantee the semantic3 execution
6943                  * for that function.
6944                  *
6945                  * If the enclosing is also an instantiated function,
6946                  * we have to rely on the ancestor's needsCodegen() result.
6947                  */
6948                 if (TemplateInstance ti = enclosing.isInstantiated())
6949                     return ti.needsCodegen();
6950 
6951                 /* https://issues.dlang.org/show_bug.cgi?id=13415
6952                  * If and only if the enclosing scope needs codegen,
6953                  * this nested templates would also need code generation.
6954                  */
6955                 return !enclosing.inNonRoot();
6956             }
6957             return true;
6958         }
6959 
6960         if (!minst)
6961         {
6962             // If this is a speculative instantiation,
6963             // 1. do codegen if ancestors really needs codegen.
6964             // 2. become non-speculative if siblings are not speculative
6965 
6966             TemplateInstance tnext = this.tnext;
6967             TemplateInstance tinst = this.tinst;
6968             // At first, disconnect chain first to prevent infinite recursion.
6969             this.tnext = null;
6970             this.tinst = null;
6971 
6972             // Determine necessity of tinst before tnext.
6973             if (tinst && tinst.needsCodegen())
6974             {
6975                 minst = tinst.minst; // cache result
6976                 assert(minst);
6977                 assert(minst.isRoot() || minst.rootImports());
6978                 return true;
6979             }
6980             if (tnext && (tnext.needsCodegen() || tnext.minst))
6981             {
6982                 minst = tnext.minst; // cache result
6983                 assert(minst);
6984                 return minst.isRoot() || minst.rootImports();
6985             }
6986 
6987             // Elide codegen because this is really speculative.
6988             return false;
6989         }
6990 
6991         /* Even when this is reached to the codegen pass,
6992          * a non-root nested template should not generate code,
6993          * due to avoid ODR violation.
6994          */
6995         if (enclosing && enclosing.inNonRoot())
6996         {
6997             if (tinst)
6998             {
6999                 auto r = tinst.needsCodegen();
7000                 minst = tinst.minst; // cache result
7001                 return r;
7002             }
7003             if (tnext)
7004             {
7005                 auto r = tnext.needsCodegen();
7006                 minst = tnext.minst; // cache result
7007                 return r;
7008             }
7009             return false;
7010         }
7011 
7012         /* The issue is that if the importee is compiled with a different -debug
7013          * setting than the importer, the importer may believe it exists
7014          * in the compiled importee when it does not, when the instantiation
7015          * is behind a conditional debug declaration.
7016          */
7017         // workaround for https://issues.dlang.org/show_bug.cgi?id=11239
7018         if (global.params.useUnitTests ||
7019             global.params.debuglevel)
7020         {
7021             // Prefer instantiations from root modules, to maximize link-ability.
7022             if (minst.isRoot())
7023                 return true;
7024 
7025             TemplateInstance tnext = this.tnext;
7026             TemplateInstance tinst = this.tinst;
7027             this.tnext = null;
7028             this.tinst = null;
7029 
7030             if (tinst && tinst.needsCodegen())
7031             {
7032                 minst = tinst.minst; // cache result
7033                 assert(minst);
7034                 assert(minst.isRoot() || minst.rootImports());
7035                 return true;
7036             }
7037             if (tnext && tnext.needsCodegen())
7038             {
7039                 minst = tnext.minst; // cache result
7040                 assert(minst);
7041                 assert(minst.isRoot() || minst.rootImports());
7042                 return true;
7043             }
7044 
7045             // https://issues.dlang.org/show_bug.cgi?id=2500 case
7046             if (minst.rootImports())
7047                 return true;
7048 
7049             // Elide codegen because this is not included in root instances.
7050             return false;
7051         }
7052         else
7053         {
7054             // Prefer instantiations from non-root module, to minimize object code size.
7055 
7056             /* If a TemplateInstance is ever instantiated by non-root modules,
7057              * we do not have to generate code for it,
7058              * because it will be generated when the non-root module is compiled.
7059              *
7060              * But, if the non-root 'minst' imports any root modules, it might still need codegen.
7061              *
7062              * The problem is if A imports B, and B imports A, and both A
7063              * and B instantiate the same template, does the compilation of A
7064              * or the compilation of B do the actual instantiation?
7065              *
7066              * See https://issues.dlang.org/show_bug.cgi?id=2500.
7067              */
7068             if (!minst.isRoot() && !minst.rootImports())
7069                 return false;
7070 
7071             TemplateInstance tnext = this.tnext;
7072             this.tnext = null;
7073 
7074             if (tnext && !tnext.needsCodegen() && tnext.minst)
7075             {
7076                 minst = tnext.minst; // cache result
7077                 assert(!minst.isRoot());
7078                 return false;
7079             }
7080 
7081             // Do codegen because this is not included in non-root instances.
7082             return true;
7083         }
7084     }
7085 
7086     /**********************************************
7087      * Find template declaration corresponding to template instance.
7088      *
7089      * Returns:
7090      *      false if finding fails.
7091      * Note:
7092      *      This function is reentrant against error occurrence. If returns false,
7093      *      any members of this object won't be modified, and repetition call will
7094      *      reproduce same error.
7095      */
7096     final bool findTempDecl(Scope* sc, WithScopeSymbol* pwithsym)
7097     {
7098         if (pwithsym)
7099             *pwithsym = null;
7100 
7101         if (havetempdecl)
7102             return true;
7103 
7104         //printf("TemplateInstance.findTempDecl() %s\n", toChars());
7105         if (!tempdecl)
7106         {
7107             /* Given:
7108              *    foo!( ... )
7109              * figure out which TemplateDeclaration foo refers to.
7110              */
7111             Identifier id = name;
7112             Dsymbol scopesym;
7113             Dsymbol s = sc.search(loc, id, &scopesym);
7114             if (!s)
7115             {
7116                 s = sc.search_correct(id);
7117                 if (s)
7118                     error("template '%s' is not defined, did you mean %s?", id.toChars(), s.toChars());
7119                 else
7120                     error("template '%s' is not defined", id.toChars());
7121                 return false;
7122             }
7123             static if (LOG)
7124             {
7125                 printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind());
7126                 if (s.parent)
7127                     printf("s.parent = '%s'\n", s.parent.toChars());
7128             }
7129             if (pwithsym)
7130                 *pwithsym = scopesym.isWithScopeSymbol();
7131 
7132             /* We might have found an alias within a template when
7133              * we really want the template.
7134              */
7135             TemplateInstance ti;
7136             if (s.parent && (ti = s.parent.isTemplateInstance()) !is null)
7137             {
7138                 if (ti.tempdecl && ti.tempdecl.ident == id)
7139                 {
7140                     /* This is so that one can refer to the enclosing
7141                      * template, even if it has the same name as a member
7142                      * of the template, if it has a !(arguments)
7143                      */
7144                     TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
7145                     assert(td);
7146                     if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
7147                         td = td.overroot; // then get the start
7148                     s = td;
7149                 }
7150             }
7151 
7152             if (!updateTempDecl(sc, s))
7153             {
7154                 return false;
7155             }
7156         }
7157         assert(tempdecl);
7158 
7159         // Look for forward references
7160         auto tovers = tempdecl.isOverloadSet();
7161         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
7162         {
7163             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7164             int r = overloadApply(dstart, (Dsymbol s)
7165             {
7166                 auto td = s.isTemplateDeclaration();
7167                 if (!td)
7168                     return 0;
7169 
7170                 if (td.semanticRun == PASSinit)
7171                 {
7172                     if (td._scope)
7173                     {
7174                         // Try to fix forward reference. Ungag errors while doing so.
7175                         Ungag ungag = td.ungagSpeculative();
7176                         td.semantic(td._scope);
7177                     }
7178                     if (td.semanticRun == PASSinit)
7179                     {
7180                         error("%s forward references template declaration %s",
7181                             toChars(), td.toChars());
7182                         return 1;
7183                     }
7184                 }
7185                 return 0;
7186             });
7187             if (r)
7188                 return false;
7189         }
7190         return true;
7191     }
7192 
7193     /**********************************************
7194      * Confirm s is a valid template, then store it.
7195      * Input:
7196      *      sc
7197      *      s   candidate symbol of template. It may be:
7198      *          TemplateDeclaration
7199      *          FuncDeclaration with findTemplateDeclRoot() != NULL
7200      *          OverloadSet which contains candidates
7201      * Returns:
7202      *      true if updating succeeds.
7203      */
7204     final bool updateTempDecl(Scope* sc, Dsymbol s)
7205     {
7206         if (s)
7207         {
7208             Identifier id = name;
7209             s = s.toAlias();
7210 
7211             /* If an OverloadSet, look for a unique member that is a template declaration
7212              */
7213             OverloadSet os = s.isOverloadSet();
7214             if (os)
7215             {
7216                 s = null;
7217                 for (size_t i = 0; i < os.a.dim; i++)
7218                 {
7219                     Dsymbol s2 = os.a[i];
7220                     if (FuncDeclaration f = s2.isFuncDeclaration())
7221                         s2 = f.findTemplateDeclRoot();
7222                     else
7223                         s2 = s2.isTemplateDeclaration();
7224                     if (s2)
7225                     {
7226                         if (s)
7227                         {
7228                             tempdecl = os;
7229                             return true;
7230                         }
7231                         s = s2;
7232                     }
7233                 }
7234                 if (!s)
7235                 {
7236                     error("template '%s' is not defined", id.toChars());
7237                     return false;
7238                 }
7239             }
7240 
7241             OverDeclaration od = s.isOverDeclaration();
7242             if (od)
7243             {
7244                 tempdecl = od; // TODO: more strict check
7245                 return true;
7246             }
7247 
7248             /* It should be a TemplateDeclaration, not some other symbol
7249              */
7250             if (FuncDeclaration f = s.isFuncDeclaration())
7251                 tempdecl = f.findTemplateDeclRoot();
7252             else
7253                 tempdecl = s.isTemplateDeclaration();
7254             if (!tempdecl)
7255             {
7256                 if (!s.parent && global.errors)
7257                     return false;
7258                 if (!s.parent && s.getType())
7259                 {
7260                     Dsymbol s2 = s.getType().toDsymbol(sc);
7261                     if (!s2)
7262                     {
7263                         error("%s is not a template declaration, it is a %s", id.toChars(), s.kind());
7264                         return false;
7265                     }
7266                     s = s2;
7267                 }
7268                 debug
7269                 {
7270                     //if (!s.parent) printf("s = %s %s\n", s.kind(), s.toChars());
7271                 }
7272                 //assert(s.parent);
7273                 TemplateInstance ti = s.parent ? s.parent.isTemplateInstance() : null;
7274                 if (ti && (ti.name == s.ident || ti.toAlias().ident == s.ident) && ti.tempdecl)
7275                 {
7276                     /* This is so that one can refer to the enclosing
7277                      * template, even if it has the same name as a member
7278                      * of the template, if it has a !(arguments)
7279                      */
7280                     TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
7281                     assert(td);
7282                     if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
7283                         td = td.overroot; // then get the start
7284                     tempdecl = td;
7285                 }
7286                 else
7287                 {
7288                     error("%s is not a template declaration, it is a %s", id.toChars(), s.kind());
7289                     return false;
7290                 }
7291             }
7292         }
7293         return (tempdecl !is null);
7294     }
7295 
7296     /**********************************
7297      * Run semantic of tiargs as arguments of template.
7298      * Input:
7299      *      loc
7300      *      sc
7301      *      tiargs  array of template arguments
7302      *      flags   1: replace const variables with their initializers
7303      *              2: don't devolve Parameter to Type
7304      * Returns:
7305      *      false if one or more arguments have errors.
7306      */
7307     static bool semanticTiargs(Loc loc, Scope* sc, Objects* tiargs, int flags)
7308     {
7309         // Run semantic on each argument, place results in tiargs[]
7310         //printf("+TemplateInstance.semanticTiargs()\n");
7311         if (!tiargs)
7312             return true;
7313         bool err = false;
7314         for (size_t j = 0; j < tiargs.dim; j++)
7315         {
7316             RootObject o = (*tiargs)[j];
7317             Type ta = isType(o);
7318             Expression ea = isExpression(o);
7319             Dsymbol sa = isDsymbol(o);
7320 
7321             //printf("1: (*tiargs)[%d] = %p, s=%p, v=%p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
7322             if (ta)
7323             {
7324                 //printf("type %s\n", ta.toChars());
7325                 // It might really be an Expression or an Alias
7326                 ta.resolve(loc, sc, &ea, &ta, &sa);
7327                 if (ea)
7328                     goto Lexpr;
7329                 if (sa)
7330                     goto Ldsym;
7331                 if (ta is null)
7332                 {
7333                     assert(global.errors);
7334                     ta = Type.terror;
7335                 }
7336 
7337             Ltype:
7338                 if (ta.ty == Ttuple)
7339                 {
7340                     // Expand tuple
7341                     TypeTuple tt = cast(TypeTuple)ta;
7342                     size_t dim = tt.arguments.dim;
7343                     tiargs.remove(j);
7344                     if (dim)
7345                     {
7346                         tiargs.reserve(dim);
7347                         for (size_t i = 0; i < dim; i++)
7348                         {
7349                             Parameter arg = (*tt.arguments)[i];
7350                             if (flags & 2 && arg.ident)
7351                                 tiargs.insert(j + i, arg);
7352                             else
7353                                 tiargs.insert(j + i, arg.type);
7354                         }
7355                     }
7356                     j--;
7357                     continue;
7358                 }
7359                 if (ta.ty == Terror)
7360                 {
7361                     err = true;
7362                     continue;
7363                 }
7364                 (*tiargs)[j] = ta.merge2();
7365             }
7366             else if (ea)
7367             {
7368             Lexpr:
7369                 //printf("+[%d] ea = %s %s\n", j, Token.toChars(ea.op), ea.toChars());
7370                 if (flags & 1) // only used by __traits
7371                 {
7372                     ea = ea.semantic(sc);
7373 
7374                     // must not interpret the args, excepting template parameters
7375                     if (ea.op != TOKvar || ((cast(VarExp)ea).var.storage_class & STCtemplateparameter))
7376                     {
7377                         ea = ea.optimize(WANTvalue);
7378                     }
7379                 }
7380                 else
7381                 {
7382                     sc = sc.startCTFE();
7383                     ea = ea.semantic(sc);
7384                     sc = sc.endCTFE();
7385 
7386                     if (ea.op == TOKvar)
7387                     {
7388                         /* This test is to skip substituting a const var with
7389                          * its initializer. The problem is the initializer won't
7390                          * match with an 'alias' parameter. Instead, do the
7391                          * const substitution in TemplateValueParameter.matchArg().
7392                          */
7393                     }
7394                     else if (definitelyValueParameter(ea))
7395                     {
7396                         if (ea.checkValue()) // check void expression
7397                             ea = new ErrorExp();
7398                         uint olderrs = global.errors;
7399                         ea = ea.ctfeInterpret();
7400                         if (global.errors != olderrs)
7401                             ea = new ErrorExp();
7402                     }
7403                 }
7404                 //printf("-[%d] ea = %s %s\n", j, Token.toChars(ea.op), ea.toChars());
7405                 if (ea.op == TOKtuple)
7406                 {
7407                     // Expand tuple
7408                     TupleExp te = cast(TupleExp)ea;
7409                     size_t dim = te.exps.dim;
7410                     tiargs.remove(j);
7411                     if (dim)
7412                     {
7413                         tiargs.reserve(dim);
7414                         for (size_t i = 0; i < dim; i++)
7415                             tiargs.insert(j + i, (*te.exps)[i]);
7416                     }
7417                     j--;
7418                     continue;
7419                 }
7420                 if (ea.op == TOKerror)
7421                 {
7422                     err = true;
7423                     continue;
7424                 }
7425                 (*tiargs)[j] = ea;
7426 
7427                 if (ea.op == TOKtype)
7428                 {
7429                     ta = ea.type;
7430                     goto Ltype;
7431                 }
7432                 if (ea.op == TOKscope)
7433                 {
7434                     sa = (cast(ScopeExp)ea).sds;
7435                     goto Ldsym;
7436                 }
7437                 if (ea.op == TOKfunction)
7438                 {
7439                     FuncExp fe = cast(FuncExp)ea;
7440                     /* A function literal, that is passed to template and
7441                      * already semanticed as function pointer, never requires
7442                      * outer frame. So convert it to global function is valid.
7443                      */
7444                     if (fe.fd.tok == TOKreserved && fe.type.ty == Tpointer)
7445                     {
7446                         // change to non-nested
7447                         fe.fd.tok = TOKfunction;
7448                         fe.fd.vthis = null;
7449                     }
7450                     else if (fe.td)
7451                     {
7452                         /* If template argument is a template lambda,
7453                          * get template declaration itself. */
7454                         //sa = fe.td;
7455                         //goto Ldsym;
7456                     }
7457                 }
7458                 if (ea.op == TOKdotvar)
7459                 {
7460                     // translate expression to dsymbol.
7461                     sa = (cast(DotVarExp)ea).var;
7462                     goto Ldsym;
7463                 }
7464                 if (ea.op == TOKtemplate)
7465                 {
7466                     sa = (cast(TemplateExp)ea).td;
7467                     goto Ldsym;
7468                 }
7469                 if (ea.op == TOKdottd)
7470                 {
7471                     // translate expression to dsymbol.
7472                     sa = (cast(DotTemplateExp)ea).td;
7473                     goto Ldsym;
7474                 }
7475             }
7476             else if (sa)
7477             {
7478             Ldsym:
7479                 //printf("dsym %s %s\n", sa.kind(), sa.toChars());
7480                 if (sa.errors)
7481                 {
7482                     err = true;
7483                     continue;
7484                 }
7485 
7486                 TupleDeclaration d = sa.toAlias().isTupleDeclaration();
7487                 if (d)
7488                 {
7489                     // Expand tuple
7490                     tiargs.remove(j);
7491                     tiargs.insert(j, d.objects);
7492                     j--;
7493                     continue;
7494                 }
7495                 if (FuncAliasDeclaration fa = sa.isFuncAliasDeclaration())
7496                 {
7497                     FuncDeclaration f = fa.toAliasFunc();
7498                     if (!fa.hasOverloads && f.isUnique())
7499                     {
7500                         // Strip FuncAlias only when the aliased function
7501                         // does not have any overloads.
7502                         sa = f;
7503                     }
7504                 }
7505                 (*tiargs)[j] = sa;
7506 
7507                 TemplateDeclaration td = sa.isTemplateDeclaration();
7508                 if (td && td.semanticRun == PASSinit && td.literal)
7509                 {
7510                     td.semantic(sc);
7511                 }
7512                 FuncDeclaration fd = sa.isFuncDeclaration();
7513                 if (fd)
7514                     fd.functionSemantic();
7515             }
7516             else if (isParameter(o))
7517             {
7518             }
7519             else
7520             {
7521                 assert(0);
7522             }
7523             //printf("1: (*tiargs)[%d] = %p\n", j, (*tiargs)[j]);
7524         }
7525         version (none)
7526         {
7527             printf("-TemplateInstance.semanticTiargs()\n");
7528             for (size_t j = 0; j < tiargs.dim; j++)
7529             {
7530                 RootObject o = (*tiargs)[j];
7531                 Type ta = isType(o);
7532                 Expression ea = isExpression(o);
7533                 Dsymbol sa = isDsymbol(o);
7534                 Tuple va = isTuple(o);
7535                 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
7536             }
7537         }
7538         return !err;
7539     }
7540 
7541     /**********************************
7542      * Run semantic on the elements of tiargs.
7543      * Input:
7544      *      sc
7545      * Returns:
7546      *      false if one or more arguments have errors.
7547      * Note:
7548      *      This function is reentrant against error occurrence. If returns false,
7549      *      all elements of tiargs won't be modified.
7550      */
7551     final bool semanticTiargs(Scope* sc)
7552     {
7553         //printf("+TemplateInstance.semanticTiargs() %s\n", toChars());
7554         if (semantictiargsdone)
7555             return true;
7556         if (semanticTiargs(loc, sc, tiargs, 0))
7557         {
7558             // cache the result iff semantic analysis succeeded entirely
7559             semantictiargsdone = 1;
7560             return true;
7561         }
7562         return false;
7563     }
7564 
7565     final bool findBestMatch(Scope* sc, Expressions* fargs)
7566     {
7567         if (havetempdecl)
7568         {
7569             TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
7570             assert(tempdecl);
7571             assert(tempdecl._scope);
7572             // Deduce tdtypes
7573             tdtypes.setDim(tempdecl.parameters.dim);
7574             if (!tempdecl.matchWithInstance(sc, this, &tdtypes, fargs, 2))
7575             {
7576                 error("incompatible arguments for template instantiation");
7577                 return false;
7578             }
7579             // TODO: Normalizing tiargs for https://issues.dlang.org/show_bug.cgi?id=7469 is necessary?
7580             return true;
7581         }
7582 
7583         static if (LOG)
7584         {
7585             printf("TemplateInstance.findBestMatch()\n");
7586         }
7587 
7588         uint errs = global.errors;
7589         TemplateDeclaration td_last = null;
7590         Objects dedtypes;
7591 
7592         /* Since there can be multiple TemplateDeclaration's with the same
7593          * name, look for the best match.
7594          */
7595         auto tovers = tempdecl.isOverloadSet();
7596         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
7597         {
7598             TemplateDeclaration td_best;
7599             TemplateDeclaration td_ambig;
7600             MATCH m_best = MATCHnomatch;
7601 
7602             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7603             overloadApply(dstart, (Dsymbol s)
7604             {
7605                 auto  td = s.isTemplateDeclaration();
7606                 if (!td || td == td_best)   // skip duplicates
7607                     return 0;
7608 
7609                 //printf("td = %s\n", td.toPrettyChars());
7610                 // If more arguments than parameters,
7611                 // then this is no match.
7612                 if (td.parameters.dim < tiargs.dim)
7613                 {
7614                     if (!td.isVariadic())
7615                         return 0;
7616                 }
7617 
7618                 dedtypes.setDim(td.parameters.dim);
7619                 dedtypes.zero();
7620                 assert(td.semanticRun != PASSinit);
7621 
7622                 MATCH m = td.matchWithInstance(sc, this, &dedtypes, fargs, 0);
7623                 //printf("matchWithInstance = %d\n", m);
7624                 if (m <= MATCHnomatch) // no match at all
7625                     return 0;
7626                 if (m < m_best) goto Ltd_best;
7627                 if (m > m_best) goto Ltd;
7628 
7629                 // Disambiguate by picking the most specialized TemplateDeclaration
7630                 {
7631                 MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs);
7632                 MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs);
7633                 //printf("c1 = %d, c2 = %d\n", c1, c2);
7634                 if (c1 > c2) goto Ltd;
7635                 if (c1 < c2) goto Ltd_best;
7636                 }
7637 
7638                 td_ambig = td;
7639                 return 0;
7640 
7641             Ltd_best:
7642                 // td_best is the best match so far
7643                 td_ambig = null;
7644                 return 0;
7645 
7646             Ltd:
7647                 // td is the new best match
7648                 td_ambig = null;
7649                 td_best = td;
7650                 m_best = m;
7651                 tdtypes.setDim(dedtypes.dim);
7652                 memcpy(tdtypes.tdata(), dedtypes.tdata(), tdtypes.dim * (void*).sizeof);
7653                 return 0;
7654             });
7655 
7656             if (td_ambig)
7657             {
7658                 .error(loc, "%s %s.%s matches more than one template declaration:\n%s:     %s\nand\n%s:     %s",
7659                     td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars(),
7660                     td_best.loc.toChars(), td_best.toChars(),
7661                     td_ambig.loc.toChars(), td_ambig.toChars());
7662                 return false;
7663             }
7664             if (td_best)
7665             {
7666                 if (!td_last)
7667                     td_last = td_best;
7668                 else if (td_last != td_best)
7669                 {
7670                     ScopeDsymbol.multiplyDefined(loc, td_last, td_best);
7671                     return false;
7672                 }
7673             }
7674         }
7675 
7676         if (td_last)
7677         {
7678             /* https://issues.dlang.org/show_bug.cgi?id=7469
7679              * Normalize tiargs by using corresponding deduced
7680              * template value parameters and tuples for the correct mangling.
7681              *
7682              * By doing this before hasNestedArgs, CTFEable local variable will be
7683              * accepted as a value parameter. For example:
7684              *
7685              *  void foo() {
7686              *    struct S(int n) {}   // non-global template
7687              *    const int num = 1;   // CTFEable local variable
7688              *    S!num s;             // S!1 is instantiated, not S!num
7689              *  }
7690              */
7691             size_t dim = td_last.parameters.dim - (td_last.isVariadic() ? 1 : 0);
7692             for (size_t i = 0; i < dim; i++)
7693             {
7694                 if (tiargs.dim <= i)
7695                     tiargs.push(tdtypes[i]);
7696                 assert(i < tiargs.dim);
7697 
7698                 auto tvp = (*td_last.parameters)[i].isTemplateValueParameter();
7699                 if (!tvp)
7700                     continue;
7701                 assert(tdtypes[i]);
7702                 // tdtypes[i] is already normalized to the required type in matchArg
7703 
7704                 (*tiargs)[i] = tdtypes[i];
7705             }
7706             if (td_last.isVariadic() && tiargs.dim == dim && tdtypes[dim])
7707             {
7708                 Tuple va = isTuple(tdtypes[dim]);
7709                 assert(va);
7710                 for (size_t i = 0; i < va.objects.dim; i++)
7711                     tiargs.push(va.objects[i]);
7712             }
7713         }
7714         else if (errors && inst)
7715         {
7716             // instantiation was failed with error reporting
7717             assert(global.errors);
7718             return false;
7719         }
7720         else
7721         {
7722             auto tdecl = tempdecl.isTemplateDeclaration();
7723 
7724             if (errs != global.errors)
7725                 errorSupplemental(loc, "while looking for match for %s", toChars());
7726             else if (tdecl && !tdecl.overnext)
7727             {
7728                 // Only one template, so we can give better error message
7729                 error("does not match template declaration %s", tdecl.toChars());
7730             }
7731             else
7732                 .error(loc, "%s %s.%s does not match any template declaration", tempdecl.kind(), tempdecl.parent.toPrettyChars(), tempdecl.ident.toChars());
7733             return false;
7734         }
7735 
7736         /* The best match is td_last
7737          */
7738         tempdecl = td_last;
7739 
7740         static if (LOG)
7741         {
7742             printf("\tIt's a match with template declaration '%s'\n", tempdecl.toChars());
7743         }
7744         return (errs == global.errors);
7745     }
7746 
7747     /*****************************************************
7748      * Determine if template instance is really a template function,
7749      * and that template function needs to infer types from the function
7750      * arguments.
7751      *
7752      * Like findBestMatch, iterate possible template candidates,
7753      * but just looks only the necessity of type inference.
7754      */
7755     final bool needsTypeInference(Scope* sc, int flag = 0)
7756     {
7757         //printf("TemplateInstance.needsTypeInference() %s\n", toChars());
7758         if (semanticRun != PASSinit)
7759             return false;
7760 
7761         uint olderrs = global.errors;
7762         Objects dedtypes;
7763         size_t count = 0;
7764 
7765         auto tovers = tempdecl.isOverloadSet();
7766         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
7767         {
7768             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7769             int r = overloadApply(dstart, (Dsymbol s)
7770             {
7771                 auto td = s.isTemplateDeclaration();
7772                 if (!td)
7773                     return 0;
7774 
7775                 /* If any of the overloaded template declarations need inference,
7776                  * then return true
7777                  */
7778                 if (!td.onemember)
7779                     return 0;
7780                 if (auto td2 = td.onemember.isTemplateDeclaration())
7781                 {
7782                     if (!td2.onemember || !td2.onemember.isFuncDeclaration())
7783                         return 0;
7784                     if (tiargs.dim >= td.parameters.dim - (td.isVariadic() ? 1 : 0))
7785                         return 0;
7786                     return 1;
7787                 }
7788                 auto fd = td.onemember.isFuncDeclaration();
7789                 if (!fd || fd.type.ty != Tfunction)
7790                     return 0;
7791 
7792                 foreach (tp; *td.parameters)
7793                 {
7794                     if (tp.isTemplateThisParameter())
7795                         return 1;
7796                 }
7797 
7798                 /* Determine if the instance arguments, tiargs, are all that is necessary
7799                  * to instantiate the template.
7800                  */
7801                 //printf("tp = %p, td.parameters.dim = %d, tiargs.dim = %d\n", tp, td.parameters.dim, tiargs.dim);
7802                 auto tf = cast(TypeFunction)fd.type;
7803                 if (size_t dim = Parameter.dim(tf.parameters))
7804                 {
7805                     auto tp = td.isVariadic();
7806                     if (tp && td.parameters.dim > 1)
7807                         return 1;
7808 
7809                     if (!tp && tiargs.dim < td.parameters.dim)
7810                     {
7811                         // Can remain tiargs be filled by default arguments?
7812                         foreach (size_t i; tiargs.dim .. td.parameters.dim)
7813                         {
7814                             if (!(*td.parameters)[i].hasDefaultArg())
7815                                 return 1;
7816                         }
7817                     }
7818 
7819                     foreach (size_t i; 0 .. dim)
7820                     {
7821                         // 'auto ref' needs inference.
7822                         if (Parameter.getNth(tf.parameters, i).storageClass & STCauto)
7823                             return 1;
7824                     }
7825                 }
7826 
7827                 if (!flag)
7828                 {
7829                     /* Calculate the need for overload resolution.
7830                      * When only one template can match with tiargs, inference is not necessary.
7831                      */
7832                     dedtypes.setDim(td.parameters.dim);
7833                     dedtypes.zero();
7834                     if (td.semanticRun == PASSinit)
7835                     {
7836                         if (td._scope)
7837                         {
7838                             // Try to fix forward reference. Ungag errors while doing so.
7839                             Ungag ungag = td.ungagSpeculative();
7840                             td.semantic(td._scope);
7841                         }
7842                         if (td.semanticRun == PASSinit)
7843                         {
7844                             error("%s forward references template declaration %s", toChars(), td.toChars());
7845                             return 1;
7846                         }
7847                     }
7848                     MATCH m = td.matchWithInstance(sc, this, &dedtypes, null, 0);
7849                     if (m <= MATCHnomatch)
7850                         return 0;
7851                 }
7852 
7853                 /* If there is more than one function template which matches, we may
7854                  * need type inference (see https://issues.dlang.org/show_bug.cgi?id=4430)
7855                  */
7856                 return ++count > 1 ? 1 : 0;
7857             });
7858             if (r)
7859                 return true;
7860         }
7861 
7862         if (olderrs != global.errors)
7863         {
7864             if (!global.gag)
7865             {
7866                 errorSupplemental(loc, "while looking for match for %s", toChars());
7867                 semanticRun = PASSsemanticdone;
7868                 inst = this;
7869             }
7870             errors = true;
7871         }
7872         //printf("false\n");
7873         return false;
7874     }
7875 
7876     /*****************************************
7877      * Determines if a TemplateInstance will need a nested
7878      * generation of the TemplateDeclaration.
7879      * Sets enclosing property if so, and returns != 0;
7880      */
7881     final bool hasNestedArgs(Objects* args, bool isstatic)
7882     {
7883         int nested = 0;
7884         //printf("TemplateInstance.hasNestedArgs('%s')\n", tempdecl.ident.toChars());
7885 
7886         version (none)
7887         {
7888             if (!enclosing)
7889             {
7890                 if (TemplateInstance ti = tempdecl.isInstantiated())
7891                     enclosing = ti.enclosing;
7892             }
7893         }
7894 
7895         /* A nested instance happens when an argument references a local
7896          * symbol that is on the stack.
7897          */
7898         for (size_t i = 0; i < args.dim; i++)
7899         {
7900             RootObject o = (*args)[i];
7901             Expression ea = isExpression(o);
7902             Dsymbol sa = isDsymbol(o);
7903             Tuple va = isTuple(o);
7904             if (ea)
7905             {
7906                 if (ea.op == TOKvar)
7907                 {
7908                     sa = (cast(VarExp)ea).var;
7909                     goto Lsa;
7910                 }
7911                 if (ea.op == TOKthis)
7912                 {
7913                     sa = (cast(ThisExp)ea).var;
7914                     goto Lsa;
7915                 }
7916                 if (ea.op == TOKfunction)
7917                 {
7918                     if ((cast(FuncExp)ea).td)
7919                         sa = (cast(FuncExp)ea).td;
7920                     else
7921                         sa = (cast(FuncExp)ea).fd;
7922                     goto Lsa;
7923                 }
7924                 // Emulate Expression.toMangleBuffer call that had exist in TemplateInstance.genIdent.
7925                 if (ea.op != TOKint64 && ea.op != TOKfloat64 && ea.op != TOKcomplex80 && ea.op != TOKnull && ea.op != TOKstring && ea.op != TOKarrayliteral && ea.op != TOKassocarrayliteral && ea.op != TOKstructliteral)
7926                 {
7927                     ea.error("expression %s is not a valid template value argument", ea.toChars());
7928                     errors = true;
7929                 }
7930             }
7931             else if (sa)
7932             {
7933             Lsa:
7934                 sa = sa.toAlias();
7935                 TemplateDeclaration td = sa.isTemplateDeclaration();
7936                 if (td)
7937                 {
7938                     TemplateInstance ti = sa.toParent().isTemplateInstance();
7939                     if (ti && ti.enclosing)
7940                         sa = ti;
7941                 }
7942                 TemplateInstance ti = sa.isTemplateInstance();
7943                 Declaration d = sa.isDeclaration();
7944                 if ((td && td.literal) || (ti && ti.enclosing) || (d && !d.isDataseg() && !(d.storage_class & STCmanifest) && (!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) && !isTemplateMixin()))
7945                 {
7946                     // if module level template
7947                     if (isstatic)
7948                     {
7949                         Dsymbol dparent = sa.toParent2();
7950                         if (!enclosing)
7951                             enclosing = dparent;
7952                         else if (enclosing != dparent)
7953                         {
7954                             /* Select the more deeply nested of the two.
7955                              * Error if one is not nested inside the other.
7956                              */
7957                             for (Dsymbol p = enclosing; p; p = p.parent)
7958                             {
7959                                 if (p == dparent)
7960                                     goto L1; // enclosing is most nested
7961                             }
7962                             for (Dsymbol p = dparent; p; p = p.parent)
7963                             {
7964                                 if (p == enclosing)
7965                                 {
7966                                     enclosing = dparent;
7967                                     goto L1; // dparent is most nested
7968                                 }
7969                             }
7970                             error("%s is nested in both %s and %s", toChars(), enclosing.toChars(), dparent.toChars());
7971                             errors = true;
7972                         }
7973                     L1:
7974                         //printf("\tnested inside %s\n", enclosing.toChars());
7975                         nested |= 1;
7976                     }
7977                     else
7978                     {
7979                         error("cannot use local '%s' as parameter to non-global template %s", sa.toChars(), tempdecl.toChars());
7980                         errors = true;
7981                     }
7982                 }
7983             }
7984             else if (va)
7985             {
7986                 nested |= cast(int)hasNestedArgs(&va.objects, isstatic);
7987             }
7988         }
7989         //printf("-TemplateInstance.hasNestedArgs('%s') = %d\n", tempdecl.ident.toChars(), nested);
7990         return nested != 0;
7991     }
7992 
7993     /*****************************************
7994      * Append 'this' to the specific module members[]
7995      */
7996     final Dsymbols* appendToModuleMember()
7997     {
7998         Module mi = minst; // instantiated . inserted module
7999 
8000         if (global.params.useUnitTests || global.params.debuglevel)
8001         {
8002             // Turn all non-root instances to speculative
8003             if (mi && !mi.isRoot())
8004                 mi = null;
8005         }
8006 
8007         //printf("%s.appendToModuleMember() enclosing = %s mi = %s\n",
8008         //    toPrettyChars(),
8009         //    enclosing ? enclosing.toPrettyChars() : null,
8010         //    mi ? mi.toPrettyChars() : null);
8011         if (!mi || mi.isRoot())
8012         {
8013             /* If the instantiated module is speculative or root, insert to the
8014              * member of a root module. Then:
8015              *  - semantic3 pass will get called on the instance members.
8016              *  - codegen pass will get a selection chance to do/skip it.
8017              */
8018             static Dsymbol getStrictEnclosing(TemplateInstance ti)
8019             {
8020                 do
8021                 {
8022                     if (ti.enclosing)
8023                         return ti.enclosing;
8024                     ti = ti.tempdecl.isInstantiated();
8025                 } while (ti);
8026                 return null;
8027             }
8028 
8029             Dsymbol enc = getStrictEnclosing(this);
8030             // insert target is made stable by using the module
8031             // where tempdecl is declared.
8032             mi = (enc ? enc : tempdecl).getModule();
8033             if (!mi.isRoot())
8034                 mi = mi.importedFrom;
8035             assert(mi.isRoot());
8036         }
8037         else
8038         {
8039             /* If the instantiated module is non-root, insert to the member of the
8040              * non-root module. Then:
8041              *  - semantic3 pass won't be called on the instance.
8042              *  - codegen pass won't reach to the instance.
8043              */
8044         }
8045         //printf("\t-. mi = %s\n", mi.toPrettyChars());
8046 
8047         if (memberOf is mi)     // already a member
8048         {
8049             debug               // make sure it really is a member
8050             {
8051                 auto a = mi.members;
8052                 for (size_t i = 0; 1; ++i)
8053                 {
8054                     assert(i != a.dim);
8055                     if (this == (*a)[i])
8056                         break;
8057                 }
8058             }
8059             return null;
8060         }
8061 
8062         Dsymbols* a = mi.members;
8063         a.push(this);
8064         memberOf = mi;
8065         if (mi.semanticRun >= PASSsemantic2done && mi.isRoot())
8066             Module.addDeferredSemantic2(this);
8067         if (mi.semanticRun >= PASSsemantic3done && mi.isRoot())
8068             Module.addDeferredSemantic3(this);
8069         return a;
8070     }
8071 
8072     /****************************************************
8073      * Declare parameters of template instance, initialize them with the
8074      * template instance arguments.
8075      */
8076     final void declareParameters(Scope* sc)
8077     {
8078         TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
8079         assert(tempdecl);
8080 
8081         //printf("TemplateInstance.declareParameters()\n");
8082         for (size_t i = 0; i < tdtypes.dim; i++)
8083         {
8084             TemplateParameter tp = (*tempdecl.parameters)[i];
8085             //RootObject *o = (*tiargs)[i];
8086             RootObject o = tdtypes[i]; // initializer for tp
8087 
8088             //printf("\ttdtypes[%d] = %p\n", i, o);
8089             tempdecl.declareParameter(sc, tp, o);
8090         }
8091     }
8092 
8093     /****************************************
8094      * This instance needs an identifier for name mangling purposes.
8095      * Create one by taking the template declaration name and adding
8096      * the type signature for it.
8097      */
8098     final Identifier genIdent(Objects* args)
8099     {
8100         TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
8101         assert(tempdecl);
8102 
8103         //printf("TemplateInstance.genIdent('%s')\n", tempdecl.ident.toChars());
8104         OutBuffer buf;
8105 
8106         const id = tempdecl.ident.toString();
8107         // Use "__U" for the symbols declared inside template constraint.
8108         const char T = members ? 'T' : 'U';
8109         buf.printf("__%c%u%.*s", T, cast(int)id.length, cast(int)id.length, id.ptr);
8110 
8111         size_t nparams = tempdecl.parameters.dim - (tempdecl.isVariadic() ? 1 : 0);
8112         for (size_t i = 0; i < args.dim; i++)
8113         {
8114             RootObject o = (*args)[i];
8115             Type ta = isType(o);
8116             Expression ea = isExpression(o);
8117             Dsymbol sa = isDsymbol(o);
8118             Tuple va = isTuple(o);
8119             //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
8120             if (i < nparams && (*tempdecl.parameters)[i].specialization())
8121                 buf.writeByte('H'); // https://issues.dlang.org/show_bug.cgi?id=6574
8122             if (ta)
8123             {
8124                 buf.writeByte('T');
8125                 if (ta.deco)
8126                     buf.writestring(ta.deco);
8127                 else
8128                 {
8129                     debug
8130                     {
8131                         if (!global.errors)
8132                             printf("ta = %d, %s\n", ta.ty, ta.toChars());
8133                     }
8134                     assert(global.errors);
8135                 }
8136             }
8137             else if (ea)
8138             {
8139                 // Don't interpret it yet, it might actually be an alias
8140                 ea = ea.optimize(WANTvalue);
8141                 if (ea.op == TOKvar)
8142                 {
8143                     sa = (cast(VarExp)ea).var;
8144                     ea = null;
8145                     goto Lsa;
8146                 }
8147                 if (ea.op == TOKthis)
8148                 {
8149                     sa = (cast(ThisExp)ea).var;
8150                     ea = null;
8151                     goto Lsa;
8152                 }
8153                 if (ea.op == TOKfunction)
8154                 {
8155                     if ((cast(FuncExp)ea).td)
8156                         sa = (cast(FuncExp)ea).td;
8157                     else
8158                         sa = (cast(FuncExp)ea).fd;
8159                     ea = null;
8160                     goto Lsa;
8161                 }
8162                 buf.writeByte('V');
8163                 if (ea.op == TOKtuple)
8164                 {
8165                     ea.error("tuple is not a valid template value argument");
8166                     continue;
8167                 }
8168                 // Now that we know it is not an alias, we MUST obtain a value
8169                 uint olderr = global.errors;
8170                 ea = ea.ctfeInterpret();
8171                 if (ea.op == TOKerror || olderr != global.errors)
8172                     continue;
8173 
8174                 /* Use deco that matches what it would be for a function parameter
8175                  */
8176                 buf.writestring(ea.type.deco);
8177                 mangleToBuffer(ea, &buf);
8178             }
8179             else if (sa)
8180             {
8181             Lsa:
8182                 buf.writeByte('S');
8183                 sa = sa.toAlias();
8184                 Declaration d = sa.isDeclaration();
8185                 if (d && (!d.type || !d.type.deco))
8186                 {
8187                     error("forward reference of %s %s", d.kind(), d.toChars());
8188                     continue;
8189                 }
8190 
8191                 OutBuffer bufsa;
8192                 mangleToBuffer(sa, &bufsa);
8193                 auto s = bufsa.peekSlice();
8194 
8195                 /* https://issues.dlang.org/show_bug.cgi?id=3043
8196                  * If the first character of p is a digit this
8197                  * causes ambiguity issues because the digits of the two numbers are adjacent.
8198                  * Current demanglers resolve this by trying various places to separate the
8199                  * numbers until one gets a successful demangle.
8200                  * Unfortunately, fixing this ambiguity will break existing binary
8201                  * compatibility and the demanglers, so we'll leave it as is.
8202                  */
8203                 buf.printf("%u%.*s", cast(uint)s.length, cast(int)s.length, s.ptr);
8204             }
8205             else if (va)
8206             {
8207                 assert(i + 1 == args.dim); // must be last one
8208                 args = &va.objects;
8209                 i = -cast(size_t)1;
8210             }
8211             else
8212                 assert(0);
8213         }
8214         buf.writeByte('Z');
8215         //printf("\tgenIdent = %s\n", buf.peekString());
8216         return Identifier.idPool(buf.peekSlice());
8217     }
8218 
8219     final void expandMembers(Scope* sc2)
8220     {
8221         for (size_t i = 0; i < members.dim; i++)
8222         {
8223             Dsymbol s = (*members)[i];
8224             s.setScope(sc2);
8225         }
8226 
8227         for (size_t i = 0; i < members.dim; i++)
8228         {
8229             Dsymbol s = (*members)[i];
8230             s.importAll(sc2);
8231         }
8232 
8233         for (size_t i = 0; i < members.dim; i++)
8234         {
8235             Dsymbol s = (*members)[i];
8236             //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s.toChars(), s, s.kind(), this.toChars());
8237             //printf("test: enclosing = %d, sc2.parent = %s\n", enclosing, sc2.parent.toChars());
8238             //if (enclosing)
8239             //    s.parent = sc.parent;
8240             //printf("test3: enclosing = %d, s.parent = %s\n", enclosing, s.parent.toChars());
8241             s.semantic(sc2);
8242             //printf("test4: enclosing = %d, s.parent = %s\n", enclosing, s.parent.toChars());
8243             Module.runDeferredSemantic();
8244         }
8245     }
8246 
8247     final void tryExpandMembers(Scope* sc2)
8248     {
8249         static __gshared int nest;
8250         // extracted to a function to allow windows SEH to work without destructors in the same function
8251         //printf("%d\n", nest);
8252         if (++nest > 500)
8253         {
8254             global.gag = 0; // ensure error message gets printed
8255             error("recursive expansion");
8256             fatal();
8257         }
8258 
8259         expandMembers(sc2);
8260 
8261         nest--;
8262     }
8263 
8264     final void trySemantic3(Scope* sc2)
8265     {
8266         // extracted to a function to allow windows SEH to work without destructors in the same function
8267         static __gshared int nest;
8268         //printf("%d\n", nest);
8269         if (++nest > 300)
8270         {
8271             global.gag = 0; // ensure error message gets printed
8272             error("recursive expansion");
8273             fatal();
8274         }
8275 
8276         semantic3(sc2);
8277 
8278         --nest;
8279     }
8280 
8281     override final inout(TemplateInstance) isTemplateInstance() inout
8282     {
8283         return this;
8284     }
8285 
8286     override void accept(Visitor v)
8287     {
8288         v.visit(this);
8289     }
8290 }
8291 
8292 /**************************************
8293  * IsExpression can evaluate the specified type speculatively, and even if
8294  * it instantiates any symbols, they are normally unnecessary for the
8295  * final executable.
8296  * However, if those symbols leak to the actual code, compiler should remark
8297  * them as non-speculative to generate their code and link to the final executable.
8298  */
8299 void unSpeculative(Scope* sc, RootObject o)
8300 {
8301     if (!o)
8302         return;
8303 
8304     if (Tuple tup = isTuple(o))
8305     {
8306         for (size_t i = 0; i < tup.objects.dim; i++)
8307         {
8308             unSpeculative(sc, tup.objects[i]);
8309         }
8310         return;
8311     }
8312 
8313     Dsymbol s = getDsymbol(o);
8314     if (!s)
8315         return;
8316 
8317     Declaration d = s.isDeclaration();
8318     if (d)
8319     {
8320         if (VarDeclaration vd = d.isVarDeclaration())
8321             o = vd.type;
8322         else if (AliasDeclaration ad = d.isAliasDeclaration())
8323         {
8324             o = ad.getType();
8325             if (!o)
8326                 o = ad.toAlias();
8327         }
8328         else
8329             o = d.toAlias();
8330 
8331         s = getDsymbol(o);
8332         if (!s)
8333             return;
8334     }
8335 
8336     if (TemplateInstance ti = s.isTemplateInstance())
8337     {
8338         // If the instance is already non-speculative,
8339         // or it is leaked to the speculative scope.
8340         if (ti.minst !is null || sc.minst is null)
8341             return;
8342 
8343         // Remark as non-speculative instance.
8344         ti.minst = sc.minst;
8345         if (!ti.tinst)
8346             ti.tinst = sc.tinst;
8347 
8348         unSpeculative(sc, ti.tempdecl);
8349     }
8350 
8351     if (TemplateInstance ti = s.isInstantiated())
8352         unSpeculative(sc, ti);
8353 }
8354 
8355 /**********************************
8356  * Return true if e could be valid only as a template value parameter.
8357  * Return false if it might be an alias or tuple.
8358  * (Note that even in this case, it could still turn out to be a value).
8359  */
8360 bool definitelyValueParameter(Expression e)
8361 {
8362     // None of these can be value parameters
8363     if (e.op == TOKtuple || e.op == TOKscope ||
8364         e.op == TOKtype || e.op == TOKdottype ||
8365         e.op == TOKtemplate || e.op == TOKdottd ||
8366         e.op == TOKfunction || e.op == TOKerror ||
8367         e.op == TOKthis || e.op == TOKsuper)
8368         return false;
8369 
8370     if (e.op != TOKdotvar)
8371         return true;
8372 
8373     /* Template instantiations involving a DotVar expression are difficult.
8374      * In most cases, they should be treated as a value parameter, and interpreted.
8375      * But they might also just be a fully qualified name, which should be treated
8376      * as an alias.
8377      */
8378 
8379     // x.y.f cannot be a value
8380     FuncDeclaration f = (cast(DotVarExp)e).var.isFuncDeclaration();
8381     if (f)
8382         return false;
8383 
8384     while (e.op == TOKdotvar)
8385     {
8386         e = (cast(DotVarExp)e).e1;
8387     }
8388     // this.x.y and super.x.y couldn't possibly be valid values.
8389     if (e.op == TOKthis || e.op == TOKsuper)
8390         return false;
8391 
8392     // e.type.x could be an alias
8393     if (e.op == TOKdottype)
8394         return false;
8395 
8396     // var.x.y is the only other possible form of alias
8397     if (e.op != TOKvar)
8398         return true;
8399 
8400     VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
8401     // func.x.y is not an alias
8402     if (!v)
8403         return true;
8404 
8405     // TODO: Should we force CTFE if it is a global constant?
8406     return false;
8407 }
8408 
8409 /***********************************************************
8410  */
8411 extern (C++) final class TemplateMixin : TemplateInstance
8412 {
8413     TypeQualified tqual;
8414 
8415     extern (D) this(Loc loc, Identifier ident, TypeQualified tqual, Objects* tiargs)
8416     {
8417         super(loc,
8418               tqual.idents.dim ? cast(Identifier)tqual.idents[tqual.idents.dim - 1] : (cast(TypeIdentifier)tqual).ident,
8419               tiargs ? tiargs : new Objects());
8420         //printf("TemplateMixin(ident = '%s')\n", ident ? ident.toChars() : "");
8421         this.ident = ident;
8422         this.tqual = tqual;
8423     }
8424 
8425     override Dsymbol syntaxCopy(Dsymbol s)
8426     {
8427         auto tm = new TemplateMixin(loc, ident, cast(TypeQualified)tqual.syntaxCopy(), tiargs);
8428         return TemplateInstance.syntaxCopy(tm);
8429     }
8430 
8431     override void semantic(Scope* sc)
8432     {
8433         static if (LOG)
8434         {
8435             printf("+TemplateMixin.semantic('%s', this=%p)\n", toChars(), this);
8436             fflush(stdout);
8437         }
8438         if (semanticRun != PASSinit)
8439         {
8440             // When a class/struct contains mixin members, and is done over
8441             // because of forward references, never reach here so semanticRun
8442             // has been reset to PASSinit.
8443             static if (LOG)
8444             {
8445                 printf("\tsemantic done\n");
8446             }
8447             return;
8448         }
8449         semanticRun = PASSsemantic;
8450         static if (LOG)
8451         {
8452             printf("\tdo semantic\n");
8453         }
8454 
8455         Scope* scx = null;
8456         if (_scope)
8457         {
8458             sc = _scope;
8459             scx = _scope; // save so we don't make redundant copies
8460             _scope = null;
8461         }
8462 
8463         /* Run semantic on each argument, place results in tiargs[],
8464          * then find best match template with tiargs
8465          */
8466         if (!findTempDecl(sc) || !semanticTiargs(sc) || !findBestMatch(sc, null))
8467         {
8468             if (semanticRun == PASSinit) // forward reference had occured
8469             {
8470                 //printf("forward reference - deferring\n");
8471                 _scope = scx ? scx : sc.copy();
8472                 _scope.setNoFree();
8473                 _scope._module.addDeferredSemantic(this);
8474                 return;
8475             }
8476 
8477             inst = this;
8478             errors = true;
8479             return; // error recovery
8480         }
8481 
8482         auto tempdecl = this.tempdecl.isTemplateDeclaration();
8483         assert(tempdecl);
8484 
8485         if (!ident)
8486         {
8487             /* Assign scope local unique identifier, as same as lambdas.
8488              */
8489             const(char)* s = "__mixin";
8490 
8491             DsymbolTable symtab;
8492             if (FuncDeclaration func = sc.parent.isFuncDeclaration())
8493             {
8494                 symtab = func.localsymtab;
8495                 if (symtab)
8496                 {
8497                     // Inside template constraint, symtab is not set yet.
8498                     goto L1;
8499                 }
8500             }
8501             else
8502             {
8503                 symtab = sc.parent.isScopeDsymbol().symtab;
8504             L1:
8505                 assert(symtab);
8506                 ident = Identifier.generateId(s, symtab.len + 1);
8507                 symtab.insert(this);
8508             }
8509         }
8510 
8511         inst = this;
8512         parent = sc.parent;
8513 
8514         /* Detect recursive mixin instantiations.
8515          */
8516         for (Dsymbol s = parent; s; s = s.parent)
8517         {
8518             //printf("\ts = '%s'\n", s.toChars());
8519             TemplateMixin tm = s.isTemplateMixin();
8520             if (!tm || tempdecl != tm.tempdecl)
8521                 continue;
8522 
8523             /* Different argument list lengths happen with variadic args
8524              */
8525             if (tiargs.dim != tm.tiargs.dim)
8526                 continue;
8527 
8528             for (size_t i = 0; i < tiargs.dim; i++)
8529             {
8530                 RootObject o = (*tiargs)[i];
8531                 Type ta = isType(o);
8532                 Expression ea = isExpression(o);
8533                 Dsymbol sa = isDsymbol(o);
8534                 RootObject tmo = (*tm.tiargs)[i];
8535                 if (ta)
8536                 {
8537                     Type tmta = isType(tmo);
8538                     if (!tmta)
8539                         goto Lcontinue;
8540                     if (!ta.equals(tmta))
8541                         goto Lcontinue;
8542                 }
8543                 else if (ea)
8544                 {
8545                     Expression tme = isExpression(tmo);
8546                     if (!tme || !ea.equals(tme))
8547                         goto Lcontinue;
8548                 }
8549                 else if (sa)
8550                 {
8551                     Dsymbol tmsa = isDsymbol(tmo);
8552                     if (sa != tmsa)
8553                         goto Lcontinue;
8554                 }
8555                 else
8556                     assert(0);
8557             }
8558             error("recursive mixin instantiation");
8559             return;
8560 
8561         Lcontinue:
8562             continue;
8563         }
8564 
8565         // Copy the syntax trees from the TemplateDeclaration
8566         members = Dsymbol.arraySyntaxCopy(tempdecl.members);
8567         if (!members)
8568             return;
8569 
8570         symtab = new DsymbolTable();
8571 
8572         for (Scope* sce = sc; 1; sce = sce.enclosing)
8573         {
8574             ScopeDsymbol sds = sce.scopesym;
8575             if (sds)
8576             {
8577                 sds.importScope(this, Prot(PROTpublic));
8578                 break;
8579             }
8580         }
8581 
8582         static if (LOG)
8583         {
8584             printf("\tcreate scope for template parameters '%s'\n", toChars());
8585         }
8586         Scope* scy = sc.push(this);
8587         scy.parent = this;
8588 
8589         argsym = new ScopeDsymbol();
8590         argsym.parent = scy.parent;
8591         Scope* argscope = scy.push(argsym);
8592 
8593         uint errorsave = global.errors;
8594 
8595         // Declare each template parameter as an alias for the argument type
8596         declareParameters(argscope);
8597 
8598         // Add members to enclosing scope, as well as this scope
8599         for (size_t i = 0; i < members.dim; i++)
8600         {
8601             Dsymbol s = (*members)[i];
8602             s.addMember(argscope, this);
8603             //printf("sc.parent = %p, sc.scopesym = %p\n", sc.parent, sc.scopesym);
8604             //printf("s.parent = %s\n", s.parent.toChars());
8605         }
8606 
8607         // Do semantic() analysis on template instance members
8608         static if (LOG)
8609         {
8610             printf("\tdo semantic() on template instance members '%s'\n", toChars());
8611         }
8612         Scope* sc2 = argscope.push(this);
8613         //size_t deferred_dim = Module.deferred.dim;
8614 
8615         static __gshared int nest;
8616         //printf("%d\n", nest);
8617         if (++nest > 500)
8618         {
8619             global.gag = 0; // ensure error message gets printed
8620             error("recursive expansion");
8621             fatal();
8622         }
8623 
8624         for (size_t i = 0; i < members.dim; i++)
8625         {
8626             Dsymbol s = (*members)[i];
8627             s.setScope(sc2);
8628         }
8629 
8630         for (size_t i = 0; i < members.dim; i++)
8631         {
8632             Dsymbol s = (*members)[i];
8633             s.importAll(sc2);
8634         }
8635 
8636         for (size_t i = 0; i < members.dim; i++)
8637         {
8638             Dsymbol s = (*members)[i];
8639             s.semantic(sc2);
8640         }
8641 
8642         nest--;
8643 
8644         /* In DeclDefs scope, TemplateMixin does not have to handle deferred symbols.
8645          * Because the members would already call Module.addDeferredSemantic() for themselves.
8646          * See Struct, Class, Interface, and EnumDeclaration.semantic().
8647          */
8648         //if (!sc.func && Module.deferred.dim > deferred_dim) {}
8649 
8650         AggregateDeclaration ad = toParent().isAggregateDeclaration();
8651         if (sc.func && !ad)
8652         {
8653             semantic2(sc2);
8654             semantic3(sc2);
8655         }
8656 
8657         // Give additional context info if error occurred during instantiation
8658         if (global.errors != errorsave)
8659         {
8660             error("error instantiating");
8661             errors = true;
8662         }
8663 
8664         sc2.pop();
8665         argscope.pop();
8666         scy.pop();
8667 
8668         static if (LOG)
8669         {
8670             printf("-TemplateMixin.semantic('%s', this=%p)\n", toChars(), this);
8671         }
8672     }
8673 
8674     override void semantic2(Scope* sc)
8675     {
8676         if (semanticRun >= PASSsemantic2)
8677             return;
8678         semanticRun = PASSsemantic2;
8679         static if (LOG)
8680         {
8681             printf("+TemplateMixin.semantic2('%s')\n", toChars());
8682         }
8683         if (members)
8684         {
8685             assert(sc);
8686             sc = sc.push(argsym);
8687             sc = sc.push(this);
8688             for (size_t i = 0; i < members.dim; i++)
8689             {
8690                 Dsymbol s = (*members)[i];
8691                 static if (LOG)
8692                 {
8693                     printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
8694                 }
8695                 s.semantic2(sc);
8696             }
8697             sc = sc.pop();
8698             sc.pop();
8699         }
8700         static if (LOG)
8701         {
8702             printf("-TemplateMixin.semantic2('%s')\n", toChars());
8703         }
8704     }
8705 
8706     override void semantic3(Scope* sc)
8707     {
8708         if (semanticRun >= PASSsemantic3)
8709             return;
8710         semanticRun = PASSsemantic3;
8711         static if (LOG)
8712         {
8713             printf("TemplateMixin.semantic3('%s')\n", toChars());
8714         }
8715         if (members)
8716         {
8717             sc = sc.push(argsym);
8718             sc = sc.push(this);
8719             for (size_t i = 0; i < members.dim; i++)
8720             {
8721                 Dsymbol s = (*members)[i];
8722                 s.semantic3(sc);
8723             }
8724             sc = sc.pop();
8725             sc.pop();
8726         }
8727     }
8728 
8729     override const(char)* kind() const
8730     {
8731         return "mixin";
8732     }
8733 
8734     override bool oneMember(Dsymbol* ps, Identifier ident)
8735     {
8736         return Dsymbol.oneMember(ps, ident);
8737     }
8738 
8739     override int apply(Dsymbol_apply_ft_t fp, void* param)
8740     {
8741         if (_scope) // if fwd reference
8742             semantic(null); // try to resolve it
8743         if (members)
8744         {
8745             for (size_t i = 0; i < members.dim; i++)
8746             {
8747                 Dsymbol s = (*members)[i];
8748                 if (s)
8749                 {
8750                     if (s.apply(fp, param))
8751                         return 1;
8752                 }
8753             }
8754         }
8755         return 0;
8756     }
8757 
8758     override bool hasPointers()
8759     {
8760         //printf("TemplateMixin.hasPointers() %s\n", toChars());
8761         if (members)
8762         {
8763             for (size_t i = 0; i < members.dim; i++)
8764             {
8765                 Dsymbol s = (*members)[i];
8766                 //printf(" s = %s %s\n", s.kind(), s.toChars());
8767                 if (s.hasPointers())
8768                 {
8769                     return true;
8770                 }
8771             }
8772         }
8773         return false;
8774     }
8775 
8776     override void setFieldOffset(AggregateDeclaration ad, uint* poffset, bool isunion)
8777     {
8778         //printf("TemplateMixin.setFieldOffset() %s\n", toChars());
8779         if (_scope) // if fwd reference
8780             semantic(null); // try to resolve it
8781         if (members)
8782         {
8783             for (size_t i = 0; i < members.dim; i++)
8784             {
8785                 Dsymbol s = (*members)[i];
8786                 //printf("\t%s\n", s.toChars());
8787                 s.setFieldOffset(ad, poffset, isunion);
8788             }
8789         }
8790     }
8791 
8792     override const(char)* toChars()
8793     {
8794         OutBuffer buf;
8795         toCBufferInstance(this, &buf);
8796         return buf.extractString();
8797     }
8798 
8799     bool findTempDecl(Scope* sc)
8800     {
8801         // Follow qualifications to find the TemplateDeclaration
8802         if (!tempdecl)
8803         {
8804             Expression e;
8805             Type t;
8806             Dsymbol s;
8807             tqual.resolve(loc, sc, &e, &t, &s);
8808             if (!s)
8809             {
8810                 error("is not defined");
8811                 return false;
8812             }
8813             s = s.toAlias();
8814             tempdecl = s.isTemplateDeclaration();
8815             OverloadSet os = s.isOverloadSet();
8816 
8817             /* If an OverloadSet, look for a unique member that is a template declaration
8818              */
8819             if (os)
8820             {
8821                 Dsymbol ds = null;
8822                 for (size_t i = 0; i < os.a.dim; i++)
8823                 {
8824                     Dsymbol s2 = os.a[i].isTemplateDeclaration();
8825                     if (s2)
8826                     {
8827                         if (ds)
8828                         {
8829                             tempdecl = os;
8830                             break;
8831                         }
8832                         ds = s2;
8833                     }
8834                 }
8835             }
8836             if (!tempdecl)
8837             {
8838                 error("%s isn't a template", s.toChars());
8839                 return false;
8840             }
8841         }
8842         assert(tempdecl);
8843 
8844         // Look for forward references
8845         auto tovers = tempdecl.isOverloadSet();
8846         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
8847         {
8848             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
8849             int r = overloadApply(dstart, (Dsymbol s)
8850             {
8851                 auto td = s.isTemplateDeclaration();
8852                 if (!td)
8853                     return 0;
8854 
8855                 if (td.semanticRun == PASSinit)
8856                 {
8857                     if (td._scope)
8858                         td.semantic(td._scope);
8859                     else
8860                     {
8861                         semanticRun = PASSinit;
8862                         return 1;
8863                     }
8864                 }
8865                 return 0;
8866             });
8867             if (r)
8868                 return false;
8869         }
8870         return true;
8871     }
8872 
8873     override inout(TemplateMixin) isTemplateMixin() inout
8874     {
8875         return this;
8876     }
8877 
8878     override void accept(Visitor v)
8879     {
8880         v.visit(this);
8881     }
8882 }
8883 
8884 /************************************
8885  * This struct is needed for TemplateInstance to be the key in an associative array.
8886  * Fixing https://issues.dlang.org/show_bug.cgi?id=15812 and
8887  * https://issues.dlang.org/show_bug.cgi?id=15813 would make it unnecessary.
8888  */
8889 struct TemplateInstanceBox
8890 {
8891     TemplateInstance ti;
8892 
8893     this(TemplateInstance ti)
8894     {
8895         this.ti = ti;
8896         this.ti.toHash();
8897         assert(this.ti.hash);
8898     }
8899 
8900     size_t toHash() const @trusted pure nothrow
8901     {
8902         assert(ti.hash);
8903         return ti.hash;
8904     }
8905 
8906     bool opEquals(ref const TemplateInstanceBox s) @trusted const
8907     {
8908         if (ti.inst && s.ti.inst)
8909             /* This clause is only used when an instance with errors
8910              * is replaced with a correct instance.
8911              */
8912             return ti is s.ti;
8913         else
8914             /* Used when a proposed instance is used to see if there's
8915              * an existing instance.
8916              */
8917             return (cast()s.ti).compare(cast()ti) == 0;
8918     }
8919 }