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