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