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