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