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