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