xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/dmd/dtemplate.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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-2022 by The D Language Foundation, All Rights Reserved
32  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
33  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
34  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d, _dtemplate.d)
35  * Documentation:  https://dlang.org/phobos/dmd_dtemplate.html
36  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dtemplate.d
37  */
38 
39 module dmd.dtemplate;
40 
41 import core.stdc.stdio;
42 import core.stdc.string;
43 import dmd.aggregate;
44 import dmd.aliasthis;
45 import dmd.arraytypes;
46 import dmd.astenums;
47 import dmd.ast_node;
48 import dmd.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.common.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 == EXP.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", EXPtoString(e1.op).ptr, e1.toChars());
301             printf("\te2 = %s '%s' %s\n", e2.type ? e2.type.toChars() : "null", EXPtoString(e2.op).ptr, 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 EXP.int64:
425         return cast(size_t) e.isIntegerExp().getInteger();
426 
427     case EXP.float64:
428         return CTFloat.hash(e.isRealExp().value);
429 
430     case EXP.complex80:
431         auto ce = e.isComplexExp();
432         return mixHash(CTFloat.hash(ce.toReal), CTFloat.hash(ce.toImaginary));
433 
434     case EXP.identifier:
435         return cast(size_t)cast(void*) e.isIdentifierExp().ident;
436 
437     case EXP.null_:
438         return cast(size_t)cast(void*) e.isNullExp().type;
439 
440     case EXP.string_:
441         return calcHash(e.isStringExp.peekData());
442 
443     case EXP.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 EXP.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 EXP.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 EXP.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 EXP.variable:
482         return cast(size_t)cast(void*) e.isVarExp().var;
483 
484     case EXP.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             write(buf, (*parameters)[i]);
989             buf.writestring(" = ");
990             write(buf, 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             write(buf, (*parameters)[end]);
1002             buf.writestring(" = ");
1003             buf.writeByte('(');
1004             if (cast(int)tiargs.length - end > 0)
1005             {
1006                 write(buf, tiargs[end]);
1007                 foreach (j; parameters.length .. tiargs.length)
1008                 {
1009                     buf.writestring(", ");
1010                     write(buf, 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.flags |= FUNCFLAG.inferRetType;
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 == EXP.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 == EXP.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 != EXP.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 == EXP.string_)
1857                             {
1858                                 StringExp se = cast(StringExp)farg;
1859                                 argtype = se.type.nextOf().sarrayOf(se.len);
1860                             }
1861                             else if (farg.op == EXP.arrayLiteral)
1862                             {
1863                                 ArrayLiteralExp ae = cast(ArrayLiteralExp)farg;
1864                                 argtype = ae.type.nextOf().sarrayOf(ae.elements.dim);
1865                             }
1866                             else if (farg.op == EXP.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                              * We also save/restore sc.func.flags to avoid messing up
1924                              * attribute inference in the evaluation.
1925                             */
1926                             const oldflags = sc.func ? sc.func.flags : 0;
1927                             auto e = resolveAliasThis(sc, farg, true);
1928                             if (sc.func)
1929                                 sc.func.flags = oldflags;
1930                             if (e)
1931                             {
1932                                 farg = e;
1933                                 goto Lretry;
1934                             }
1935                         }
1936                     }
1937 
1938                     if (m > MATCH.nomatch && (fparam.storageClass & (STC.ref_ | STC.auto_)) == STC.ref_)
1939                     {
1940                         if (!farg.isLvalue())
1941                         {
1942                             if ((farg.op == EXP.string_ || farg.op == EXP.slice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
1943                             {
1944                                 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
1945                             }
1946                             else if (global.params.rvalueRefParam == FeatureState.enabled)
1947                             {
1948                                 // Allow implicit conversion to ref
1949                             }
1950                             else
1951                                 return nomatch();
1952                         }
1953                     }
1954                     if (m > MATCH.nomatch && (fparam.storageClass & STC.out_))
1955                     {
1956                         if (!farg.isLvalue())
1957                             return nomatch();
1958                         if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
1959                             return nomatch();
1960                     }
1961                     if (m == MATCH.nomatch && (fparam.storageClass & STC.lazy_) && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
1962                         m = MATCH.convert;
1963                     if (m != MATCH.nomatch)
1964                     {
1965                         if (m < match)
1966                             match = m; // pick worst match
1967                         argi++;
1968                         continue;
1969                     }
1970                 }
1971 
1972             Lvarargs:
1973                 /* The following code for variadic arguments closely
1974                  * matches TypeFunction.callMatch()
1975                  */
1976                 if (!(fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams))
1977                     return nomatch();
1978 
1979                 /* Check for match with function parameter T...
1980                  */
1981                 Type tb = prmtype.toBasetype();
1982                 switch (tb.ty)
1983                 {
1984                     // 6764 fix - TypeAArray may be TypeSArray have not yet run semantic().
1985                 case Tsarray:
1986                 case Taarray:
1987                     {
1988                         // Perhaps we can do better with this, see TypeFunction.callMatch()
1989                         if (tb.ty == Tsarray)
1990                         {
1991                             TypeSArray tsa = cast(TypeSArray)tb;
1992                             dinteger_t sz = tsa.dim.toInteger();
1993                             if (sz != nfargs - argi)
1994                                 return nomatch();
1995                         }
1996                         else if (tb.ty == Taarray)
1997                         {
1998                             TypeAArray taa = cast(TypeAArray)tb;
1999                             Expression dim = new IntegerExp(instLoc, nfargs - argi, Type.tsize_t);
2000 
2001                             size_t i = templateParameterLookup(taa.index, parameters);
2002                             if (i == IDX_NOTFOUND)
2003                             {
2004                                 Expression e;
2005                                 Type t;
2006                                 Dsymbol s;
2007                                 Scope *sco;
2008 
2009                                 uint errors = global.startGagging();
2010                                 /* ref: https://issues.dlang.org/show_bug.cgi?id=11118
2011                                  * The parameter isn't part of the template
2012                                  * ones, let's try to find it in the
2013                                  * instantiation scope 'sc' and the one
2014                                  * belonging to the template itself. */
2015                                 sco = sc;
2016                                 taa.index.resolve(instLoc, sco, e, t, s);
2017                                 if (!e)
2018                                 {
2019                                     sco = paramscope;
2020                                     taa.index.resolve(instLoc, sco, e, t, s);
2021                                 }
2022                                 global.endGagging(errors);
2023 
2024                                 if (!e)
2025                                     return nomatch();
2026 
2027                                 e = e.ctfeInterpret();
2028                                 e = e.implicitCastTo(sco, Type.tsize_t);
2029                                 e = e.optimize(WANTvalue);
2030                                 if (!dim.equals(e))
2031                                     return nomatch();
2032                             }
2033                             else
2034                             {
2035                                 // This code matches code in TypeInstance.deduceType()
2036                                 TemplateParameter tprm = (*parameters)[i];
2037                                 TemplateValueParameter tvp = tprm.isTemplateValueParameter();
2038                                 if (!tvp)
2039                                     return nomatch();
2040                                 Expression e = cast(Expression)(*dedtypes)[i];
2041                                 if (e)
2042                                 {
2043                                     if (!dim.equals(e))
2044                                         return nomatch();
2045                                 }
2046                                 else
2047                                 {
2048                                     Type vt = tvp.valType.typeSemantic(Loc.initial, sc);
2049                                     MATCH m = dim.implicitConvTo(vt);
2050                                     if (m == MATCH.nomatch)
2051                                         return nomatch();
2052                                     (*dedtypes)[i] = dim;
2053                                 }
2054                             }
2055                         }
2056                         goto case Tarray;
2057                     }
2058                 case Tarray:
2059                     {
2060                         TypeArray ta = cast(TypeArray)tb;
2061                         Type tret = fparam.isLazyArray();
2062                         for (; argi < nfargs; argi++)
2063                         {
2064                             Expression arg = (*fargs)[argi];
2065                             assert(arg);
2066 
2067                             MATCH m;
2068                             /* If lazy array of delegates,
2069                              * convert arg(s) to delegate(s)
2070                              */
2071                             if (tret)
2072                             {
2073                                 if (ta.next.equals(arg.type))
2074                                 {
2075                                     m = MATCH.exact;
2076                                 }
2077                                 else
2078                                 {
2079                                     m = arg.implicitConvTo(tret);
2080                                     if (m == MATCH.nomatch)
2081                                     {
2082                                         if (tret.toBasetype().ty == Tvoid)
2083                                             m = MATCH.convert;
2084                                     }
2085                                 }
2086                             }
2087                             else
2088                             {
2089                                 uint wm = 0;
2090                                 m = deduceType(arg, paramscope, ta.next, parameters, dedtypes, &wm, inferStart);
2091                                 wildmatch |= wm;
2092                             }
2093                             if (m == MATCH.nomatch)
2094                                 return nomatch();
2095                             if (m < match)
2096                                 match = m;
2097                         }
2098                         goto Lmatch;
2099                     }
2100                 case Tclass:
2101                 case Tident:
2102                     goto Lmatch;
2103 
2104                 default:
2105                     return nomatch();
2106                 }
2107                 assert(0);
2108             }
2109             //printf(". argi = %d, nfargs = %d, nfargs2 = %d\n", argi, nfargs, nfargs2);
2110             if (argi != nfargs2 && fparameters.varargs == VarArg.none)
2111                 return nomatch();
2112         }
2113 
2114     Lmatch:
2115         foreach (ref dedtype; *dedtypes)
2116         {
2117             Type at = isType(dedtype);
2118             if (at)
2119             {
2120                 if (at.ty == Tnone)
2121                 {
2122                     TypeDeduced xt = cast(TypeDeduced)at;
2123                     at = xt.tded; // 'unbox'
2124                 }
2125                 dedtype = at.merge2();
2126             }
2127         }
2128         for (size_t i = ntargs; i < dedargs.dim; i++)
2129         {
2130             TemplateParameter tparam = (*parameters)[i];
2131             //printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
2132 
2133             /* For T:T*, the dedargs is the T*, dedtypes is the T
2134              * But for function templates, we really need them to match
2135              */
2136             RootObject oarg = (*dedargs)[i];
2137             RootObject oded = (*dedtypes)[i];
2138             //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
2139             //if (oarg) printf("oarg: %s\n", oarg.toChars());
2140             //if (oded) printf("oded: %s\n", oded.toChars());
2141             if (oarg)
2142                 continue;
2143 
2144             if (oded)
2145             {
2146                 if (tparam.specialization() || !tparam.isTemplateTypeParameter())
2147                 {
2148                     /* The specialization can work as long as afterwards
2149                      * the oded == oarg
2150                      */
2151                     (*dedargs)[i] = oded;
2152                     MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
2153                     //printf("m2 = %d\n", m2);
2154                     if (m2 == MATCH.nomatch)
2155                         return nomatch();
2156                     if (m2 < matchTiargs)
2157                         matchTiargs = m2; // pick worst match
2158                     if (!(*dedtypes)[i].equals(oded))
2159                         error("specialization not allowed for deduced parameter `%s`", tparam.ident.toChars());
2160                 }
2161                 else
2162                 {
2163                     // Discussion: https://issues.dlang.org/show_bug.cgi?id=16484
2164                     if (MATCH.convert < matchTiargs)
2165                         matchTiargs = MATCH.convert;
2166                 }
2167             }
2168             else
2169             {
2170                 inuse++;
2171                 oded = tparam.defaultArg(instLoc, paramscope);
2172                 inuse--;
2173                 if (!oded)
2174                 {
2175                     // if tuple parameter and
2176                     // tuple parameter was not in function parameter list and
2177                     // we're one or more arguments short (i.e. no tuple argument)
2178                     if (tparam == tp &&
2179                         fptupindex == IDX_NOTFOUND &&
2180                         ntargs <= dedargs.dim - 1)
2181                     {
2182                         // make tuple argument an empty tuple
2183                         oded = new Tuple();
2184                     }
2185                     else
2186                         return nomatch();
2187                 }
2188                 if (isError(oded))
2189                     return matcherror();
2190                 ntargs++;
2191 
2192                 /* At the template parameter T, the picked default template argument
2193                  * X!int should be matched to T in order to deduce dependent
2194                  * template parameter A.
2195                  *  auto foo(T : X!A = X!int, A...)() { ... }
2196                  *  foo();  // T <-- X!int, A <-- (int)
2197                  */
2198                 if (tparam.specialization())
2199                 {
2200                     (*dedargs)[i] = oded;
2201                     MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
2202                     //printf("m2 = %d\n", m2);
2203                     if (m2 == MATCH.nomatch)
2204                         return nomatch();
2205                     if (m2 < matchTiargs)
2206                         matchTiargs = m2; // pick worst match
2207                     if (!(*dedtypes)[i].equals(oded))
2208                         error("specialization not allowed for deduced parameter `%s`", tparam.ident.toChars());
2209                 }
2210             }
2211             oded = declareParameter(paramscope, tparam, oded);
2212             (*dedargs)[i] = oded;
2213         }
2214 
2215         /* https://issues.dlang.org/show_bug.cgi?id=7469
2216          * As same as the code for 7469 in findBestMatch,
2217          * expand a Tuple in dedargs to normalize template arguments.
2218          */
2219         if (auto d = dedargs.dim)
2220         {
2221             if (auto va = isTuple((*dedargs)[d - 1]))
2222             {
2223                 dedargs.setDim(d - 1);
2224                 dedargs.insert(d - 1, &va.objects);
2225             }
2226         }
2227         ti.tiargs = dedargs; // update to the normalized template arguments.
2228 
2229         // Partially instantiate function for constraint and fd.leastAsSpecialized()
2230         {
2231             assert(paramscope.scopesym);
2232             Scope* sc2 = _scope;
2233             sc2 = sc2.push(paramscope.scopesym);
2234             sc2 = sc2.push(ti);
2235             sc2.parent = ti;
2236             sc2.tinst = ti;
2237             sc2.minst = sc.minst;
2238             sc2.stc |= fd.storage_class & STC.deprecated_;
2239 
2240             fd = doHeaderInstantiation(ti, sc2, fd, tthis, fargs);
2241 
2242             sc2 = sc2.pop();
2243             sc2 = sc2.pop();
2244 
2245             if (!fd)
2246                 return nomatch();
2247         }
2248 
2249         if (constraint)
2250         {
2251             if (!evaluateConstraint(ti, sc, paramscope, dedargs, fd))
2252                 return nomatch();
2253         }
2254 
2255         version (none)
2256         {
2257             for (size_t i = 0; i < dedargs.dim; i++)
2258             {
2259                 RootObject o = (*dedargs)[i];
2260                 printf("\tdedargs[%d] = %d, %s\n", i, o.dyncast(), o.toChars());
2261             }
2262         }
2263 
2264         paramscope.pop();
2265         //printf("\tmatch %d\n", match);
2266         return MATCHpair(matchTiargs, match);
2267     }
2268 
2269     /**************************************************
2270      * Declare template parameter tp with value o, and install it in the scope sc.
2271      */
declareParameter(Scope * sc,TemplateParameter tp,RootObject o)2272     RootObject declareParameter(Scope* sc, TemplateParameter tp, RootObject o)
2273     {
2274         //printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o);
2275         Type ta = isType(o);
2276         Expression ea = isExpression(o);
2277         Dsymbol sa = isDsymbol(o);
2278         Tuple va = isTuple(o);
2279 
2280         Declaration d;
2281         VarDeclaration v = null;
2282 
2283         if (ea && ea.op == EXP.type)
2284             ta = ea.type;
2285         else if (ea && ea.op == EXP.scope_)
2286             sa = (cast(ScopeExp)ea).sds;
2287         else if (ea && (ea.op == EXP.this_ || ea.op == EXP.super_))
2288             sa = (cast(ThisExp)ea).var;
2289         else if (ea && ea.op == EXP.function_)
2290         {
2291             if ((cast(FuncExp)ea).td)
2292                 sa = (cast(FuncExp)ea).td;
2293             else
2294                 sa = (cast(FuncExp)ea).fd;
2295         }
2296 
2297         if (ta)
2298         {
2299             //printf("type %s\n", ta.toChars());
2300             auto ad = new AliasDeclaration(Loc.initial, tp.ident, ta);
2301             ad.storage_class |= STC.templateparameter;
2302             d = ad;
2303         }
2304         else if (sa)
2305         {
2306             //printf("Alias %s %s;\n", sa.ident.toChars(), tp.ident.toChars());
2307             auto ad = new AliasDeclaration(Loc.initial, tp.ident, sa);
2308             ad.storage_class |= STC.templateparameter;
2309             d = ad;
2310         }
2311         else if (ea)
2312         {
2313             // tdtypes.data[i] always matches ea here
2314             Initializer _init = new ExpInitializer(loc, ea);
2315             TemplateValueParameter tvp = tp.isTemplateValueParameter();
2316             Type t = tvp ? tvp.valType : null;
2317             v = new VarDeclaration(loc, t, tp.ident, _init);
2318             v.storage_class = STC.manifest | STC.templateparameter;
2319             d = v;
2320         }
2321         else if (va)
2322         {
2323             //printf("\ttuple\n");
2324             d = new TupleDeclaration(loc, tp.ident, &va.objects);
2325         }
2326         else
2327         {
2328             assert(0);
2329         }
2330         d.storage_class |= STC.templateparameter;
2331 
2332         if (ta)
2333         {
2334             Type t = ta;
2335             // consistent with Type.checkDeprecated()
2336             while (t.ty != Tenum)
2337             {
2338                 if (!t.nextOf())
2339                     break;
2340                 t = (cast(TypeNext)t).next;
2341             }
2342             if (Dsymbol s = t.toDsymbol(sc))
2343             {
2344                 if (s.isDeprecated())
2345                     d.storage_class |= STC.deprecated_;
2346             }
2347         }
2348         else if (sa)
2349         {
2350             if (sa.isDeprecated())
2351                 d.storage_class |= STC.deprecated_;
2352         }
2353 
2354         if (!sc.insert(d))
2355             error("declaration `%s` is already defined", tp.ident.toChars());
2356         d.dsymbolSemantic(sc);
2357         /* So the caller's o gets updated with the result of semantic() being run on o
2358          */
2359         if (v)
2360             o = v._init.initializerToExpression();
2361         return o;
2362     }
2363 
2364     /*************************************************
2365      * Limited function template instantiation for using fd.leastAsSpecialized()
2366      */
doHeaderInstantiation(TemplateInstance ti,Scope * sc2,FuncDeclaration fd,Type tthis,Expressions * fargs)2367     extern (D) FuncDeclaration doHeaderInstantiation(TemplateInstance ti, Scope* sc2, FuncDeclaration fd, Type tthis, Expressions* fargs)
2368     {
2369         assert(fd);
2370         version (none)
2371         {
2372             printf("doHeaderInstantiation this = %s\n", toChars());
2373         }
2374 
2375         // function body and contracts are not need
2376         if (fd.isCtorDeclaration())
2377             fd = new CtorDeclaration(fd.loc, fd.endloc, fd.storage_class, fd.type.syntaxCopy());
2378         else
2379             fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, fd.type.syntaxCopy());
2380         fd.parent = ti;
2381 
2382         assert(fd.type.ty == Tfunction);
2383         auto tf = fd.type.isTypeFunction();
2384         tf.fargs = fargs;
2385 
2386         if (tthis)
2387         {
2388             // Match 'tthis' to any TemplateThisParameter's
2389             bool hasttp = false;
2390             foreach (tp; *parameters)
2391             {
2392                 TemplateThisParameter ttp = tp.isTemplateThisParameter();
2393                 if (ttp)
2394                     hasttp = true;
2395             }
2396             if (hasttp)
2397             {
2398                 tf = cast(TypeFunction)tf.addSTC(ModToStc(tthis.mod));
2399                 assert(!tf.deco);
2400             }
2401         }
2402 
2403         Scope* scx = sc2.push();
2404 
2405         // Shouldn't run semantic on default arguments and return type.
2406         foreach (ref params; *tf.parameterList.parameters)
2407             params.defaultArg = null;
2408         tf.incomplete = true;
2409 
2410         if (fd.isCtorDeclaration())
2411         {
2412             // For constructors, emitting return type is necessary for
2413             // isReturnIsolated() in functionResolve.
2414             tf.isctor = true;
2415 
2416             Dsymbol parent = toParentDecl();
2417             Type tret;
2418             AggregateDeclaration ad = parent.isAggregateDeclaration();
2419             if (!ad || parent.isUnionDeclaration())
2420             {
2421                 tret = Type.tvoid;
2422             }
2423             else
2424             {
2425                 tret = ad.handleType();
2426                 assert(tret);
2427                 tret = tret.addStorageClass(fd.storage_class | scx.stc);
2428                 tret = tret.addMod(tf.mod);
2429             }
2430             tf.next = tret;
2431             if (ad && ad.isStructDeclaration())
2432                 tf.isref = 1;
2433             //printf("tf = %s\n", tf.toChars());
2434         }
2435         else
2436             tf.next = null;
2437         fd.type = tf;
2438         fd.type = fd.type.addSTC(scx.stc);
2439         fd.type = fd.type.typeSemantic(fd.loc, scx);
2440         scx = scx.pop();
2441 
2442         if (fd.type.ty != Tfunction)
2443             return null;
2444 
2445         fd.originalType = fd.type; // for mangling
2446         //printf("\t[%s] fd.type = %s, mod = %x, ", loc.toChars(), fd.type.toChars(), fd.type.mod);
2447         //printf("fd.needThis() = %d\n", fd.needThis());
2448 
2449         return fd;
2450     }
2451 
debug(FindExistingInstance)2452     debug (FindExistingInstance)
2453     {
2454         __gshared uint nFound, nNotFound, nAdded, nRemoved;
2455 
2456         shared static ~this()
2457         {
2458             printf("debug (FindExistingInstance) nFound %u, nNotFound: %u, nAdded: %u, nRemoved: %u\n",
2459                    nFound, nNotFound, nAdded, nRemoved);
2460         }
2461     }
2462 
2463     /****************************************************
2464      * Given a new instance tithis of this TemplateDeclaration,
2465      * see if there already exists an instance.
2466      * If so, return that existing instance.
2467      */
findExistingInstance(TemplateInstance tithis,Expressions * fargs)2468     extern (D) TemplateInstance findExistingInstance(TemplateInstance tithis, Expressions* fargs)
2469     {
2470         //printf("findExistingInstance() %s\n", tithis.toChars());
2471         tithis.fargs = fargs;
2472         auto tibox = TemplateInstanceBox(tithis);
2473         auto p = tibox in instances;
2474         debug (FindExistingInstance) ++(p ? nFound : nNotFound);
2475         //if (p) printf("\tfound %p\n", *p); else printf("\tnot found\n");
2476         return p ? *p : null;
2477     }
2478 
2479     /********************************************
2480      * Add instance ti to TemplateDeclaration's table of instances.
2481      * Return a handle we can use to later remove it if it fails instantiation.
2482      */
addInstance(TemplateInstance ti)2483     extern (D) TemplateInstance addInstance(TemplateInstance ti)
2484     {
2485         //printf("addInstance() %p %s\n", instances, ti.toChars());
2486         auto tibox = TemplateInstanceBox(ti);
2487         instances[tibox] = ti;
2488         debug (FindExistingInstance) ++nAdded;
2489         return ti;
2490     }
2491 
2492     /*******************************************
2493      * Remove TemplateInstance from table of instances.
2494      * Input:
2495      *      handle returned by addInstance()
2496      */
removeInstance(TemplateInstance ti)2497     extern (D) void removeInstance(TemplateInstance ti)
2498     {
2499         //printf("removeInstance() %s\n", ti.toChars());
2500         auto tibox = TemplateInstanceBox(ti);
2501         debug (FindExistingInstance) ++nRemoved;
2502         instances.remove(tibox);
2503     }
2504 
inout(TemplateDeclaration)2505     override inout(TemplateDeclaration) isTemplateDeclaration() inout
2506     {
2507         return this;
2508     }
2509 
2510     /**
2511      * Check if the last template parameter is a tuple one,
2512      * and returns it if so, else returns `null`.
2513      *
2514      * Returns:
2515      *   The last template parameter if it's a `TemplateTupleParameter`
2516      */
isVariadic()2517     TemplateTupleParameter isVariadic()
2518     {
2519         size_t dim = parameters.dim;
2520         if (dim == 0)
2521             return null;
2522         return (*parameters)[dim - 1].isTemplateTupleParameter();
2523     }
2524 
isDeprecated()2525     extern(C++) override bool isDeprecated() const
2526     {
2527         return this.deprecated_;
2528     }
2529 
2530     /***********************************
2531      * We can overload templates.
2532      */
isOverloadable()2533     override bool isOverloadable() const
2534     {
2535         return true;
2536     }
2537 
accept(Visitor v)2538     override void accept(Visitor v)
2539     {
2540         v.visit(this);
2541     }
2542 }
2543 
2544 extern (C++) final class TypeDeduced : Type
2545 {
2546     Type tded;
2547     Expressions argexps; // corresponding expressions
2548     Types tparams; // tparams[i].mod
2549 
this(Type tt,Expression e,Type tparam)2550     extern (D) this(Type tt, Expression e, Type tparam)
2551     {
2552         super(Tnone);
2553         tded = tt;
2554         argexps.push(e);
2555         tparams.push(tparam);
2556     }
2557 
update(Expression e,Type tparam)2558     void update(Expression e, Type tparam)
2559     {
2560         argexps.push(e);
2561         tparams.push(tparam);
2562     }
2563 
update(Type tt,Expression e,Type tparam)2564     void update(Type tt, Expression e, Type tparam)
2565     {
2566         tded = tt;
2567         argexps.push(e);
2568         tparams.push(tparam);
2569     }
2570 
matchAll(Type tt)2571     MATCH matchAll(Type tt)
2572     {
2573         MATCH match = MATCH.exact;
2574         foreach (j, e; argexps)
2575         {
2576             assert(e);
2577             if (e == emptyArrayElement)
2578                 continue;
2579 
2580             Type t = tt.addMod(tparams[j].mod).substWildTo(MODFlags.const_);
2581 
2582             MATCH m = e.implicitConvTo(t);
2583             if (match > m)
2584                 match = m;
2585             if (match == MATCH.nomatch)
2586                 break;
2587         }
2588         return match;
2589     }
2590 }
2591 
2592 
2593 /*************************************************
2594  * Given function arguments, figure out which template function
2595  * to expand, and return matching result.
2596  * Params:
2597  *      m           = matching result
2598  *      dstart      = the root of overloaded function templates
2599  *      loc         = instantiation location
2600  *      sc          = instantiation scope
2601  *      tiargs      = initial list of template arguments
2602  *      tthis       = if !NULL, the 'this' pointer argument
2603  *      fargs       = arguments to function
2604  *      pMessage    = address to store error message, or null
2605  */
2606 void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs,
2607     Type tthis, Expressions* fargs, const(char)** pMessage = null)
2608 {
2609     Expression[] fargs_ = fargs.peekSlice();
version(none)2610     version (none)
2611     {
2612         printf("functionResolve() dstart = %s\n", dstart.toChars());
2613         printf("    tiargs:\n");
2614         if (tiargs)
2615         {
2616             for (size_t i = 0; i < tiargs.dim; i++)
2617             {
2618                 RootObject arg = (*tiargs)[i];
2619                 printf("\t%s\n", arg.toChars());
2620             }
2621         }
2622         printf("    fargs:\n");
2623         for (size_t i = 0; i < (fargs ? fargs.dim : 0); i++)
2624         {
2625             Expression arg = (*fargs)[i];
2626             printf("\t%s %s\n", arg.type.toChars(), arg.toChars());
2627             //printf("\tty = %d\n", arg.type.ty);
2628         }
2629         //printf("stc = %llx\n", dstart._scope.stc);
2630         //printf("match:t/f = %d/%d\n", ta_last, m.last);
2631     }
2632 
2633     // results
2634     int property = 0;   // 0: uninitialized
2635                         // 1: seen @property
2636                         // 2: not @property
2637     size_t ov_index = 0;
2638     TemplateDeclaration td_best;
2639     TemplateInstance ti_best;
2640     MATCH ta_last = m.last != MATCH.nomatch ? MATCH.exact : MATCH.nomatch;
2641     Type tthis_best;
2642 
applyFunction(FuncDeclaration fd)2643     int applyFunction(FuncDeclaration fd)
2644     {
2645         // skip duplicates
2646         if (fd == m.lastf)
2647             return 0;
2648         // explicitly specified tiargs never match to non template function
2649         if (tiargs && tiargs.dim > 0)
2650             return 0;
2651 
2652         // constructors need a valid scope in order to detect semantic errors
2653         if (!fd.isCtorDeclaration &&
2654             fd.semanticRun < PASS.semanticdone)
2655         {
2656             Ungag ungag = fd.ungagSpeculative();
2657             fd.dsymbolSemantic(null);
2658         }
2659         if (fd.semanticRun < PASS.semanticdone)
2660         {
2661             .error(loc, "forward reference to template `%s`", fd.toChars());
2662             return 1;
2663         }
2664         //printf("fd = %s %s, fargs = %s\n", fd.toChars(), fd.type.toChars(), fargs.toChars());
2665         auto tf = cast(TypeFunction)fd.type;
2666 
2667         int prop = tf.isproperty ? 1 : 2;
2668         if (property == 0)
2669             property = prop;
2670         else if (property != prop)
2671             error(fd.loc, "cannot overload both property and non-property functions");
2672 
2673         /* For constructors, qualifier check will be opposite direction.
2674          * Qualified constructor always makes qualified object, then will be checked
2675          * that it is implicitly convertible to tthis.
2676          */
2677         Type tthis_fd = fd.needThis() ? tthis : null;
2678         bool isCtorCall = tthis_fd && fd.isCtorDeclaration();
2679         if (isCtorCall)
2680         {
2681             //printf("%s tf.mod = x%x tthis_fd.mod = x%x %d\n", tf.toChars(),
2682             //        tf.mod, tthis_fd.mod, fd.isReturnIsolated());
2683             if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
2684                 tf.isWild() && tf.isShared() == tthis_fd.isShared() ||
2685                 fd.isReturnIsolated())
2686             {
2687                 /* && tf.isShared() == tthis_fd.isShared()*/
2688                 // Uniquely constructed object can ignore shared qualifier.
2689                 // TODO: Is this appropriate?
2690                 tthis_fd = null;
2691             }
2692             else
2693                 return 0;   // MATCH.nomatch
2694         }
2695         /* Fix Issue 17970:
2696            If a struct is declared as shared the dtor is automatically
2697            considered to be shared, but when the struct is instantiated
2698            the instance is no longer considered to be shared when the
2699            function call matching is done. The fix makes it so that if a
2700            struct declaration is shared, when the destructor is called,
2701            the instantiated struct is also considered shared.
2702         */
2703         if (auto dt = fd.isDtorDeclaration())
2704         {
2705             auto dtmod = dt.type.toTypeFunction();
2706             auto shared_dtor = dtmod.mod & MODFlags.shared_;
2707             auto shared_this = tthis_fd !is null ?
2708                 tthis_fd.mod & MODFlags.shared_ : 0;
2709             if (shared_dtor && !shared_this)
2710                 tthis_fd = dtmod;
2711             else if (shared_this && !shared_dtor && tthis_fd !is null)
2712                 tf.mod = tthis_fd.mod;
2713         }
2714         MATCH mfa = tf.callMatch(tthis_fd, fargs_, 0, pMessage, sc);
2715         //printf("test1: mfa = %d\n", mfa);
2716         if (mfa == MATCH.nomatch)
2717             return 0;
2718 
2719         if (mfa > m.last) goto LfIsBetter;
2720         if (mfa < m.last) goto LlastIsBetter;
2721 
2722         /* See if one of the matches overrides the other.
2723          */
2724         assert(m.lastf);
2725         if (m.lastf.overrides(fd)) goto LlastIsBetter;
2726         if (fd.overrides(m.lastf)) goto LfIsBetter;
2727 
2728         /* Try to disambiguate using template-style partial ordering rules.
2729          * In essence, if f() and g() are ambiguous, if f() can call g(),
2730          * but g() cannot call f(), then pick f().
2731          * This is because f() is "more specialized."
2732          */
2733         {
2734             MATCH c1 = fd.leastAsSpecialized(m.lastf);
2735             MATCH c2 = m.lastf.leastAsSpecialized(fd);
2736             //printf("c1 = %d, c2 = %d\n", c1, c2);
2737             if (c1 > c2) goto LfIsBetter;
2738             if (c1 < c2) goto LlastIsBetter;
2739         }
2740 
2741         /* The 'overrides' check above does covariant checking only
2742          * for virtual member functions. It should do it for all functions,
2743          * but in order to not risk breaking code we put it after
2744          * the 'leastAsSpecialized' check.
2745          * In the future try moving it before.
2746          * I.e. a not-the-same-but-covariant match is preferred,
2747          * as it is more restrictive.
2748          */
2749         if (!m.lastf.type.equals(fd.type))
2750         {
2751             //printf("cov: %d %d\n", m.lastf.type.covariant(fd.type), fd.type.covariant(m.lastf.type));
2752             const lastCovariant = m.lastf.type.covariant(fd.type);
2753             const firstCovariant = fd.type.covariant(m.lastf.type);
2754 
2755             if (lastCovariant == Covariant.yes || lastCovariant == Covariant.no)
2756             {
2757                 if (firstCovariant != Covariant.yes && firstCovariant != Covariant.no)
2758                 {
2759                     goto LlastIsBetter;
2760                 }
2761             }
2762             else if (firstCovariant == Covariant.yes || firstCovariant == Covariant.no)
2763             {
2764                 goto LfIsBetter;
2765             }
2766         }
2767 
2768         /* If the two functions are the same function, like:
2769          *    int foo(int);
2770          *    int foo(int x) { ... }
2771          * then pick the one with the body.
2772          *
2773          * If none has a body then don't care because the same
2774          * real function would be linked to the decl (e.g from object file)
2775          */
2776         if (tf.equals(m.lastf.type) &&
2777             fd.storage_class == m.lastf.storage_class &&
2778             fd.parent == m.lastf.parent &&
2779             fd.visibility == m.lastf.visibility &&
2780             fd._linkage == m.lastf._linkage)
2781         {
2782             if (fd.fbody && !m.lastf.fbody)
2783                 goto LfIsBetter;
2784             if (!fd.fbody)
2785                 goto LlastIsBetter;
2786         }
2787 
2788         // https://issues.dlang.org/show_bug.cgi?id=14450
2789         // Prefer exact qualified constructor for the creating object type
2790         if (isCtorCall && tf.mod != m.lastf.type.mod)
2791         {
2792             if (tthis.mod == tf.mod) goto LfIsBetter;
2793             if (tthis.mod == m.lastf.type.mod) goto LlastIsBetter;
2794         }
2795 
2796         m.nextf = fd;
2797         m.count++;
2798         return 0;
2799 
2800     LlastIsBetter:
2801         return 0;
2802 
2803     LfIsBetter:
2804         td_best = null;
2805         ti_best = null;
2806         ta_last = MATCH.exact;
2807         m.last = mfa;
2808         m.lastf = fd;
2809         tthis_best = tthis_fd;
2810         ov_index = 0;
2811         m.count = 1;
2812         return 0;
2813 
2814     }
2815 
applyTemplate(TemplateDeclaration td)2816     int applyTemplate(TemplateDeclaration td)
2817     {
2818         //printf("applyTemplate()\n");
2819         if (td.inuse)
2820         {
2821             td.error(loc, "recursive template expansion");
2822             return 1;
2823         }
2824         if (td == td_best)   // skip duplicates
2825             return 0;
2826 
2827         if (!sc)
2828             sc = td._scope; // workaround for Type.aliasthisOf
2829 
2830         if (td.semanticRun == PASS.initial && td._scope)
2831         {
2832             // Try to fix forward reference. Ungag errors while doing so.
2833             Ungag ungag = td.ungagSpeculative();
2834             td.dsymbolSemantic(td._scope);
2835         }
2836         if (td.semanticRun == PASS.initial)
2837         {
2838             .error(loc, "forward reference to template `%s`", td.toChars());
2839         Lerror:
2840             m.lastf = null;
2841             m.count = 0;
2842             m.last = MATCH.nomatch;
2843             return 1;
2844         }
2845         //printf("td = %s\n", td.toChars());
2846 
2847         auto f = td.onemember ? td.onemember.isFuncDeclaration() : null;
2848         if (!f)
2849         {
2850             if (!tiargs)
2851                 tiargs = new Objects();
2852             auto ti = new TemplateInstance(loc, td, tiargs);
2853             Objects dedtypes = Objects(td.parameters.dim);
2854             assert(td.semanticRun != PASS.initial);
2855             MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0);
2856             //printf("matchWithInstance = %d\n", mta);
2857             if (mta == MATCH.nomatch || mta < ta_last)   // no match or less match
2858                 return 0;
2859 
2860             ti.templateInstanceSemantic(sc, fargs);
2861             if (!ti.inst)               // if template failed to expand
2862                 return 0;
2863 
2864             Dsymbol s = ti.inst.toAlias();
2865             FuncDeclaration fd;
2866             if (auto tdx = s.isTemplateDeclaration())
2867             {
2868                 Objects dedtypesX;      // empty tiargs
2869 
2870                 // https://issues.dlang.org/show_bug.cgi?id=11553
2871                 // Check for recursive instantiation of tdx.
2872                 for (TemplatePrevious* p = tdx.previous; p; p = p.prev)
2873                 {
2874                     if (arrayObjectMatch(p.dedargs, &dedtypesX))
2875                     {
2876                         //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
2877                         /* It must be a subscope of p.sc, other scope chains are not recursive
2878                          * instantiations.
2879                          */
2880                         for (Scope* scx = sc; scx; scx = scx.enclosing)
2881                         {
2882                             if (scx == p.sc)
2883                             {
2884                                 error(loc, "recursive template expansion while looking for `%s.%s`", ti.toChars(), tdx.toChars());
2885                                 goto Lerror;
2886                             }
2887                         }
2888                     }
2889                     /* BUG: should also check for ref param differences
2890                      */
2891                 }
2892 
2893                 TemplatePrevious pr;
2894                 pr.prev = tdx.previous;
2895                 pr.sc = sc;
2896                 pr.dedargs = &dedtypesX;
2897                 tdx.previous = &pr;             // add this to threaded list
2898 
2899                 fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, FuncResolveFlag.quiet);
2900 
2901                 tdx.previous = pr.prev;         // unlink from threaded list
2902             }
2903             else if (s.isFuncDeclaration())
2904             {
2905                 fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, FuncResolveFlag.quiet);
2906             }
2907             else
2908                 goto Lerror;
2909 
2910             if (!fd)
2911                 return 0;
2912 
2913             if (fd.type.ty != Tfunction)
2914             {
2915                 m.lastf = fd;   // to propagate "error match"
2916                 m.count = 1;
2917                 m.last = MATCH.nomatch;
2918                 return 1;
2919             }
2920 
2921             Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null;
2922 
2923             auto tf = cast(TypeFunction)fd.type;
2924             MATCH mfa = tf.callMatch(tthis_fd, fargs_, 0, null, sc);
2925             if (mfa < m.last)
2926                 return 0;
2927 
2928             if (mta < ta_last) goto Ltd_best2;
2929             if (mta > ta_last) goto Ltd2;
2930 
2931             if (mfa < m.last) goto Ltd_best2;
2932             if (mfa > m.last) goto Ltd2;
2933 
2934             // td_best and td are ambiguous
2935             //printf("Lambig2\n");
2936             m.nextf = fd;
2937             m.count++;
2938             return 0;
2939 
2940         Ltd_best2:
2941             return 0;
2942 
2943         Ltd2:
2944             // td is the new best match
2945             assert(td._scope);
2946             td_best = td;
2947             ti_best = null;
2948             property = 0;   // (backward compatibility)
2949             ta_last = mta;
2950             m.last = mfa;
2951             m.lastf = fd;
2952             tthis_best = tthis_fd;
2953             ov_index = 0;
2954             m.nextf = null;
2955             m.count = 1;
2956             return 0;
2957         }
2958 
2959         //printf("td = %s\n", td.toChars());
2960         for (size_t ovi = 0; f; f = f.overnext0, ovi++)
2961         {
2962             if (f.type.ty != Tfunction || f.errors)
2963                 goto Lerror;
2964 
2965             /* This is a 'dummy' instance to evaluate constraint properly.
2966              */
2967             auto ti = new TemplateInstance(loc, td, tiargs);
2968             ti.parent = td.parent;  // Maybe calculating valid 'enclosing' is unnecessary.
2969 
2970             auto fd = f;
2971             MATCHpair x = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, fargs);
2972             MATCH mta = x.mta;
2973             MATCH mfa = x.mfa;
2974             //printf("match:t/f = %d/%d\n", mta, mfa);
2975             if (!fd || mfa == MATCH.nomatch)
2976                 continue;
2977 
2978             Type tthis_fd = fd.needThis() ? tthis : null;
2979 
2980             bool isCtorCall = tthis_fd && fd.isCtorDeclaration();
2981             if (isCtorCall)
2982             {
2983                 // Constructor call requires additional check.
2984 
2985                 auto tf = cast(TypeFunction)fd.type;
2986                 assert(tf.next);
2987                 if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
2988                     tf.isWild() && tf.isShared() == tthis_fd.isShared() ||
2989                     fd.isReturnIsolated())
2990                 {
2991                     tthis_fd = null;
2992                 }
2993                 else
2994                     continue;   // MATCH.nomatch
2995             }
2996 
2997             if (mta < ta_last) goto Ltd_best;
2998             if (mta > ta_last) goto Ltd;
2999 
3000             if (mfa < m.last) goto Ltd_best;
3001             if (mfa > m.last) goto Ltd;
3002 
3003             if (td_best)
3004             {
3005                 // Disambiguate by picking the most specialized TemplateDeclaration
3006                 MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs);
3007                 MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs);
3008                 //printf("1: c1 = %d, c2 = %d\n", c1, c2);
3009                 if (c1 > c2) goto Ltd;
3010                 if (c1 < c2) goto Ltd_best;
3011             }
3012             assert(fd && m.lastf);
3013             {
3014                 // Disambiguate by tf.callMatch
3015                 auto tf1 = fd.type.isTypeFunction();
3016                 auto tf2 = m.lastf.type.isTypeFunction();
3017                 MATCH c1 = tf1.callMatch(tthis_fd, fargs_, 0, null, sc);
3018                 MATCH c2 = tf2.callMatch(tthis_best, fargs_, 0, null, sc);
3019                 //printf("2: c1 = %d, c2 = %d\n", c1, c2);
3020                 if (c1 > c2) goto Ltd;
3021                 if (c1 < c2) goto Ltd_best;
3022             }
3023             {
3024                 // Disambiguate by picking the most specialized FunctionDeclaration
3025                 MATCH c1 = fd.leastAsSpecialized(m.lastf);
3026                 MATCH c2 = m.lastf.leastAsSpecialized(fd);
3027                 //printf("3: c1 = %d, c2 = %d\n", c1, c2);
3028                 if (c1 > c2) goto Ltd;
3029                 if (c1 < c2) goto Ltd_best;
3030             }
3031 
3032             // https://issues.dlang.org/show_bug.cgi?id=14450
3033             // Prefer exact qualified constructor for the creating object type
3034             if (isCtorCall && fd.type.mod != m.lastf.type.mod)
3035             {
3036                 if (tthis.mod == fd.type.mod) goto Ltd;
3037                 if (tthis.mod == m.lastf.type.mod) goto Ltd_best;
3038             }
3039 
3040             m.nextf = fd;
3041             m.count++;
3042             continue;
3043 
3044         Ltd_best:           // td_best is the best match so far
3045             //printf("Ltd_best\n");
3046             continue;
3047 
3048         Ltd:                // td is the new best match
3049             //printf("Ltd\n");
3050             assert(td._scope);
3051             td_best = td;
3052             ti_best = ti;
3053             property = 0;   // (backward compatibility)
3054             ta_last = mta;
3055             m.last = mfa;
3056             m.lastf = fd;
3057             tthis_best = tthis_fd;
3058             ov_index = ovi;
3059             m.nextf = null;
3060             m.count = 1;
3061             continue;
3062         }
3063         return 0;
3064     }
3065 
3066     auto td = dstart.isTemplateDeclaration();
3067     if (td && td.funcroot)
3068         dstart = td.funcroot;
3069     overloadApply(dstart, (Dsymbol s)
3070     {
3071         if (s.errors)
3072             return 0;
3073         if (auto fd = s.isFuncDeclaration())
3074             return applyFunction(fd);
3075         if (auto td = s.isTemplateDeclaration())
3076             return applyTemplate(td);
3077         return 0;
3078     }, sc);
3079 
3080     //printf("td_best = %p, m.lastf = %p\n", td_best, m.lastf);
3081     if (td_best && ti_best && m.count == 1)
3082     {
3083         // Matches to template function
3084         assert(td_best.onemember && td_best.onemember.isFuncDeclaration());
3085         /* The best match is td_best with arguments tdargs.
3086          * Now instantiate the template.
3087          */
3088         assert(td_best._scope);
3089         if (!sc)
3090             sc = td_best._scope; // workaround for Type.aliasthisOf
3091 
3092         auto ti = new TemplateInstance(loc, td_best, ti_best.tiargs);
3093         ti.templateInstanceSemantic(sc, fargs);
3094 
3095         m.lastf = ti.toAlias().isFuncDeclaration();
3096         if (!m.lastf)
3097             goto Lnomatch;
3098         if (ti.errors)
3099         {
3100         Lerror:
3101             m.count = 1;
3102             assert(m.lastf);
3103             m.last = MATCH.nomatch;
3104             return;
3105         }
3106 
3107         // look forward instantiated overload function
3108         // Dsymbol.oneMembers is alredy called in TemplateInstance.semantic.
3109         // it has filled overnext0d
3110         while (ov_index--)
3111         {
3112             m.lastf = m.lastf.overnext0;
3113             assert(m.lastf);
3114         }
3115 
3116         tthis_best = m.lastf.needThis() && !m.lastf.isCtorDeclaration() ? tthis : null;
3117 
3118         if (m.lastf.type.ty == Terror)
3119             goto Lerror;
3120         auto tf = m.lastf.type.isTypeFunction();
3121         if (!tf.callMatch(tthis_best, fargs_, 0, null, sc))
3122             goto Lnomatch;
3123 
3124         /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows,
3125          * a template instance can be matched while instantiating
3126          * that same template. Thus, the function type can be incomplete. Complete it.
3127          *
3128          * https://issues.dlang.org/show_bug.cgi?id=9208
3129          * For auto function, completion should be deferred to the end of
3130          * its semantic3. Should not complete it in here.
3131          */
3132         if (tf.next && !m.lastf.inferRetType)
3133         {
3134             m.lastf.type = tf.typeSemantic(loc, sc);
3135         }
3136     }
3137     else if (m.lastf)
3138     {
3139         // Matches to non template function,
3140         // or found matches were ambiguous.
3141         assert(m.count >= 1);
3142     }
3143     else
3144     {
3145     Lnomatch:
3146         m.count = 0;
3147         m.lastf = null;
3148         m.last = MATCH.nomatch;
3149     }
3150 }
3151 
3152 /* ======================== Type ============================================ */
3153 
3154 /****
3155  * Given an identifier, figure out which TemplateParameter it is.
3156  * Return IDX_NOTFOUND if not found.
3157  */
templateIdentifierLookup(Identifier id,TemplateParameters * parameters)3158 private size_t templateIdentifierLookup(Identifier id, TemplateParameters* parameters)
3159 {
3160     for (size_t i = 0; i < parameters.dim; i++)
3161     {
3162         TemplateParameter tp = (*parameters)[i];
3163         if (tp.ident.equals(id))
3164             return i;
3165     }
3166     return IDX_NOTFOUND;
3167 }
3168 
templateParameterLookup(Type tparam,TemplateParameters * parameters)3169 private size_t templateParameterLookup(Type tparam, TemplateParameters* parameters)
3170 {
3171     if (tparam.ty == Tident)
3172     {
3173         TypeIdentifier tident = cast(TypeIdentifier)tparam;
3174         //printf("\ttident = '%s'\n", tident.toChars());
3175         return templateIdentifierLookup(tident.ident, parameters);
3176     }
3177     return IDX_NOTFOUND;
3178 }
3179 
deduceWildHelper(Type t,Type * at,Type tparam)3180 private ubyte deduceWildHelper(Type t, Type* at, Type tparam)
3181 {
3182     if ((tparam.mod & MODFlags.wild) == 0)
3183         return 0;
3184 
3185     *at = null;
3186 
3187     auto X(T, U)(T U, U T)
3188     {
3189         return (U << 4) | T;
3190     }
3191 
3192     switch (X(tparam.mod, t.mod))
3193     {
3194     case X(MODFlags.wild, 0):
3195     case X(MODFlags.wild, MODFlags.const_):
3196     case X(MODFlags.wild, MODFlags.shared_):
3197     case X(MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3198     case X(MODFlags.wild, MODFlags.immutable_):
3199     case X(MODFlags.wildconst, 0):
3200     case X(MODFlags.wildconst, MODFlags.const_):
3201     case X(MODFlags.wildconst, MODFlags.shared_):
3202     case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3203     case X(MODFlags.wildconst, MODFlags.immutable_):
3204     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_):
3205     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3206     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.immutable_):
3207     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_):
3208     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3209     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.immutable_):
3210         {
3211             ubyte wm = (t.mod & ~MODFlags.shared_);
3212             if (wm == 0)
3213                 wm = MODFlags.mutable;
3214             ubyte m = (t.mod & (MODFlags.const_ | MODFlags.immutable_)) | (tparam.mod & t.mod & MODFlags.shared_);
3215             *at = t.unqualify(m);
3216             return wm;
3217         }
3218     case X(MODFlags.wild, MODFlags.wild):
3219     case X(MODFlags.wild, MODFlags.wildconst):
3220     case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3221     case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3222     case X(MODFlags.wildconst, MODFlags.wild):
3223     case X(MODFlags.wildconst, MODFlags.wildconst):
3224     case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3225     case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3226     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3227     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3228     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3229     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3230         {
3231             *at = t.unqualify(tparam.mod & t.mod);
3232             return MODFlags.wild;
3233         }
3234     default:
3235         return 0;
3236     }
3237 }
3238 
3239 /**
3240  * Returns the common type of the 2 types.
3241  */
rawTypeMerge(Type t1,Type t2)3242 private Type rawTypeMerge(Type t1, Type t2)
3243 {
3244     if (t1.equals(t2))
3245         return t1;
3246     if (t1.equivalent(t2))
3247         return t1.castMod(MODmerge(t1.mod, t2.mod));
3248 
3249     auto t1b = t1.toBasetype();
3250     auto t2b = t2.toBasetype();
3251     if (t1b.equals(t2b))
3252         return t1b;
3253     if (t1b.equivalent(t2b))
3254         return t1b.castMod(MODmerge(t1b.mod, t2b.mod));
3255 
3256     auto ty = implicitConvCommonTy(t1b.ty, t2b.ty);
3257     if (ty != Terror)
3258         return Type.basic[ty];
3259 
3260     return null;
3261 }
3262 
deduceTypeHelper(Type t,Type * at,Type tparam)3263 private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
3264 {
3265     // 9*9 == 81 cases
3266 
3267     auto X(T, U)(T U, U T)
3268     {
3269         return (U << 4) | T;
3270     }
3271 
3272     switch (X(tparam.mod, t.mod))
3273     {
3274     case X(0, 0):
3275     case X(0, MODFlags.const_):
3276     case X(0, MODFlags.wild):
3277     case X(0, MODFlags.wildconst):
3278     case X(0, MODFlags.shared_):
3279     case X(0, MODFlags.shared_ | MODFlags.const_):
3280     case X(0, MODFlags.shared_ | MODFlags.wild):
3281     case X(0, MODFlags.shared_ | MODFlags.wildconst):
3282     case X(0, MODFlags.immutable_):
3283         // foo(U)                       T                       => T
3284         // foo(U)                       const(T)                => const(T)
3285         // foo(U)                       inout(T)                => inout(T)
3286         // foo(U)                       inout(const(T))         => inout(const(T))
3287         // foo(U)                       shared(T)               => shared(T)
3288         // foo(U)                       shared(const(T))        => shared(const(T))
3289         // foo(U)                       shared(inout(T))        => shared(inout(T))
3290         // foo(U)                       shared(inout(const(T))) => shared(inout(const(T)))
3291         // foo(U)                       immutable(T)            => immutable(T)
3292         {
3293             *at = t;
3294             return MATCH.exact;
3295         }
3296     case X(MODFlags.const_, MODFlags.const_):
3297     case X(MODFlags.wild, MODFlags.wild):
3298     case X(MODFlags.wildconst, MODFlags.wildconst):
3299     case X(MODFlags.shared_, MODFlags.shared_):
3300     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.const_):
3301     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3302     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3303     case X(MODFlags.immutable_, MODFlags.immutable_):
3304         // foo(const(U))                const(T)                => T
3305         // foo(inout(U))                inout(T)                => T
3306         // foo(inout(const(U)))         inout(const(T))         => T
3307         // foo(shared(U))               shared(T)               => T
3308         // foo(shared(const(U)))        shared(const(T))        => T
3309         // foo(shared(inout(U)))        shared(inout(T))        => T
3310         // foo(shared(inout(const(U)))) shared(inout(const(T))) => T
3311         // foo(immutable(U))            immutable(T)            => T
3312         {
3313             *at = t.mutableOf().unSharedOf();
3314             return MATCH.exact;
3315         }
3316     case X(MODFlags.const_, MODFlags.shared_ | MODFlags.const_):
3317     case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3318     case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3319         // foo(const(U))                shared(const(T))        => shared(T)
3320         // foo(inout(U))                shared(inout(T))        => shared(T)
3321         // foo(inout(const(U)))         shared(inout(const(T))) => shared(T)
3322         {
3323             *at = t.mutableOf();
3324             return MATCH.exact;
3325         }
3326     case X(MODFlags.const_, 0):
3327     case X(MODFlags.const_, MODFlags.wild):
3328     case X(MODFlags.const_, MODFlags.wildconst):
3329     case X(MODFlags.const_, MODFlags.shared_ | MODFlags.wild):
3330     case X(MODFlags.const_, MODFlags.shared_ | MODFlags.wildconst):
3331     case X(MODFlags.const_, MODFlags.immutable_):
3332     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.immutable_):
3333         // foo(const(U))                T                       => T
3334         // foo(const(U))                inout(T)                => T
3335         // foo(const(U))                inout(const(T))         => T
3336         // foo(const(U))                shared(inout(T))        => shared(T)
3337         // foo(const(U))                shared(inout(const(T))) => shared(T)
3338         // foo(const(U))                immutable(T)            => T
3339         // foo(shared(const(U)))        immutable(T)            => T
3340         {
3341             *at = t.mutableOf();
3342             return MATCH.constant;
3343         }
3344     case X(MODFlags.const_, MODFlags.shared_):
3345         // foo(const(U))                shared(T)               => shared(T)
3346         {
3347             *at = t;
3348             return MATCH.constant;
3349         }
3350     case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.const_):
3351     case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wild):
3352     case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wildconst):
3353         // foo(shared(U))               shared(const(T))        => const(T)
3354         // foo(shared(U))               shared(inout(T))        => inout(T)
3355         // foo(shared(U))               shared(inout(const(T))) => inout(const(T))
3356         {
3357             *at = t.unSharedOf();
3358             return MATCH.exact;
3359         }
3360     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_):
3361         // foo(shared(const(U)))        shared(T)               => T
3362         {
3363             *at = t.unSharedOf();
3364             return MATCH.constant;
3365         }
3366     case X(MODFlags.wildconst, MODFlags.immutable_):
3367     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.wildconst):
3368     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.immutable_):
3369     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3370         // foo(inout(const(U)))         immutable(T)            => T
3371         // foo(shared(const(U)))        shared(inout(const(T))) => T
3372         // foo(shared(inout(const(U)))) immutable(T)            => T
3373         // foo(shared(inout(const(U)))) shared(inout(T))        => T
3374         {
3375             *at = t.unSharedOf().mutableOf();
3376             return MATCH.constant;
3377         }
3378     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.wild):
3379         // foo(shared(const(U)))        shared(inout(T))        => T
3380         {
3381             *at = t.unSharedOf().mutableOf();
3382             return MATCH.constant;
3383         }
3384     case X(MODFlags.wild, 0):
3385     case X(MODFlags.wild, MODFlags.const_):
3386     case X(MODFlags.wild, MODFlags.wildconst):
3387     case X(MODFlags.wild, MODFlags.immutable_):
3388     case X(MODFlags.wild, MODFlags.shared_):
3389     case X(MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3390     case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3391     case X(MODFlags.wildconst, 0):
3392     case X(MODFlags.wildconst, MODFlags.const_):
3393     case X(MODFlags.wildconst, MODFlags.wild):
3394     case X(MODFlags.wildconst, MODFlags.shared_):
3395     case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3396     case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3397     case X(MODFlags.shared_, 0):
3398     case X(MODFlags.shared_, MODFlags.const_):
3399     case X(MODFlags.shared_, MODFlags.wild):
3400     case X(MODFlags.shared_, MODFlags.wildconst):
3401     case X(MODFlags.shared_, MODFlags.immutable_):
3402     case X(MODFlags.shared_ | MODFlags.const_, 0):
3403     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.const_):
3404     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.wild):
3405     case X(MODFlags.shared_ | MODFlags.const_, MODFlags.wildconst):
3406     case X(MODFlags.shared_ | MODFlags.wild, 0):
3407     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.const_):
3408     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.wild):
3409     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.wildconst):
3410     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.immutable_):
3411     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_):
3412     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3413     case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3414     case X(MODFlags.shared_ | MODFlags.wildconst, 0):
3415     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.const_):
3416     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.wild):
3417     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.wildconst):
3418     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_):
3419     case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3420     case X(MODFlags.immutable_, 0):
3421     case X(MODFlags.immutable_, MODFlags.const_):
3422     case X(MODFlags.immutable_, MODFlags.wild):
3423     case X(MODFlags.immutable_, MODFlags.wildconst):
3424     case X(MODFlags.immutable_, MODFlags.shared_):
3425     case X(MODFlags.immutable_, MODFlags.shared_ | MODFlags.const_):
3426     case X(MODFlags.immutable_, MODFlags.shared_ | MODFlags.wild):
3427     case X(MODFlags.immutable_, MODFlags.shared_ | MODFlags.wildconst):
3428         // foo(inout(U))                T                       => nomatch
3429         // foo(inout(U))                const(T)                => nomatch
3430         // foo(inout(U))                inout(const(T))         => nomatch
3431         // foo(inout(U))                immutable(T)            => nomatch
3432         // foo(inout(U))                shared(T)               => nomatch
3433         // foo(inout(U))                shared(const(T))        => nomatch
3434         // foo(inout(U))                shared(inout(const(T))) => nomatch
3435         // foo(inout(const(U)))         T                       => nomatch
3436         // foo(inout(const(U)))         const(T)                => nomatch
3437         // foo(inout(const(U)))         inout(T)                => nomatch
3438         // foo(inout(const(U)))         shared(T)               => nomatch
3439         // foo(inout(const(U)))         shared(const(T))        => nomatch
3440         // foo(inout(const(U)))         shared(inout(T))        => nomatch
3441         // foo(shared(U))               T                       => nomatch
3442         // foo(shared(U))               const(T)                => nomatch
3443         // foo(shared(U))               inout(T)                => nomatch
3444         // foo(shared(U))               inout(const(T))         => nomatch
3445         // foo(shared(U))               immutable(T)            => nomatch
3446         // foo(shared(const(U)))        T                       => nomatch
3447         // foo(shared(const(U)))        const(T)                => nomatch
3448         // foo(shared(const(U)))        inout(T)                => nomatch
3449         // foo(shared(const(U)))        inout(const(T))         => nomatch
3450         // foo(shared(inout(U)))        T                       => nomatch
3451         // foo(shared(inout(U)))        const(T)                => nomatch
3452         // foo(shared(inout(U)))        inout(T)                => nomatch
3453         // foo(shared(inout(U)))        inout(const(T))         => nomatch
3454         // foo(shared(inout(U)))        immutable(T)            => nomatch
3455         // foo(shared(inout(U)))        shared(T)               => nomatch
3456         // foo(shared(inout(U)))        shared(const(T))        => nomatch
3457         // foo(shared(inout(U)))        shared(inout(const(T))) => nomatch
3458         // foo(shared(inout(const(U)))) T                       => nomatch
3459         // foo(shared(inout(const(U)))) const(T)                => nomatch
3460         // foo(shared(inout(const(U)))) inout(T)                => nomatch
3461         // foo(shared(inout(const(U)))) inout(const(T))         => nomatch
3462         // foo(shared(inout(const(U)))) shared(T)               => nomatch
3463         // foo(shared(inout(const(U)))) shared(const(T))        => nomatch
3464         // foo(immutable(U))            T                       => nomatch
3465         // foo(immutable(U))            const(T)                => nomatch
3466         // foo(immutable(U))            inout(T)                => nomatch
3467         // foo(immutable(U))            inout(const(T))         => nomatch
3468         // foo(immutable(U))            shared(T)               => nomatch
3469         // foo(immutable(U))            shared(const(T))        => nomatch
3470         // foo(immutable(U))            shared(inout(T))        => nomatch
3471         // foo(immutable(U))            shared(inout(const(T))) => nomatch
3472         return MATCH.nomatch;
3473 
3474     default:
3475         assert(0);
3476     }
3477 }
3478 
3479 __gshared Expression emptyArrayElement = null;
3480 
3481 /* These form the heart of template argument deduction.
3482  * Given 'this' being the type argument to the template instance,
3483  * it is matched against the template declaration parameter specialization
3484  * 'tparam' to determine the type to be used for the parameter.
3485  * Example:
3486  *      template Foo(T:T*)      // template declaration
3487  *      Foo!(int*)              // template instantiation
3488  * Input:
3489  *      this = int*
3490  *      tparam = T*
3491  *      parameters = [ T:T* ]   // Array of TemplateParameter's
3492  * Output:
3493  *      dedtypes = [ int ]      // Array of Expression/Type's
3494  */
3495 MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm = null, size_t inferStart = 0, bool ignoreAliasThis = false)
3496 {
3497     extern (C++) final class DeduceType : Visitor
3498     {
3499         alias visit = Visitor.visit;
3500     public:
3501         Scope* sc;
3502         Type tparam;
3503         TemplateParameters* parameters;
3504         Objects* dedtypes;
3505         uint* wm;
3506         size_t inferStart;
3507         bool ignoreAliasThis;
3508         MATCH result;
3509 
this(Scope * sc,Type tparam,TemplateParameters * parameters,Objects * dedtypes,uint * wm,size_t inferStart,bool ignoreAliasThis)3510         extern (D) this(Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm, size_t inferStart, bool ignoreAliasThis)
3511         {
3512             this.sc = sc;
3513             this.tparam = tparam;
3514             this.parameters = parameters;
3515             this.dedtypes = dedtypes;
3516             this.wm = wm;
3517             this.inferStart = inferStart;
3518             this.ignoreAliasThis = ignoreAliasThis;
3519             result = MATCH.nomatch;
3520         }
3521 
visit(Type t)3522         override void visit(Type t)
3523         {
3524             if (!tparam)
3525                 goto Lnomatch;
3526 
3527             if (t == tparam)
3528                 goto Lexact;
3529 
3530             if (tparam.ty == Tident)
3531             {
3532                 // Determine which parameter tparam is
3533                 size_t i = templateParameterLookup(tparam, parameters);
3534                 if (i == IDX_NOTFOUND)
3535                 {
3536                     if (!sc)
3537                         goto Lnomatch;
3538 
3539                     /* Need a loc to go with the semantic routine.
3540                      */
3541                     Loc loc;
3542                     if (parameters.dim)
3543                     {
3544                         TemplateParameter tp = (*parameters)[0];
3545                         loc = tp.loc;
3546                     }
3547 
3548                     /* BUG: what if tparam is a template instance, that
3549                      * has as an argument another Tident?
3550                      */
3551                     tparam = tparam.typeSemantic(loc, sc);
3552                     assert(tparam.ty != Tident);
3553                     result = deduceType(t, sc, tparam, parameters, dedtypes, wm);
3554                     return;
3555                 }
3556 
3557                 TemplateParameter tp = (*parameters)[i];
3558 
3559                 TypeIdentifier tident = cast(TypeIdentifier)tparam;
3560                 if (tident.idents.dim > 0)
3561                 {
3562                     //printf("matching %s to %s\n", tparam.toChars(), t.toChars());
3563                     Dsymbol s = t.toDsymbol(sc);
3564                     for (size_t j = tident.idents.dim; j-- > 0;)
3565                     {
3566                         RootObject id = tident.idents[j];
3567                         if (id.dyncast() == DYNCAST.identifier)
3568                         {
3569                             if (!s || !s.parent)
3570                                 goto Lnomatch;
3571                             Dsymbol s2 = s.parent.search(Loc.initial, cast(Identifier)id);
3572                             if (!s2)
3573                                 goto Lnomatch;
3574                             s2 = s2.toAlias();
3575                             //printf("[%d] s = %s %s, s2 = %s %s\n", j, s.kind(), s.toChars(), s2.kind(), s2.toChars());
3576                             if (s != s2)
3577                             {
3578                                 if (Type tx = s2.getType())
3579                                 {
3580                                     if (s != tx.toDsymbol(sc))
3581                                         goto Lnomatch;
3582                                 }
3583                                 else
3584                                     goto Lnomatch;
3585                             }
3586                             s = s.parent;
3587                         }
3588                         else
3589                             goto Lnomatch;
3590                     }
3591                     //printf("[e] s = %s\n", s?s.toChars():"(null)");
3592                     if (tp.isTemplateTypeParameter())
3593                     {
3594                         Type tt = s.getType();
3595                         if (!tt)
3596                             goto Lnomatch;
3597                         Type at = cast(Type)(*dedtypes)[i];
3598                         if (at && at.ty == Tnone)
3599                             at = (cast(TypeDeduced)at).tded;
3600                         if (!at || tt.equals(at))
3601                         {
3602                             (*dedtypes)[i] = tt;
3603                             goto Lexact;
3604                         }
3605                     }
3606                     if (tp.isTemplateAliasParameter())
3607                     {
3608                         Dsymbol s2 = cast(Dsymbol)(*dedtypes)[i];
3609                         if (!s2 || s == s2)
3610                         {
3611                             (*dedtypes)[i] = s;
3612                             goto Lexact;
3613                         }
3614                     }
3615                     goto Lnomatch;
3616                 }
3617 
3618                 // Found the corresponding parameter tp
3619                 if (!tp.isTemplateTypeParameter())
3620                     goto Lnomatch;
3621                 Type at = cast(Type)(*dedtypes)[i];
3622                 Type tt;
3623                 if (ubyte wx = wm ? deduceWildHelper(t, &tt, tparam) : 0)
3624                 {
3625                     // type vs (none)
3626                     if (!at)
3627                     {
3628                         (*dedtypes)[i] = tt;
3629                         *wm |= wx;
3630                         result = MATCH.constant;
3631                         return;
3632                     }
3633 
3634                     // type vs expressions
3635                     if (at.ty == Tnone)
3636                     {
3637                         TypeDeduced xt = cast(TypeDeduced)at;
3638                         result = xt.matchAll(tt);
3639                         if (result > MATCH.nomatch)
3640                         {
3641                             (*dedtypes)[i] = tt;
3642                             if (result > MATCH.constant)
3643                                 result = MATCH.constant; // limit level for inout matches
3644                         }
3645                         return;
3646                     }
3647 
3648                     // type vs type
3649                     if (tt.equals(at))
3650                     {
3651                         (*dedtypes)[i] = tt; // Prefer current type match
3652                         goto Lconst;
3653                     }
3654                     if (tt.implicitConvTo(at.constOf()))
3655                     {
3656                         (*dedtypes)[i] = at.constOf().mutableOf();
3657                         *wm |= MODFlags.const_;
3658                         goto Lconst;
3659                     }
3660                     if (at.implicitConvTo(tt.constOf()))
3661                     {
3662                         (*dedtypes)[i] = tt.constOf().mutableOf();
3663                         *wm |= MODFlags.const_;
3664                         goto Lconst;
3665                     }
3666                     goto Lnomatch;
3667                 }
3668                 else if (MATCH m = deduceTypeHelper(t, &tt, tparam))
3669                 {
3670                     // type vs (none)
3671                     if (!at)
3672                     {
3673                         (*dedtypes)[i] = tt;
3674                         result = m;
3675                         return;
3676                     }
3677 
3678                     // type vs expressions
3679                     if (at.ty == Tnone)
3680                     {
3681                         TypeDeduced xt = cast(TypeDeduced)at;
3682                         result = xt.matchAll(tt);
3683                         if (result > MATCH.nomatch)
3684                         {
3685                             (*dedtypes)[i] = tt;
3686                         }
3687                         return;
3688                     }
3689 
3690                     // type vs type
3691                     if (tt.equals(at))
3692                     {
3693                         goto Lexact;
3694                     }
3695                     if (tt.ty == Tclass && at.ty == Tclass)
3696                     {
3697                         result = tt.implicitConvTo(at);
3698                         return;
3699                     }
3700                     if (tt.ty == Tsarray && at.ty == Tarray && tt.nextOf().implicitConvTo(at.nextOf()) >= MATCH.constant)
3701                     {
3702                         goto Lexact;
3703                     }
3704                 }
3705                 goto Lnomatch;
3706             }
3707 
3708             if (tparam.ty == Ttypeof)
3709             {
3710                 /* Need a loc to go with the semantic routine.
3711                  */
3712                 Loc loc;
3713                 if (parameters.dim)
3714                 {
3715                     TemplateParameter tp = (*parameters)[0];
3716                     loc = tp.loc;
3717                 }
3718 
3719                 tparam = tparam.typeSemantic(loc, sc);
3720             }
3721             if (t.ty != tparam.ty)
3722             {
3723                 if (Dsymbol sym = t.toDsymbol(sc))
3724                 {
3725                     if (sym.isforwardRef() && !tparam.deco)
3726                         goto Lnomatch;
3727                 }
3728 
3729                 MATCH m = t.implicitConvTo(tparam);
3730                 if (m == MATCH.nomatch && !ignoreAliasThis)
3731                 {
3732                     if (t.ty == Tclass)
3733                     {
3734                         TypeClass tc = cast(TypeClass)t;
3735                         if (tc.sym.aliasthis && !(tc.att & AliasThisRec.tracingDT))
3736                         {
3737                             if (auto ato = t.aliasthisOf())
3738                             {
3739                                 tc.att = cast(AliasThisRec)(tc.att | AliasThisRec.tracingDT);
3740                                 m = deduceType(ato, sc, tparam, parameters, dedtypes, wm);
3741                                 tc.att = cast(AliasThisRec)(tc.att & ~AliasThisRec.tracingDT);
3742                             }
3743                         }
3744                     }
3745                     else if (t.ty == Tstruct)
3746                     {
3747                         TypeStruct ts = cast(TypeStruct)t;
3748                         if (ts.sym.aliasthis && !(ts.att & AliasThisRec.tracingDT))
3749                         {
3750                             if (auto ato = t.aliasthisOf())
3751                             {
3752                                 ts.att = cast(AliasThisRec)(ts.att | AliasThisRec.tracingDT);
3753                                 m = deduceType(ato, sc, tparam, parameters, dedtypes, wm);
3754                                 ts.att = cast(AliasThisRec)(ts.att & ~AliasThisRec.tracingDT);
3755                             }
3756                         }
3757                     }
3758                 }
3759                 result = m;
3760                 return;
3761             }
3762 
3763             if (t.nextOf())
3764             {
3765                 if (tparam.deco && !tparam.hasWild())
3766                 {
3767                     result = t.implicitConvTo(tparam);
3768                     return;
3769                 }
3770 
3771                 Type tpn = tparam.nextOf();
3772                 if (wm && t.ty == Taarray && tparam.isWild())
3773                 {
3774                     // https://issues.dlang.org/show_bug.cgi?id=12403
3775                     // In IFTI, stop inout matching on transitive part of AA types.
3776                     tpn = tpn.substWildTo(MODFlags.mutable);
3777                 }
3778 
3779                 result = deduceType(t.nextOf(), sc, tpn, parameters, dedtypes, wm);
3780                 return;
3781             }
3782 
3783         Lexact:
3784             result = MATCH.exact;
3785             return;
3786 
3787         Lnomatch:
3788             result = MATCH.nomatch;
3789             return;
3790 
3791         Lconst:
3792             result = MATCH.constant;
3793         }
3794 
visit(TypeVector t)3795         override void visit(TypeVector t)
3796         {
3797             if (tparam.ty == Tvector)
3798             {
3799                 TypeVector tp = cast(TypeVector)tparam;
3800                 result = deduceType(t.basetype, sc, tp.basetype, parameters, dedtypes, wm);
3801                 return;
3802             }
3803             visit(cast(Type)t);
3804         }
3805 
visit(TypeDArray t)3806         override void visit(TypeDArray t)
3807         {
3808             visit(cast(Type)t);
3809         }
3810 
visit(TypeSArray t)3811         override void visit(TypeSArray t)
3812         {
3813             // Extra check that array dimensions must match
3814             if (tparam)
3815             {
3816                 if (tparam.ty == Tarray)
3817                 {
3818                     MATCH m = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
3819                     result = (m >= MATCH.constant) ? MATCH.convert : MATCH.nomatch;
3820                     return;
3821                 }
3822 
3823                 TemplateParameter tp = null;
3824                 Expression edim = null;
3825                 size_t i;
3826                 if (tparam.ty == Tsarray)
3827                 {
3828                     TypeSArray tsa = cast(TypeSArray)tparam;
3829                     if (tsa.dim.op == EXP.variable && (cast(VarExp)tsa.dim).var.storage_class & STC.templateparameter)
3830                     {
3831                         Identifier id = (cast(VarExp)tsa.dim).var.ident;
3832                         i = templateIdentifierLookup(id, parameters);
3833                         assert(i != IDX_NOTFOUND);
3834                         tp = (*parameters)[i];
3835                     }
3836                     else
3837                         edim = tsa.dim;
3838                 }
3839                 else if (tparam.ty == Taarray)
3840                 {
3841                     TypeAArray taa = cast(TypeAArray)tparam;
3842                     i = templateParameterLookup(taa.index, parameters);
3843                     if (i != IDX_NOTFOUND)
3844                         tp = (*parameters)[i];
3845                     else
3846                     {
3847                         Expression e;
3848                         Type tx;
3849                         Dsymbol s;
3850                         taa.index.resolve(Loc.initial, sc, e, tx, s);
3851                         edim = s ? getValue(s) : getValue(e);
3852                     }
3853                 }
3854                 if (tp && tp.matchArg(sc, t.dim, i, parameters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
3855                 {
3856                     result = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
3857                     return;
3858                 }
3859             }
3860             visit(cast(Type)t);
3861         }
3862 
visit(TypeAArray t)3863         override void visit(TypeAArray t)
3864         {
3865             // Extra check that index type must match
3866             if (tparam && tparam.ty == Taarray)
3867             {
3868                 TypeAArray tp = cast(TypeAArray)tparam;
3869                 if (!deduceType(t.index, sc, tp.index, parameters, dedtypes))
3870                 {
3871                     result = MATCH.nomatch;
3872                     return;
3873                 }
3874             }
3875             visit(cast(Type)t);
3876         }
3877 
visit(TypeFunction t)3878         override void visit(TypeFunction t)
3879         {
3880             // Extra check that function characteristics must match
3881             if (!tparam)
3882                 return visit(cast(Type)t);
3883 
3884             if (auto tp = tparam.isTypeFunction())
3885             {
3886                 if (t.parameterList.varargs != tp.parameterList.varargs || t.linkage != tp.linkage)
3887                 {
3888                     result = MATCH.nomatch;
3889                     return;
3890                 }
3891 
3892                 foreach (fparam; *tp.parameterList.parameters)
3893                 {
3894                     // https://issues.dlang.org/show_bug.cgi?id=2579
3895                     // Apply function parameter storage classes to parameter types
3896                     fparam.type = fparam.type.addStorageClass(fparam.storageClass);
3897                     fparam.storageClass &= ~(STC.TYPECTOR | STC.in_);
3898 
3899                     // https://issues.dlang.org/show_bug.cgi?id=15243
3900                     // Resolve parameter type if it's not related with template parameters
3901                     if (!reliesOnTemplateParameters(fparam.type, (*parameters)[inferStart .. parameters.dim]))
3902                     {
3903                         auto tx = fparam.type.typeSemantic(Loc.initial, sc);
3904                         if (tx.ty == Terror)
3905                         {
3906                             result = MATCH.nomatch;
3907                             return;
3908                         }
3909                         fparam.type = tx;
3910                     }
3911                 }
3912 
3913                 size_t nfargs = t.parameterList.length;
3914                 size_t nfparams = tp.parameterList.length;
3915 
3916                 /* See if tuple match
3917                  */
3918                 if (nfparams > 0 && nfargs >= nfparams - 1)
3919                 {
3920                     /* See if 'A' of the template parameter matches 'A'
3921                      * of the type of the last function parameter.
3922                      */
3923                     Parameter fparam = tp.parameterList[nfparams - 1];
3924                     assert(fparam);
3925                     assert(fparam.type);
3926                     if (fparam.type.ty != Tident)
3927                         goto L1;
3928                     TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
3929                     if (tid.idents.dim)
3930                         goto L1;
3931 
3932                     /* Look through parameters to find tuple matching tid.ident
3933                      */
3934                     size_t tupi = 0;
3935                     for (; 1; tupi++)
3936                     {
3937                         if (tupi == parameters.dim)
3938                             goto L1;
3939                         TemplateParameter tx = (*parameters)[tupi];
3940                         TemplateTupleParameter tup = tx.isTemplateTupleParameter();
3941                         if (tup && tup.ident.equals(tid.ident))
3942                             break;
3943                     }
3944 
3945                     /* The types of the function arguments [nfparams - 1 .. nfargs]
3946                      * now form the tuple argument.
3947                      */
3948                     size_t tuple_dim = nfargs - (nfparams - 1);
3949 
3950                     /* See if existing tuple, and whether it matches or not
3951                      */
3952                     RootObject o = (*dedtypes)[tupi];
3953                     if (o)
3954                     {
3955                         // Existing deduced argument must be a tuple, and must match
3956                         Tuple tup = isTuple(o);
3957                         if (!tup || tup.objects.dim != tuple_dim)
3958                         {
3959                             result = MATCH.nomatch;
3960                             return;
3961                         }
3962                         for (size_t i = 0; i < tuple_dim; i++)
3963                         {
3964                             Parameter arg = t.parameterList[nfparams - 1 + i];
3965                             if (!arg.type.equals(tup.objects[i]))
3966                             {
3967                                 result = MATCH.nomatch;
3968                                 return;
3969                             }
3970                         }
3971                     }
3972                     else
3973                     {
3974                         // Create new tuple
3975                         auto tup = new Tuple(tuple_dim);
3976                         for (size_t i = 0; i < tuple_dim; i++)
3977                         {
3978                             Parameter arg = t.parameterList[nfparams - 1 + i];
3979                             tup.objects[i] = arg.type;
3980                         }
3981                         (*dedtypes)[tupi] = tup;
3982                     }
3983                     nfparams--; // don't consider the last parameter for type deduction
3984                     goto L2;
3985                 }
3986 
3987             L1:
3988                 if (nfargs != nfparams)
3989                 {
3990                     result = MATCH.nomatch;
3991                     return;
3992                 }
3993             L2:
3994                 assert(nfparams <= tp.parameterList.length);
3995                 foreach (i, ap; tp.parameterList)
3996                 {
3997                     if (i == nfparams)
3998                         break;
3999 
4000                     Parameter a = t.parameterList[i];
4001 
4002                     if (!a.isCovariant(t.isref, ap) ||
4003                         !deduceType(a.type, sc, ap.type, parameters, dedtypes))
4004                     {
4005                         result = MATCH.nomatch;
4006                         return;
4007                     }
4008                 }
4009             }
4010             visit(cast(Type)t);
4011         }
4012 
visit(TypeIdentifier t)4013         override void visit(TypeIdentifier t)
4014         {
4015             // Extra check
4016             if (tparam && tparam.ty == Tident)
4017             {
4018                 TypeIdentifier tp = cast(TypeIdentifier)tparam;
4019                 for (size_t i = 0; i < t.idents.dim; i++)
4020                 {
4021                     RootObject id1 = t.idents[i];
4022                     RootObject id2 = tp.idents[i];
4023                     if (!id1.equals(id2))
4024                     {
4025                         result = MATCH.nomatch;
4026                         return;
4027                     }
4028                 }
4029             }
4030             visit(cast(Type)t);
4031         }
4032 
visit(TypeInstance t)4033         override void visit(TypeInstance t)
4034         {
4035             // Extra check
4036             if (tparam && tparam.ty == Tinstance && t.tempinst.tempdecl)
4037             {
4038                 TemplateDeclaration tempdecl = t.tempinst.tempdecl.isTemplateDeclaration();
4039                 assert(tempdecl);
4040 
4041                 TypeInstance tp = cast(TypeInstance)tparam;
4042 
4043                 //printf("tempinst.tempdecl = %p\n", tempdecl);
4044                 //printf("tp.tempinst.tempdecl = %p\n", tp.tempinst.tempdecl);
4045                 if (!tp.tempinst.tempdecl)
4046                 {
4047                     //printf("tp.tempinst.name = '%s'\n", tp.tempinst.name.toChars());
4048 
4049                     /* Handle case of:
4050                      *  template Foo(T : sa!(T), alias sa)
4051                      */
4052                     size_t i = templateIdentifierLookup(tp.tempinst.name, parameters);
4053                     if (i == IDX_NOTFOUND)
4054                     {
4055                         /* Didn't find it as a parameter identifier. Try looking
4056                          * it up and seeing if is an alias.
4057                          * https://issues.dlang.org/show_bug.cgi?id=1454
4058                          */
4059                         auto tid = new TypeIdentifier(tp.loc, tp.tempinst.name);
4060                         Type tx;
4061                         Expression e;
4062                         Dsymbol s;
4063                         tid.resolve(tp.loc, sc, e, tx, s);
4064                         if (tx)
4065                         {
4066                             s = tx.toDsymbol(sc);
4067                             if (TemplateInstance ti = s ? s.parent.isTemplateInstance() : null)
4068                             {
4069                                 // https://issues.dlang.org/show_bug.cgi?id=14290
4070                                 // Try to match with ti.tempecl,
4071                                 // only when ti is an enclosing instance.
4072                                 Dsymbol p = sc.parent;
4073                                 while (p && p != ti)
4074                                     p = p.parent;
4075                                 if (p)
4076                                     s = ti.tempdecl;
4077                             }
4078                         }
4079                         if (s)
4080                         {
4081                             s = s.toAlias();
4082                             TemplateDeclaration td = s.isTemplateDeclaration();
4083                             if (td)
4084                             {
4085                                 if (td.overroot)
4086                                     td = td.overroot;
4087                                 for (; td; td = td.overnext)
4088                                 {
4089                                     if (td == tempdecl)
4090                                         goto L2;
4091                                 }
4092                             }
4093                         }
4094                         goto Lnomatch;
4095                     }
4096                     TemplateParameter tpx = (*parameters)[i];
4097                     if (!tpx.matchArg(sc, tempdecl, i, parameters, dedtypes, null))
4098                         goto Lnomatch;
4099                 }
4100                 else if (tempdecl != tp.tempinst.tempdecl)
4101                     goto Lnomatch;
4102 
4103             L2:
4104                 for (size_t i = 0; 1; i++)
4105                 {
4106                     //printf("\ttest: tempinst.tiargs[%d]\n", i);
4107                     RootObject o1 = null;
4108                     if (i < t.tempinst.tiargs.dim)
4109                         o1 = (*t.tempinst.tiargs)[i];
4110                     else if (i < t.tempinst.tdtypes.dim && i < tp.tempinst.tiargs.dim)
4111                     {
4112                         // Pick up default arg
4113                         o1 = t.tempinst.tdtypes[i];
4114                     }
4115                     else if (i >= tp.tempinst.tiargs.dim)
4116                         break;
4117 
4118                     if (i >= tp.tempinst.tiargs.dim)
4119                     {
4120                         size_t dim = tempdecl.parameters.dim - (tempdecl.isVariadic() ? 1 : 0);
4121                         while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
4122                         {
4123                             i++;
4124                         }
4125                         if (i >= dim)
4126                             break; // match if all remained parameters are dependent
4127                         goto Lnomatch;
4128                     }
4129 
4130                     RootObject o2 = (*tp.tempinst.tiargs)[i];
4131                     Type t2 = isType(o2);
4132 
4133                     size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.dim - 1)
4134                         ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
4135                     if (j != IDX_NOTFOUND && j == parameters.dim - 1 &&
4136                         (*parameters)[j].isTemplateTupleParameter())
4137                     {
4138                         /* Given:
4139                          *  struct A(B...) {}
4140                          *  alias A!(int, float) X;
4141                          *  static if (is(X Y == A!(Z), Z...)) {}
4142                          * deduce that Z is a tuple(int, float)
4143                          */
4144 
4145                         /* Create tuple from remaining args
4146                          */
4147                         size_t vtdim = (tempdecl.isVariadic() ? t.tempinst.tiargs.dim : t.tempinst.tdtypes.dim) - i;
4148                         auto vt = new Tuple(vtdim);
4149                         for (size_t k = 0; k < vtdim; k++)
4150                         {
4151                             RootObject o;
4152                             if (k < t.tempinst.tiargs.dim)
4153                                 o = (*t.tempinst.tiargs)[i + k];
4154                             else // Pick up default arg
4155                                 o = t.tempinst.tdtypes[i + k];
4156                             vt.objects[k] = o;
4157                         }
4158 
4159                         Tuple v = cast(Tuple)(*dedtypes)[j];
4160                         if (v)
4161                         {
4162                             if (!match(v, vt))
4163                                 goto Lnomatch;
4164                         }
4165                         else
4166                             (*dedtypes)[j] = vt;
4167                         break;
4168                     }
4169                     else if (!o1)
4170                         break;
4171 
4172                     Type t1 = isType(o1);
4173                     Dsymbol s1 = isDsymbol(o1);
4174                     Dsymbol s2 = isDsymbol(o2);
4175                     Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
4176                     Expression e2 = isExpression(o2);
4177                     version (none)
4178                     {
4179                         Tuple v1 = isTuple(o1);
4180                         Tuple v2 = isTuple(o2);
4181                         if (t1)
4182                             printf("t1 = %s\n", t1.toChars());
4183                         if (t2)
4184                             printf("t2 = %s\n", t2.toChars());
4185                         if (e1)
4186                             printf("e1 = %s\n", e1.toChars());
4187                         if (e2)
4188                             printf("e2 = %s\n", e2.toChars());
4189                         if (s1)
4190                             printf("s1 = %s\n", s1.toChars());
4191                         if (s2)
4192                             printf("s2 = %s\n", s2.toChars());
4193                         if (v1)
4194                             printf("v1 = %s\n", v1.toChars());
4195                         if (v2)
4196                             printf("v2 = %s\n", v2.toChars());
4197                     }
4198 
4199                     if (t1 && t2)
4200                     {
4201                         if (!deduceType(t1, sc, t2, parameters, dedtypes))
4202                             goto Lnomatch;
4203                     }
4204                     else if (e1 && e2)
4205                     {
4206                     Le:
4207                         e1 = e1.ctfeInterpret();
4208 
4209                         /* If it is one of the template parameters for this template,
4210                          * we should not attempt to interpret it. It already has a value.
4211                          */
4212                         if (e2.op == EXP.variable && ((cast(VarExp)e2).var.storage_class & STC.templateparameter))
4213                         {
4214                             /*
4215                              * (T:Number!(e2), int e2)
4216                              */
4217                             j = templateIdentifierLookup((cast(VarExp)e2).var.ident, parameters);
4218                             if (j != IDX_NOTFOUND)
4219                                 goto L1;
4220                             // The template parameter was not from this template
4221                             // (it may be from a parent template, for example)
4222                         }
4223 
4224                         e2 = e2.expressionSemantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
4225                         e2 = e2.ctfeInterpret();
4226 
4227                         //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
4228                         //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
4229                         if (!e1.equals(e2))
4230                         {
4231                             if (!e2.implicitConvTo(e1.type))
4232                                 goto Lnomatch;
4233 
4234                             e2 = e2.implicitCastTo(sc, e1.type);
4235                             e2 = e2.ctfeInterpret();
4236                             if (!e1.equals(e2))
4237                                 goto Lnomatch;
4238                         }
4239                     }
4240                     else if (e1 && t2 && t2.ty == Tident)
4241                     {
4242                         j = templateParameterLookup(t2, parameters);
4243                     L1:
4244                         if (j == IDX_NOTFOUND)
4245                         {
4246                             t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
4247                             if (e2)
4248                                 goto Le;
4249                             goto Lnomatch;
4250                         }
4251                         if (!(*parameters)[j].matchArg(sc, e1, j, parameters, dedtypes, null))
4252                             goto Lnomatch;
4253                     }
4254                     else if (s1 && s2)
4255                     {
4256                     Ls:
4257                         if (!s1.equals(s2))
4258                             goto Lnomatch;
4259                     }
4260                     else if (s1 && t2 && t2.ty == Tident)
4261                     {
4262                         j = templateParameterLookup(t2, parameters);
4263                         if (j == IDX_NOTFOUND)
4264                         {
4265                             t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
4266                             if (s2)
4267                                 goto Ls;
4268                             goto Lnomatch;
4269                         }
4270                         if (!(*parameters)[j].matchArg(sc, s1, j, parameters, dedtypes, null))
4271                             goto Lnomatch;
4272                     }
4273                     else
4274                         goto Lnomatch;
4275                 }
4276             }
4277             visit(cast(Type)t);
4278             return;
4279 
4280         Lnomatch:
4281             //printf("no match\n");
4282             result = MATCH.nomatch;
4283         }
4284 
visit(TypeStruct t)4285         override void visit(TypeStruct t)
4286         {
4287             /* If this struct is a template struct, and we're matching
4288              * it against a template instance, convert the struct type
4289              * to a template instance, too, and try again.
4290              */
4291             TemplateInstance ti = t.sym.parent.isTemplateInstance();
4292 
4293             if (tparam && tparam.ty == Tinstance)
4294             {
4295                 if (ti && ti.toAlias() == t.sym)
4296                 {
4297                     auto tx = new TypeInstance(Loc.initial, ti);
4298                     auto m = deduceType(tx, sc, tparam, parameters, dedtypes, wm);
4299                     // if we have a no match we still need to check alias this
4300                     if (m != MATCH.nomatch)
4301                     {
4302                         result = m;
4303                         return;
4304                     }
4305                 }
4306 
4307                 /* Match things like:
4308                  *  S!(T).foo
4309                  */
4310                 TypeInstance tpi = cast(TypeInstance)tparam;
4311                 if (tpi.idents.dim)
4312                 {
4313                     RootObject id = tpi.idents[tpi.idents.dim - 1];
4314                     if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id))
4315                     {
4316                         Type tparent = t.sym.parent.getType();
4317                         if (tparent)
4318                         {
4319                             /* Slice off the .foo in S!(T).foo
4320                              */
4321                             tpi.idents.dim--;
4322                             result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
4323                             tpi.idents.dim++;
4324                             return;
4325                         }
4326                     }
4327                 }
4328             }
4329 
4330             // Extra check
4331             if (tparam && tparam.ty == Tstruct)
4332             {
4333                 TypeStruct tp = cast(TypeStruct)tparam;
4334 
4335                 //printf("\t%d\n", cast(MATCH) t.implicitConvTo(tp));
4336                 if (wm && t.deduceWild(tparam, false))
4337                 {
4338                     result = MATCH.constant;
4339                     return;
4340                 }
4341                 result = t.implicitConvTo(tp);
4342                 return;
4343             }
4344             visit(cast(Type)t);
4345         }
4346 
visit(TypeEnum t)4347         override void visit(TypeEnum t)
4348         {
4349             // Extra check
4350             if (tparam && tparam.ty == Tenum)
4351             {
4352                 TypeEnum tp = cast(TypeEnum)tparam;
4353                 if (t.sym == tp.sym)
4354                     visit(cast(Type)t);
4355                 else
4356                     result = MATCH.nomatch;
4357                 return;
4358             }
4359             Type tb = t.toBasetype();
4360             if (tb.ty == tparam.ty || tb.ty == Tsarray && tparam.ty == Taarray)
4361             {
4362                 result = deduceType(tb, sc, tparam, parameters, dedtypes, wm);
4363                 if (result == MATCH.exact)
4364                     result = MATCH.convert;
4365                 return;
4366             }
4367             visit(cast(Type)t);
4368         }
4369 
4370         /* Helper for TypeClass.deduceType().
4371          * Classes can match with implicit conversion to a base class or interface.
4372          * This is complicated, because there may be more than one base class which
4373          * matches. In such cases, one or more parameters remain ambiguous.
4374          * For example,
4375          *
4376          *   interface I(X, Y) {}
4377          *   class C : I(uint, double), I(char, double) {}
4378          *   C x;
4379          *   foo(T, U)( I!(T, U) x)
4380          *
4381          *   deduces that U is double, but T remains ambiguous (could be char or uint).
4382          *
4383          * Given a baseclass b, and initial deduced types 'dedtypes', this function
4384          * tries to match tparam with b, and also tries all base interfaces of b.
4385          * If a match occurs, numBaseClassMatches is incremented, and the new deduced
4386          * types are ANDed with the current 'best' estimate for dedtypes.
4387          */
deduceBaseClassParameters(ref BaseClass b,Scope * sc,Type tparam,TemplateParameters * parameters,Objects * dedtypes,Objects * best,ref int numBaseClassMatches)4388         static void deduceBaseClassParameters(ref BaseClass b, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, Objects* best, ref int numBaseClassMatches)
4389         {
4390             TemplateInstance parti = b.sym ? b.sym.parent.isTemplateInstance() : null;
4391             if (parti)
4392             {
4393                 // Make a temporary copy of dedtypes so we don't destroy it
4394                 auto tmpdedtypes = new Objects(dedtypes.dim);
4395                 memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.dim * (void*).sizeof);
4396 
4397                 auto t = new TypeInstance(Loc.initial, parti);
4398                 MATCH m = deduceType(t, sc, tparam, parameters, tmpdedtypes);
4399                 if (m > MATCH.nomatch)
4400                 {
4401                     // If this is the first ever match, it becomes our best estimate
4402                     if (numBaseClassMatches == 0)
4403                         memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.dim * (void*).sizeof);
4404                     else
4405                         for (size_t k = 0; k < tmpdedtypes.dim; ++k)
4406                         {
4407                             // If we've found more than one possible type for a parameter,
4408                             // mark it as unknown.
4409                             if ((*tmpdedtypes)[k] != (*best)[k])
4410                                 (*best)[k] = (*dedtypes)[k];
4411                         }
4412                     ++numBaseClassMatches;
4413                 }
4414             }
4415 
4416             // Now recursively test the inherited interfaces
4417             foreach (ref bi; b.baseInterfaces)
4418             {
4419                 deduceBaseClassParameters(bi, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4420             }
4421         }
4422 
visit(TypeClass t)4423         override void visit(TypeClass t)
4424         {
4425             //printf("TypeClass.deduceType(this = %s)\n", t.toChars());
4426 
4427             /* If this class is a template class, and we're matching
4428              * it against a template instance, convert the class type
4429              * to a template instance, too, and try again.
4430              */
4431             TemplateInstance ti = t.sym.parent.isTemplateInstance();
4432 
4433             if (tparam && tparam.ty == Tinstance)
4434             {
4435                 if (ti && ti.toAlias() == t.sym)
4436                 {
4437                     auto tx = new TypeInstance(Loc.initial, ti);
4438                     MATCH m = deduceType(tx, sc, tparam, parameters, dedtypes, wm);
4439                     // Even if the match fails, there is still a chance it could match
4440                     // a base class.
4441                     if (m != MATCH.nomatch)
4442                     {
4443                         result = m;
4444                         return;
4445                     }
4446                 }
4447 
4448                 /* Match things like:
4449                  *  S!(T).foo
4450                  */
4451                 TypeInstance tpi = cast(TypeInstance)tparam;
4452                 if (tpi.idents.dim)
4453                 {
4454                     RootObject id = tpi.idents[tpi.idents.dim - 1];
4455                     if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id))
4456                     {
4457                         Type tparent = t.sym.parent.getType();
4458                         if (tparent)
4459                         {
4460                             /* Slice off the .foo in S!(T).foo
4461                              */
4462                             tpi.idents.dim--;
4463                             result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
4464                             tpi.idents.dim++;
4465                             return;
4466                         }
4467                     }
4468                 }
4469 
4470                 // If it matches exactly or via implicit conversion, we're done
4471                 visit(cast(Type)t);
4472                 if (result != MATCH.nomatch)
4473                     return;
4474 
4475                 /* There is still a chance to match via implicit conversion to
4476                  * a base class or interface. Because there could be more than one such
4477                  * match, we need to check them all.
4478                  */
4479 
4480                 int numBaseClassMatches = 0; // Have we found an interface match?
4481 
4482                 // Our best guess at dedtypes
4483                 auto best = new Objects(dedtypes.dim);
4484 
4485                 ClassDeclaration s = t.sym;
4486                 while (s && s.baseclasses.dim > 0)
4487                 {
4488                     // Test the base class
4489                     deduceBaseClassParameters(*(*s.baseclasses)[0], sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4490 
4491                     // Test the interfaces inherited by the base class
4492                     foreach (b; s.interfaces)
4493                     {
4494                         deduceBaseClassParameters(*b, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4495                     }
4496                     s = (*s.baseclasses)[0].sym;
4497                 }
4498 
4499                 if (numBaseClassMatches == 0)
4500                 {
4501                     result = MATCH.nomatch;
4502                     return;
4503                 }
4504 
4505                 // If we got at least one match, copy the known types into dedtypes
4506                 memcpy(dedtypes.tdata(), best.tdata(), best.dim * (void*).sizeof);
4507                 result = MATCH.convert;
4508                 return;
4509             }
4510 
4511             // Extra check
4512             if (tparam && tparam.ty == Tclass)
4513             {
4514                 TypeClass tp = cast(TypeClass)tparam;
4515 
4516                 //printf("\t%d\n", cast(MATCH) t.implicitConvTo(tp));
4517                 if (wm && t.deduceWild(tparam, false))
4518                 {
4519                     result = MATCH.constant;
4520                     return;
4521                 }
4522                 result = t.implicitConvTo(tp);
4523                 return;
4524             }
4525             visit(cast(Type)t);
4526         }
4527 
visit(Expression e)4528         override void visit(Expression e)
4529         {
4530             //printf("Expression.deduceType(e = %s)\n", e.toChars());
4531             size_t i = templateParameterLookup(tparam, parameters);
4532             if (i == IDX_NOTFOUND || (cast(TypeIdentifier)tparam).idents.dim > 0)
4533             {
4534                 if (e == emptyArrayElement && tparam.ty == Tarray)
4535                 {
4536                     Type tn = (cast(TypeNext)tparam).next;
4537                     result = deduceType(emptyArrayElement, sc, tn, parameters, dedtypes, wm);
4538                     return;
4539                 }
4540                 e.type.accept(this);
4541                 return;
4542             }
4543 
4544             TemplateTypeParameter tp = (*parameters)[i].isTemplateTypeParameter();
4545             if (!tp)
4546                 return; // nomatch
4547 
4548             if (e == emptyArrayElement)
4549             {
4550                 if ((*dedtypes)[i])
4551                 {
4552                     result = MATCH.exact;
4553                     return;
4554                 }
4555                 if (tp.defaultType)
4556                 {
4557                     tp.defaultType.accept(this);
4558                     return;
4559                 }
4560             }
4561 
4562             /* Returns `true` if `t` is a reference type, or an array of reference types
4563              */
4564             bool isTopRef(Type t)
4565             {
4566                 auto tb = t.baseElemOf();
4567                 return tb.ty == Tclass ||
4568                        tb.ty == Taarray ||
4569                        tb.ty == Tstruct && tb.hasPointers();
4570             }
4571 
4572             Type at = cast(Type)(*dedtypes)[i];
4573             Type tt;
4574             if (ubyte wx = deduceWildHelper(e.type, &tt, tparam))
4575             {
4576                 *wm |= wx;
4577                 result = MATCH.constant;
4578             }
4579             else if (MATCH m = deduceTypeHelper(e.type, &tt, tparam))
4580             {
4581                 result = m;
4582             }
4583             else if (!isTopRef(e.type))
4584             {
4585                 /* https://issues.dlang.org/show_bug.cgi?id=15653
4586                  * In IFTI, recognize top-qualifier conversions
4587                  * through the value copy, e.g.
4588                  *      int --> immutable(int)
4589                  *      immutable(string[]) --> immutable(string)[]
4590                  */
4591                 tt = e.type.mutableOf();
4592                 result = MATCH.convert;
4593             }
4594             else
4595                 return; // nomatch
4596 
4597             // expression vs (none)
4598             if (!at)
4599             {
4600                 (*dedtypes)[i] = new TypeDeduced(tt, e, tparam);
4601                 return;
4602             }
4603 
4604             TypeDeduced xt = null;
4605             if (at.ty == Tnone)
4606             {
4607                 xt = cast(TypeDeduced)at;
4608                 at = xt.tded;
4609             }
4610 
4611             // From previous matched expressions to current deduced type
4612             MATCH match1 = xt ? xt.matchAll(tt) : MATCH.nomatch;
4613 
4614             // From current expressions to previous deduced type
4615             Type pt = at.addMod(tparam.mod);
4616             if (*wm)
4617                 pt = pt.substWildTo(*wm);
4618             MATCH match2 = e.implicitConvTo(pt);
4619 
4620             if (match1 > MATCH.nomatch && match2 > MATCH.nomatch)
4621             {
4622                 if (at.implicitConvTo(tt) == MATCH.nomatch)
4623                     match1 = MATCH.nomatch; // Prefer at
4624                 else if (tt.implicitConvTo(at) == MATCH.nomatch)
4625                     match2 = MATCH.nomatch; // Prefer tt
4626                 else if (tt.isTypeBasic() && tt.ty == at.ty && tt.mod != at.mod)
4627                 {
4628                     if (!tt.isMutable() && !at.isMutable())
4629                         tt = tt.mutableOf().addMod(MODmerge(tt.mod, at.mod));
4630                     else if (tt.isMutable())
4631                     {
4632                         if (at.mod == 0) // Prefer unshared
4633                             match1 = MATCH.nomatch;
4634                         else
4635                             match2 = MATCH.nomatch;
4636                     }
4637                     else if (at.isMutable())
4638                     {
4639                         if (tt.mod == 0) // Prefer unshared
4640                             match2 = MATCH.nomatch;
4641                         else
4642                             match1 = MATCH.nomatch;
4643                     }
4644                     //printf("tt = %s, at = %s\n", tt.toChars(), at.toChars());
4645                 }
4646                 else
4647                 {
4648                     match1 = MATCH.nomatch;
4649                     match2 = MATCH.nomatch;
4650                 }
4651             }
4652             if (match1 > MATCH.nomatch)
4653             {
4654                 // Prefer current match: tt
4655                 if (xt)
4656                     xt.update(tt, e, tparam);
4657                 else
4658                     (*dedtypes)[i] = tt;
4659                 result = match1;
4660                 return;
4661             }
4662             if (match2 > MATCH.nomatch)
4663             {
4664                 // Prefer previous match: (*dedtypes)[i]
4665                 if (xt)
4666                     xt.update(e, tparam);
4667                 result = match2;
4668                 return;
4669             }
4670 
4671             /* Deduce common type
4672              */
4673             if (Type t = rawTypeMerge(at, tt))
4674             {
4675                 if (xt)
4676                     xt.update(t, e, tparam);
4677                 else
4678                     (*dedtypes)[i] = t;
4679 
4680                 pt = tt.addMod(tparam.mod);
4681                 if (*wm)
4682                     pt = pt.substWildTo(*wm);
4683                 result = e.implicitConvTo(pt);
4684                 return;
4685             }
4686 
4687             result = MATCH.nomatch;
4688         }
4689 
deduceEmptyArrayElement()4690         MATCH deduceEmptyArrayElement()
4691         {
4692             if (!emptyArrayElement)
4693             {
4694                 emptyArrayElement = new IdentifierExp(Loc.initial, Id.p); // dummy
4695                 emptyArrayElement.type = Type.tvoid;
4696             }
4697             assert(tparam.ty == Tarray);
4698 
4699             Type tn = (cast(TypeNext)tparam).next;
4700             return deduceType(emptyArrayElement, sc, tn, parameters, dedtypes, wm);
4701         }
4702 
visit(NullExp e)4703         override void visit(NullExp e)
4704         {
4705             if (tparam.ty == Tarray && e.type.ty == Tnull)
4706             {
4707                 // tparam:T[] <- e:null (void[])
4708                 result = deduceEmptyArrayElement();
4709                 return;
4710             }
4711             visit(cast(Expression)e);
4712         }
4713 
visit(StringExp e)4714         override void visit(StringExp e)
4715         {
4716             Type taai;
4717             if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
4718             {
4719                 // Consider compile-time known boundaries
4720                 e.type.nextOf().sarrayOf(e.len).accept(this);
4721                 return;
4722             }
4723             visit(cast(Expression)e);
4724         }
4725 
visit(ArrayLiteralExp e)4726         override void visit(ArrayLiteralExp e)
4727         {
4728             // https://issues.dlang.org/show_bug.cgi?id=20092
4729             if (e.elements && e.elements.dim && e.type.toBasetype().nextOf().ty == Tvoid)
4730             {
4731                 result = deduceEmptyArrayElement();
4732                 return;
4733             }
4734             if ((!e.elements || !e.elements.dim) && e.type.toBasetype().nextOf().ty == Tvoid && tparam.ty == Tarray)
4735             {
4736                 // tparam:T[] <- e:[] (void[])
4737                 result = deduceEmptyArrayElement();
4738                 return;
4739             }
4740 
4741             if (tparam.ty == Tarray && e.elements && e.elements.dim)
4742             {
4743                 Type tn = (cast(TypeDArray)tparam).next;
4744                 result = MATCH.exact;
4745                 if (e.basis)
4746                 {
4747                     MATCH m = deduceType(e.basis, sc, tn, parameters, dedtypes, wm);
4748                     if (m < result)
4749                         result = m;
4750                 }
4751                 foreach (el; *e.elements)
4752                 {
4753                     if (result == MATCH.nomatch)
4754                         break;
4755                     if (!el)
4756                         continue;
4757                     MATCH m = deduceType(el, sc, tn, parameters, dedtypes, wm);
4758                     if (m < result)
4759                         result = m;
4760                 }
4761                 return;
4762             }
4763 
4764             Type taai;
4765             if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
4766             {
4767                 // Consider compile-time known boundaries
4768                 e.type.nextOf().sarrayOf(e.elements.dim).accept(this);
4769                 return;
4770             }
4771             visit(cast(Expression)e);
4772         }
4773 
visit(AssocArrayLiteralExp e)4774         override void visit(AssocArrayLiteralExp e)
4775         {
4776             if (tparam.ty == Taarray && e.keys && e.keys.dim)
4777             {
4778                 TypeAArray taa = cast(TypeAArray)tparam;
4779                 result = MATCH.exact;
4780                 foreach (i, key; *e.keys)
4781                 {
4782                     MATCH m1 = deduceType(key, sc, taa.index, parameters, dedtypes, wm);
4783                     if (m1 < result)
4784                         result = m1;
4785                     if (result == MATCH.nomatch)
4786                         break;
4787                     MATCH m2 = deduceType((*e.values)[i], sc, taa.next, parameters, dedtypes, wm);
4788                     if (m2 < result)
4789                         result = m2;
4790                     if (result == MATCH.nomatch)
4791                         break;
4792                 }
4793                 return;
4794             }
4795             visit(cast(Expression)e);
4796         }
4797 
visit(FuncExp e)4798         override void visit(FuncExp e)
4799         {
4800             //printf("e.type = %s, tparam = %s\n", e.type.toChars(), tparam.toChars());
4801             if (e.td)
4802             {
4803                 Type to = tparam;
4804                 if (!to.nextOf())
4805                     return;
4806                 auto tof = to.nextOf().isTypeFunction();
4807                 if (!tof)
4808                     return;
4809 
4810                 // Parameter types inference from 'tof'
4811                 assert(e.td._scope);
4812                 TypeFunction tf = cast(TypeFunction)e.fd.type;
4813                 //printf("\ttof = %s\n", tof.toChars());
4814                 //printf("\ttf  = %s\n", tf.toChars());
4815                 const dim = tf.parameterList.length;
4816 
4817                 if (tof.parameterList.length != dim || tof.parameterList.varargs != tf.parameterList.varargs)
4818                     return;
4819 
4820                 auto tiargs = new Objects();
4821                 tiargs.reserve(e.td.parameters.dim);
4822 
4823                 foreach (tp; *e.td.parameters)
4824                 {
4825                     size_t u = 0;
4826                     foreach (i, p; tf.parameterList)
4827                     {
4828                         if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4829                             break;
4830                         ++u;
4831                     }
4832                     assert(u < dim);
4833                     Parameter pto = tof.parameterList[u];
4834                     if (!pto)
4835                         break;
4836                     Type t = pto.type.syntaxCopy(); // https://issues.dlang.org/show_bug.cgi?id=11774
4837                     if (reliesOnTemplateParameters(t, (*parameters)[inferStart .. parameters.dim]))
4838                         return;
4839                     t = t.typeSemantic(e.loc, sc);
4840                     if (t.ty == Terror)
4841                         return;
4842                     tiargs.push(t);
4843                 }
4844 
4845                 // Set target of return type inference
4846                 if (!tf.next && tof.next)
4847                     e.fd.treq = tparam;
4848 
4849                 auto ti = new TemplateInstance(e.loc, e.td, tiargs);
4850                 Expression ex = (new ScopeExp(e.loc, ti)).expressionSemantic(e.td._scope);
4851 
4852                 // Reset inference target for the later re-semantic
4853                 e.fd.treq = null;
4854 
4855                 if (ex.op == EXP.error)
4856                     return;
4857                 if (ex.op != EXP.function_)
4858                     return;
4859                 visit(ex.type);
4860                 return;
4861             }
4862 
4863             Type t = e.type;
4864 
4865             if (t.ty == Tdelegate && tparam.ty == Tpointer)
4866                 return;
4867 
4868             // Allow conversion from implicit function pointer to delegate
4869             if (e.tok == TOK.reserved && t.ty == Tpointer && tparam.ty == Tdelegate)
4870             {
4871                 TypeFunction tf = cast(TypeFunction)t.nextOf();
4872                 t = (new TypeDelegate(tf)).merge();
4873             }
4874             //printf("tparam = %s <= e.type = %s, t = %s\n", tparam.toChars(), e.type.toChars(), t.toChars());
4875             visit(t);
4876         }
4877 
visit(SliceExp e)4878         override void visit(SliceExp e)
4879         {
4880             Type taai;
4881             if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
4882             {
4883                 // Consider compile-time known boundaries
4884                 if (Type tsa = toStaticArrayType(e))
4885                 {
4886                     tsa.accept(this);
4887                     if (result > MATCH.convert)
4888                         result = MATCH.convert; // match with implicit conversion at most
4889                     return;
4890                 }
4891             }
4892             visit(cast(Expression)e);
4893         }
4894 
visit(CommaExp e)4895         override void visit(CommaExp e)
4896         {
4897             e.e2.accept(this);
4898         }
4899     }
4900 
4901     scope DeduceType v = new DeduceType(sc, tparam, parameters, dedtypes, wm, inferStart, ignoreAliasThis);
4902     if (Type t = isType(o))
4903         t.accept(v);
4904     else if (Expression e = isExpression(o))
4905     {
4906         assert(wm);
4907         e.accept(v);
4908     }
4909     else
4910         assert(0);
4911     return v.result;
4912 }
4913 
4914 /***********************************************************
4915  * Check whether the type t representation relies on one or more the template parameters.
4916  * Params:
4917  *      t           = Tested type, if null, returns false.
4918  *      tparams     = Template parameters.
4919  *      iStart      = Start index of tparams to limit the tested parameters. If it's
4920  *                    nonzero, tparams[0..iStart] will be excluded from the test target.
4921  */
4922 bool reliesOnTident(Type t, TemplateParameters* tparams, size_t iStart = 0)
4923 {
4924     return reliesOnTemplateParameters(t, (*tparams)[0 .. tparams.dim]);
4925 }
4926 
4927 /***********************************************************
4928  * Check whether the type t representation relies on one or more the template parameters.
4929  * Params:
4930  *      t           = Tested type, if null, returns false.
4931  *      tparams     = Template parameters.
4932  */
reliesOnTemplateParameters(Type t,TemplateParameter[]tparams)4933 private bool reliesOnTemplateParameters(Type t, TemplateParameter[] tparams)
4934 {
4935     bool visitVector(TypeVector t)
4936     {
4937         return t.basetype.reliesOnTemplateParameters(tparams);
4938     }
4939 
4940     bool visitAArray(TypeAArray t)
4941     {
4942         return t.next.reliesOnTemplateParameters(tparams) ||
4943                t.index.reliesOnTemplateParameters(tparams);
4944     }
4945 
4946     bool visitFunction(TypeFunction t)
4947     {
4948         foreach (i, fparam; t.parameterList)
4949         {
4950             if (fparam.type.reliesOnTemplateParameters(tparams))
4951                 return true;
4952         }
4953         return t.next.reliesOnTemplateParameters(tparams);
4954     }
4955 
4956     bool visitIdentifier(TypeIdentifier t)
4957     {
4958         foreach (tp; tparams)
4959         {
4960             if (tp.ident.equals(t.ident))
4961                 return true;
4962         }
4963         return false;
4964     }
4965 
4966     bool visitInstance(TypeInstance t)
4967     {
4968         foreach (tp; tparams)
4969         {
4970             if (t.tempinst.name == tp.ident)
4971                 return true;
4972         }
4973 
4974         if (t.tempinst.tiargs)
4975             foreach (arg; *t.tempinst.tiargs)
4976             {
4977                 if (Type ta = isType(arg))
4978                 {
4979                     if (ta.reliesOnTemplateParameters(tparams))
4980                         return true;
4981                 }
4982             }
4983 
4984         return false;
4985     }
4986 
4987     bool visitTypeof(TypeTypeof t)
4988     {
4989         //printf("TypeTypeof.reliesOnTemplateParameters('%s')\n", t.toChars());
4990         return t.exp.reliesOnTemplateParameters(tparams);
4991     }
4992 
4993     bool visitTuple(TypeTuple t)
4994     {
4995         if (t.arguments)
4996             foreach (arg; *t.arguments)
4997             {
4998                 if (arg.type.reliesOnTemplateParameters(tparams))
4999                     return true;
5000             }
5001 
5002         return false;
5003     }
5004 
5005     if (!t)
5006         return false;
5007 
5008     Type tb = t.toBasetype();
5009     switch (tb.ty)
5010     {
5011         case Tvector:   return visitVector(tb.isTypeVector());
5012         case Taarray:   return visitAArray(tb.isTypeAArray());
5013         case Tfunction: return visitFunction(tb.isTypeFunction());
5014         case Tident:    return visitIdentifier(tb.isTypeIdentifier());
5015         case Tinstance: return visitInstance(tb.isTypeInstance());
5016         case Ttypeof:   return visitTypeof(tb.isTypeTypeof());
5017         case Ttuple:    return visitTuple(tb.isTypeTuple());
5018         case Tenum:     return false;
5019         default:        return tb.nextOf().reliesOnTemplateParameters(tparams);
5020     }
5021 }
5022 
5023 /***********************************************************
5024  * Check whether the expression representation relies on one or more the template parameters.
5025  * Params:
5026  *      e           = expression to test
5027  *      tparams     = Template parameters.
5028  * Returns:
5029  *      true if it does
5030  */
reliesOnTemplateParameters(Expression e,TemplateParameter[]tparams)5031 private bool reliesOnTemplateParameters(Expression e, TemplateParameter[] tparams)
5032 {
5033     extern (C++) final class ReliesOnTemplateParameters : Visitor
5034     {
5035         alias visit = Visitor.visit;
5036     public:
5037         TemplateParameter[] tparams;
5038         bool result;
5039 
5040         extern (D) this(TemplateParameter[] tparams)
5041         {
5042             this.tparams = tparams;
5043         }
5044 
5045         override void visit(Expression e)
5046         {
5047             //printf("Expression.reliesOnTemplateParameters('%s')\n", e.toChars());
5048         }
5049 
5050         override void visit(IdentifierExp e)
5051         {
5052             //printf("IdentifierExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5053             foreach (tp; tparams)
5054             {
5055                 if (e.ident == tp.ident)
5056                 {
5057                     result = true;
5058                     return;
5059                 }
5060             }
5061         }
5062 
5063         override void visit(TupleExp e)
5064         {
5065             //printf("TupleExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5066             if (e.exps)
5067             {
5068                 foreach (ea; *e.exps)
5069                 {
5070                     ea.accept(this);
5071                     if (result)
5072                         return;
5073                 }
5074             }
5075         }
5076 
5077         override void visit(ArrayLiteralExp e)
5078         {
5079             //printf("ArrayLiteralExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5080             if (e.elements)
5081             {
5082                 foreach (el; *e.elements)
5083                 {
5084                     el.accept(this);
5085                     if (result)
5086                         return;
5087                 }
5088             }
5089         }
5090 
5091         override void visit(AssocArrayLiteralExp e)
5092         {
5093             //printf("AssocArrayLiteralExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5094             foreach (ek; *e.keys)
5095             {
5096                 ek.accept(this);
5097                 if (result)
5098                     return;
5099             }
5100             foreach (ev; *e.values)
5101             {
5102                 ev.accept(this);
5103                 if (result)
5104                     return;
5105             }
5106         }
5107 
5108         override void visit(StructLiteralExp e)
5109         {
5110             //printf("StructLiteralExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5111             if (e.elements)
5112             {
5113                 foreach (ea; *e.elements)
5114                 {
5115                     ea.accept(this);
5116                     if (result)
5117                         return;
5118                 }
5119             }
5120         }
5121 
5122         override void visit(TypeExp e)
5123         {
5124             //printf("TypeExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5125             result = e.type.reliesOnTemplateParameters(tparams);
5126         }
5127 
5128         override void visit(NewExp e)
5129         {
5130             //printf("NewExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5131             if (e.thisexp)
5132                 e.thisexp.accept(this);
5133             result = e.newtype.reliesOnTemplateParameters(tparams);
5134             if (!result && e.arguments)
5135             {
5136                 foreach (ea; *e.arguments)
5137                 {
5138                     ea.accept(this);
5139                     if (result)
5140                         return;
5141                 }
5142             }
5143         }
5144 
5145         override void visit(NewAnonClassExp e)
5146         {
5147             //printf("NewAnonClassExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5148             result = true;
5149         }
5150 
5151         override void visit(FuncExp e)
5152         {
5153             //printf("FuncExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5154             result = true;
5155         }
5156 
5157         override void visit(TypeidExp e)
5158         {
5159             //printf("TypeidExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5160             if (auto ea = isExpression(e.obj))
5161                 ea.accept(this);
5162             else if (auto ta = isType(e.obj))
5163                 result = ta.reliesOnTemplateParameters(tparams);
5164         }
5165 
5166         override void visit(TraitsExp e)
5167         {
5168             //printf("TraitsExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5169             if (e.args)
5170             {
5171                 foreach (oa; *e.args)
5172                 {
5173                     if (auto ea = isExpression(oa))
5174                         ea.accept(this);
5175                     else if (auto ta = isType(oa))
5176                         result = ta.reliesOnTemplateParameters(tparams);
5177                     if (result)
5178                         return;
5179                 }
5180             }
5181         }
5182 
5183         override void visit(IsExp e)
5184         {
5185             //printf("IsExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5186             result = e.targ.reliesOnTemplateParameters(tparams);
5187         }
5188 
5189         override void visit(UnaExp e)
5190         {
5191             //printf("UnaExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5192             e.e1.accept(this);
5193         }
5194 
5195         override void visit(DotTemplateInstanceExp e)
5196         {
5197             //printf("DotTemplateInstanceExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5198             visit(cast(UnaExp)e);
5199             if (!result && e.ti.tiargs)
5200             {
5201                 foreach (oa; *e.ti.tiargs)
5202                 {
5203                     if (auto ea = isExpression(oa))
5204                         ea.accept(this);
5205                     else if (auto ta = isType(oa))
5206                         result = ta.reliesOnTemplateParameters(tparams);
5207                     if (result)
5208                         return;
5209                 }
5210             }
5211         }
5212 
5213         override void visit(CallExp e)
5214         {
5215             //printf("CallExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5216             visit(cast(UnaExp)e);
5217             if (!result && e.arguments)
5218             {
5219                 foreach (ea; *e.arguments)
5220                 {
5221                     ea.accept(this);
5222                     if (result)
5223                         return;
5224                 }
5225             }
5226         }
5227 
5228         override void visit(CastExp e)
5229         {
5230             //printf("CallExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5231             visit(cast(UnaExp)e);
5232             // e.to can be null for cast() with no type
5233             if (!result && e.to)
5234                 result = e.to.reliesOnTemplateParameters(tparams);
5235         }
5236 
5237         override void visit(SliceExp e)
5238         {
5239             //printf("SliceExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5240             visit(cast(UnaExp)e);
5241             if (!result && e.lwr)
5242                 e.lwr.accept(this);
5243             if (!result && e.upr)
5244                 e.upr.accept(this);
5245         }
5246 
5247         override void visit(IntervalExp e)
5248         {
5249             //printf("IntervalExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5250             e.lwr.accept(this);
5251             if (!result)
5252                 e.upr.accept(this);
5253         }
5254 
5255         override void visit(ArrayExp e)
5256         {
5257             //printf("ArrayExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5258             visit(cast(UnaExp)e);
5259             if (!result && e.arguments)
5260             {
5261                 foreach (ea; *e.arguments)
5262                     ea.accept(this);
5263             }
5264         }
5265 
5266         override void visit(BinExp e)
5267         {
5268             //printf("BinExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5269             e.e1.accept(this);
5270             if (!result)
5271                 e.e2.accept(this);
5272         }
5273 
5274         override void visit(CondExp e)
5275         {
5276             //printf("BinExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5277             e.econd.accept(this);
5278             if (!result)
5279                 visit(cast(BinExp)e);
5280         }
5281     }
5282 
5283     scope ReliesOnTemplateParameters v = new ReliesOnTemplateParameters(tparams);
5284     e.accept(v);
5285     return v.result;
5286 }
5287 
5288 /***********************************************************
5289  * https://dlang.org/spec/template.html#TemplateParameter
5290  */
5291 extern (C++) class TemplateParameter : ASTNode
5292 {
5293     Loc loc;
5294     Identifier ident;
5295 
5296     /* True if this is a part of precedent parameter specialization pattern.
5297      *
5298      *  template A(T : X!TL, alias X, TL...) {}
5299      *  // X and TL are dependent template parameter
5300      *
5301      * A dependent template parameter should return MATCH.exact in matchArg()
5302      * to respect the match level of the corresponding precedent parameter.
5303      */
5304     bool dependent;
5305 
5306     /* ======================== TemplateParameter =============================== */
this(const ref Loc loc,Identifier ident)5307     extern (D) this(const ref Loc loc, Identifier ident)
5308     {
5309         this.loc = loc;
5310         this.ident = ident;
5311     }
5312 
isTemplateTypeParameter()5313     TemplateTypeParameter isTemplateTypeParameter()
5314     {
5315         return null;
5316     }
5317 
isTemplateValueParameter()5318     TemplateValueParameter isTemplateValueParameter()
5319     {
5320         return null;
5321     }
5322 
isTemplateAliasParameter()5323     TemplateAliasParameter isTemplateAliasParameter()
5324     {
5325         return null;
5326     }
5327 
isTemplateThisParameter()5328     TemplateThisParameter isTemplateThisParameter()
5329     {
5330         return null;
5331     }
5332 
isTemplateTupleParameter()5333     TemplateTupleParameter isTemplateTupleParameter()
5334     {
5335         return null;
5336     }
5337 
5338     abstract TemplateParameter syntaxCopy();
5339 
5340     abstract bool declareParameter(Scope* sc);
5341 
5342     abstract void print(RootObject oarg, RootObject oded);
5343 
5344     abstract RootObject specialization();
5345 
5346     abstract RootObject defaultArg(const ref Loc instLoc, Scope* sc);
5347 
5348     abstract bool hasDefaultArg();
5349 
toChars()5350     override const(char)* toChars() const
5351     {
5352         return this.ident.toChars();
5353     }
5354 
dyncast()5355     override DYNCAST dyncast() const pure @nogc nothrow @safe
5356     {
5357         return DYNCAST.templateparameter;
5358     }
5359 
5360     /* Create dummy argument based on parameter.
5361      */
5362     abstract RootObject dummyArg();
5363 
accept(Visitor v)5364     override void accept(Visitor v)
5365     {
5366         v.visit(this);
5367     }
5368 }
5369 
5370 /***********************************************************
5371  * https://dlang.org/spec/template.html#TemplateTypeParameter
5372  * Syntax:
5373  *  ident : specType = defaultType
5374  */
5375 extern (C++) class TemplateTypeParameter : TemplateParameter
5376 {
5377     Type specType;      // if !=null, this is the type specialization
5378     Type defaultType;
5379 
5380     extern (D) __gshared Type tdummy = null;
5381 
this(const ref Loc loc,Identifier ident,Type specType,Type defaultType)5382     extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType)
5383     {
5384         super(loc, ident);
5385         this.specType = specType;
5386         this.defaultType = defaultType;
5387     }
5388 
isTemplateTypeParameter()5389     override final TemplateTypeParameter isTemplateTypeParameter()
5390     {
5391         return this;
5392     }
5393 
syntaxCopy()5394     override TemplateTypeParameter syntaxCopy()
5395     {
5396         return new TemplateTypeParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5397     }
5398 
declareParameter(Scope * sc)5399     override final bool declareParameter(Scope* sc)
5400     {
5401         //printf("TemplateTypeParameter.declareParameter('%s')\n", ident.toChars());
5402         auto ti = new TypeIdentifier(loc, ident);
5403         Declaration ad = new AliasDeclaration(loc, ident, ti);
5404         return sc.insert(ad) !is null;
5405     }
5406 
print(RootObject oarg,RootObject oded)5407     override final void print(RootObject oarg, RootObject oded)
5408     {
5409         printf(" %s\n", ident.toChars());
5410 
5411         Type t = isType(oarg);
5412         Type ta = isType(oded);
5413         assert(ta);
5414 
5415         if (specType)
5416             printf("\tSpecialization: %s\n", specType.toChars());
5417         if (defaultType)
5418             printf("\tDefault:        %s\n", defaultType.toChars());
5419         printf("\tParameter:       %s\n", t ? t.toChars() : "NULL");
5420         printf("\tDeduced Type:   %s\n", ta.toChars());
5421     }
5422 
specialization()5423     override final RootObject specialization()
5424     {
5425         return specType;
5426     }
5427 
defaultArg(const ref Loc instLoc,Scope * sc)5428     override final RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5429     {
5430         Type t = defaultType;
5431         if (t)
5432         {
5433             t = t.syntaxCopy();
5434             t = t.typeSemantic(loc, sc); // use the parameter loc
5435         }
5436         return t;
5437     }
5438 
hasDefaultArg()5439     override final bool hasDefaultArg()
5440     {
5441         return defaultType !is null;
5442     }
5443 
dummyArg()5444     override final RootObject dummyArg()
5445     {
5446         Type t = specType;
5447         if (!t)
5448         {
5449             // Use this for alias-parameter's too (?)
5450             if (!tdummy)
5451                 tdummy = new TypeIdentifier(loc, ident);
5452             t = tdummy;
5453         }
5454         return t;
5455     }
5456 
accept(Visitor v)5457     override void accept(Visitor v)
5458     {
5459         v.visit(this);
5460     }
5461 }
5462 
5463 /***********************************************************
5464  * https://dlang.org/spec/template.html#TemplateThisParameter
5465  * Syntax:
5466  *  this ident : specType = defaultType
5467  */
5468 extern (C++) final class TemplateThisParameter : TemplateTypeParameter
5469 {
this(const ref Loc loc,Identifier ident,Type specType,Type defaultType)5470     extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType)
5471     {
5472         super(loc, ident, specType, defaultType);
5473     }
5474 
isTemplateThisParameter()5475     override TemplateThisParameter isTemplateThisParameter()
5476     {
5477         return this;
5478     }
5479 
syntaxCopy()5480     override TemplateThisParameter syntaxCopy()
5481     {
5482         return new TemplateThisParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5483     }
5484 
accept(Visitor v)5485     override void accept(Visitor v)
5486     {
5487         v.visit(this);
5488     }
5489 }
5490 
5491 /***********************************************************
5492  * https://dlang.org/spec/template.html#TemplateValueParameter
5493  * Syntax:
5494  *  valType ident : specValue = defaultValue
5495  */
5496 extern (C++) final class TemplateValueParameter : TemplateParameter
5497 {
5498     Type valType;
5499     Expression specValue;
5500     Expression defaultValue;
5501 
5502     extern (D) __gshared Expression[void*] edummies;
5503 
this(const ref Loc loc,Identifier ident,Type valType,Expression specValue,Expression defaultValue)5504     extern (D) this(const ref Loc loc, Identifier ident, Type valType,
5505         Expression specValue, Expression defaultValue)
5506     {
5507         super(loc, ident);
5508         this.valType = valType;
5509         this.specValue = specValue;
5510         this.defaultValue = defaultValue;
5511     }
5512 
isTemplateValueParameter()5513     override TemplateValueParameter isTemplateValueParameter()
5514     {
5515         return this;
5516     }
5517 
syntaxCopy()5518     override TemplateValueParameter syntaxCopy()
5519     {
5520         return new TemplateValueParameter(loc, ident,
5521             valType.syntaxCopy(),
5522             specValue ? specValue.syntaxCopy() : null,
5523             defaultValue ? defaultValue.syntaxCopy() : null);
5524     }
5525 
declareParameter(Scope * sc)5526     override bool declareParameter(Scope* sc)
5527     {
5528         /*
5529             Do type semantic earlier.
5530 
5531             This means for certain erroneous value parameters
5532             their "type" can be known earlier and thus a better
5533             error message given.
5534 
5535             For example:
5536             `template test(x* x) {}`
5537             now yields "undefined identifier" rather than the opaque
5538             "variable `x` is used as a type".
5539          */
5540         if (valType)
5541             valType = valType.typeSemantic(loc, sc);
5542         auto v = new VarDeclaration(loc, valType, ident, null);
5543         v.storage_class = STC.templateparameter;
5544         return sc.insert(v) !is null;
5545     }
5546 
print(RootObject oarg,RootObject oded)5547     override void print(RootObject oarg, RootObject oded)
5548     {
5549         printf(" %s\n", ident.toChars());
5550         Expression ea = isExpression(oded);
5551         if (specValue)
5552             printf("\tSpecialization: %s\n", specValue.toChars());
5553         printf("\tParameter Value: %s\n", ea ? ea.toChars() : "NULL");
5554     }
5555 
specialization()5556     override RootObject specialization()
5557     {
5558         return specValue;
5559     }
5560 
defaultArg(const ref Loc instLoc,Scope * sc)5561     override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5562     {
5563         Expression e = defaultValue;
5564         if (e)
5565         {
5566             e = e.syntaxCopy();
5567             uint olderrs = global.errors;
5568             if ((e = e.expressionSemantic(sc)) is null)
5569                 return null;
5570             if ((e = resolveProperties(sc, e)) is null)
5571                 return null;
5572             e = e.resolveLoc(instLoc, sc); // use the instantiated loc
5573             e = e.optimize(WANTvalue);
5574             if (global.errors != olderrs)
5575                 e = ErrorExp.get();
5576         }
5577         return e;
5578     }
5579 
hasDefaultArg()5580     override bool hasDefaultArg()
5581     {
5582         return defaultValue !is null;
5583     }
5584 
dummyArg()5585     override RootObject dummyArg()
5586     {
5587         Expression e = specValue;
5588         if (!e)
5589         {
5590             // Create a dummy value
5591             auto pe = cast(void*)valType in edummies;
5592             if (!pe)
5593             {
5594                 e = valType.defaultInit(Loc.initial);
5595                 edummies[cast(void*)valType] = e;
5596             }
5597             else
5598                 e = *pe;
5599         }
5600         return e;
5601     }
5602 
accept(Visitor v)5603     override void accept(Visitor v)
5604     {
5605         v.visit(this);
5606     }
5607 }
5608 
5609 /***********************************************************
5610  * https://dlang.org/spec/template.html#TemplateAliasParameter
5611  * Syntax:
5612  *  specType ident : specAlias = defaultAlias
5613  */
5614 extern (C++) final class TemplateAliasParameter : TemplateParameter
5615 {
5616     Type specType;
5617     RootObject specAlias;
5618     RootObject defaultAlias;
5619 
5620     extern (D) __gshared Dsymbol sdummy = null;
5621 
this(const ref Loc loc,Identifier ident,Type specType,RootObject specAlias,RootObject defaultAlias)5622     extern (D) this(const ref Loc loc, Identifier ident, Type specType, RootObject specAlias, RootObject defaultAlias)
5623     {
5624         super(loc, ident);
5625         this.specType = specType;
5626         this.specAlias = specAlias;
5627         this.defaultAlias = defaultAlias;
5628     }
5629 
isTemplateAliasParameter()5630     override TemplateAliasParameter isTemplateAliasParameter()
5631     {
5632         return this;
5633     }
5634 
syntaxCopy()5635     override TemplateAliasParameter syntaxCopy()
5636     {
5637         return new TemplateAliasParameter(loc, ident, specType ? specType.syntaxCopy() : null, objectSyntaxCopy(specAlias), objectSyntaxCopy(defaultAlias));
5638     }
5639 
declareParameter(Scope * sc)5640     override bool declareParameter(Scope* sc)
5641     {
5642         auto ti = new TypeIdentifier(loc, ident);
5643         Declaration ad = new AliasDeclaration(loc, ident, ti);
5644         return sc.insert(ad) !is null;
5645     }
5646 
print(RootObject oarg,RootObject oded)5647     override void print(RootObject oarg, RootObject oded)
5648     {
5649         printf(" %s\n", ident.toChars());
5650         Dsymbol sa = isDsymbol(oded);
5651         assert(sa);
5652         printf("\tParameter alias: %s\n", sa.toChars());
5653     }
5654 
specialization()5655     override RootObject specialization()
5656     {
5657         return specAlias;
5658     }
5659 
defaultArg(const ref Loc instLoc,Scope * sc)5660     override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5661     {
5662         RootObject da = defaultAlias;
5663         Type ta = isType(defaultAlias);
5664         if (ta)
5665         {
5666             if (ta.ty == Tinstance)
5667             {
5668                 // If the default arg is a template, instantiate for each type
5669                 da = ta.syntaxCopy();
5670             }
5671         }
5672 
5673         RootObject o = aliasParameterSemantic(loc, sc, da, null); // use the parameter loc
5674         return o;
5675     }
5676 
hasDefaultArg()5677     override bool hasDefaultArg()
5678     {
5679         return defaultAlias !is null;
5680     }
5681 
dummyArg()5682     override RootObject dummyArg()
5683     {
5684         RootObject s = specAlias;
5685         if (!s)
5686         {
5687             if (!sdummy)
5688                 sdummy = new Dsymbol();
5689             s = sdummy;
5690         }
5691         return s;
5692     }
5693 
accept(Visitor v)5694     override void accept(Visitor v)
5695     {
5696         v.visit(this);
5697     }
5698 }
5699 
5700 /***********************************************************
5701  * https://dlang.org/spec/template.html#TemplateSequenceParameter
5702  * Syntax:
5703  *  ident ...
5704  */
5705 extern (C++) final class TemplateTupleParameter : TemplateParameter
5706 {
this(const ref Loc loc,Identifier ident)5707     extern (D) this(const ref Loc loc, Identifier ident)
5708     {
5709         super(loc, ident);
5710     }
5711 
isTemplateTupleParameter()5712     override TemplateTupleParameter isTemplateTupleParameter()
5713     {
5714         return this;
5715     }
5716 
syntaxCopy()5717     override TemplateTupleParameter syntaxCopy()
5718     {
5719         return new TemplateTupleParameter(loc, ident);
5720     }
5721 
declareParameter(Scope * sc)5722     override bool declareParameter(Scope* sc)
5723     {
5724         auto ti = new TypeIdentifier(loc, ident);
5725         Declaration ad = new AliasDeclaration(loc, ident, ti);
5726         return sc.insert(ad) !is null;
5727     }
5728 
print(RootObject oarg,RootObject oded)5729     override void print(RootObject oarg, RootObject oded)
5730     {
5731         printf(" %s... [", ident.toChars());
5732         Tuple v = isTuple(oded);
5733         assert(v);
5734 
5735         //printf("|%d| ", v.objects.dim);
5736         foreach (i, o; v.objects)
5737         {
5738             if (i)
5739                 printf(", ");
5740 
5741             Dsymbol sa = isDsymbol(o);
5742             if (sa)
5743                 printf("alias: %s", sa.toChars());
5744             Type ta = isType(o);
5745             if (ta)
5746                 printf("type: %s", ta.toChars());
5747             Expression ea = isExpression(o);
5748             if (ea)
5749                 printf("exp: %s", ea.toChars());
5750 
5751             assert(!isTuple(o)); // no nested Tuple arguments
5752         }
5753         printf("]\n");
5754     }
5755 
specialization()5756     override RootObject specialization()
5757     {
5758         return null;
5759     }
5760 
defaultArg(const ref Loc instLoc,Scope * sc)5761     override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5762     {
5763         return null;
5764     }
5765 
hasDefaultArg()5766     override bool hasDefaultArg()
5767     {
5768         return false;
5769     }
5770 
dummyArg()5771     override RootObject dummyArg()
5772     {
5773         return null;
5774     }
5775 
accept(Visitor v)5776     override void accept(Visitor v)
5777     {
5778         v.visit(this);
5779     }
5780 }
5781 
5782 /***********************************************************
5783  * https://dlang.org/spec/template.html#explicit_tmp_instantiation
5784  * Given:
5785  *  foo!(args) =>
5786  *      name = foo
5787  *      tiargs = args
5788  */
5789 extern (C++) class TemplateInstance : ScopeDsymbol
5790 {
5791     Identifier name;
5792 
5793     // Array of Types/Expressions of template
5794     // instance arguments [int*, char, 10*10]
5795     Objects* tiargs;
5796 
5797     // Array of Types/Expressions corresponding
5798     // to TemplateDeclaration.parameters
5799     // [int, char, 100]
5800     Objects tdtypes;
5801 
5802     // Modules imported by this template instance
5803     Modules importedModules;
5804 
5805     Dsymbol tempdecl;           // referenced by foo.bar.abc
5806     Dsymbol enclosing;          // if referencing local symbols, this is the context
5807     Dsymbol aliasdecl;          // !=null if instance is an alias for its sole member
5808     TemplateInstance inst;      // refer to existing instance
5809     ScopeDsymbol argsym;        // argument symbol table
5810     size_t hash;                // cached result of toHash()
5811     Expressions* fargs;         // for function template, these are the function arguments
5812 
5813     TemplateInstances* deferred;
5814 
5815     Module memberOf;            // if !null, then this TemplateInstance appears in memberOf.members[]
5816 
5817     // Used to determine the instance needs code generation.
5818     // Note that these are inaccurate until semantic analysis phase completed.
5819     TemplateInstance tinst;     // enclosing template instance
5820     TemplateInstance tnext;     // non-first instantiated instances
5821     Module minst;               // the top module that instantiated this instance
5822 
5823     private ushort _nest;       // for recursive pretty printing detection, 3 MSBs reserved for flags (below)
5824     ubyte inuse;                // for recursive expansion detection
5825 
5826     private enum Flag : uint
5827     {
5828         semantictiargsdone = 1u << (_nest.sizeof * 8 - 1), // MSB of _nest
5829         havetempdecl = semantictiargsdone >> 1,
5830         gagged = semantictiargsdone >> 2,
5831         available = gagged - 1 // always last flag minus one, 1s for all available bits
5832     }
5833 
5834     extern(D) final @safe @property pure nothrow @nogc
5835     {
nest()5836         ushort nest() const { return _nest & Flag.available; }
nestUp()5837         void nestUp() { assert(nest() < Flag.available); ++_nest; }
nestDown()5838         void nestDown() { assert(nest() > 0); --_nest; }
5839         /// has semanticTiargs() been done?
semantictiargsdone()5840         bool semantictiargsdone() const { return (_nest & Flag.semantictiargsdone) != 0; }
semantictiargsdone(bool x)5841         void semantictiargsdone(bool x)
5842         {
5843             if (x) _nest |= Flag.semantictiargsdone;
5844             else _nest &= ~Flag.semantictiargsdone;
5845         }
5846         /// if used second constructor
havetempdecl()5847         bool havetempdecl() const { return (_nest & Flag.havetempdecl) != 0; }
havetempdecl(bool x)5848         void havetempdecl(bool x)
5849         {
5850             if (x) _nest |= Flag.havetempdecl;
5851             else _nest &= ~Flag.havetempdecl;
5852         }
5853         /// if the instantiation is done with error gagging
gagged()5854         bool gagged() const { return (_nest & Flag.gagged) != 0; }
gagged(bool x)5855         void gagged(bool x)
5856         {
5857             if (x) _nest |= Flag.gagged;
5858             else _nest &= ~Flag.gagged;
5859         }
5860     }
5861 
this(const ref Loc loc,Identifier ident,Objects * tiargs)5862     extern (D) this(const ref Loc loc, Identifier ident, Objects* tiargs)
5863     {
5864         super(loc, null);
5865         static if (LOG)
5866         {
5867             printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident.toChars() : "null");
5868         }
5869         this.name = ident;
5870         this.tiargs = tiargs;
5871     }
5872 
5873     /*****************
5874      * This constructor is only called when we figured out which function
5875      * template to instantiate.
5876      */
this(const ref Loc loc,TemplateDeclaration td,Objects * tiargs)5877     extern (D) this(const ref Loc loc, TemplateDeclaration td, Objects* tiargs)
5878     {
5879         super(loc, null);
5880         static if (LOG)
5881         {
5882             printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td.toChars());
5883         }
5884         this.name = td.ident;
5885         this.tiargs = tiargs;
5886         this.tempdecl = td;
5887         this.semantictiargsdone = true;
5888         this.havetempdecl = true;
5889         assert(tempdecl._scope);
5890     }
5891 
arraySyntaxCopy(Objects * objs)5892     extern (D) static Objects* arraySyntaxCopy(Objects* objs)
5893     {
5894         Objects* a = null;
5895         if (objs)
5896         {
5897             a = new Objects(objs.dim);
5898             foreach (i, o; *objs)
5899                 (*a)[i] = objectSyntaxCopy(o);
5900         }
5901         return a;
5902     }
5903 
syntaxCopy(Dsymbol s)5904     override TemplateInstance syntaxCopy(Dsymbol s)
5905     {
5906         TemplateInstance ti = s ? cast(TemplateInstance)s : new TemplateInstance(loc, name, null);
5907         ti.tiargs = arraySyntaxCopy(tiargs);
5908         TemplateDeclaration td;
5909         if (inst && tempdecl && (td = tempdecl.isTemplateDeclaration()) !is null)
5910             td.ScopeDsymbol.syntaxCopy(ti);
5911         else
5912             ScopeDsymbol.syntaxCopy(ti);
5913         return ti;
5914     }
5915 
5916     // resolve real symbol
toAlias()5917     override final Dsymbol toAlias()
5918     {
5919         static if (LOG)
5920         {
5921             printf("TemplateInstance.toAlias()\n");
5922         }
5923         if (!inst)
5924         {
5925             // Maybe we can resolve it
5926             if (_scope)
5927             {
5928                 dsymbolSemantic(this, _scope);
5929             }
5930             if (!inst)
5931             {
5932                 error("cannot resolve forward reference");
5933                 errors = true;
5934                 return this;
5935             }
5936         }
5937 
5938         if (inst != this)
5939             return inst.toAlias();
5940 
5941         if (aliasdecl)
5942         {
5943             return aliasdecl.toAlias();
5944         }
5945 
5946         return inst;
5947     }
5948 
kind()5949     override const(char)* kind() const
5950     {
5951         return "template instance";
5952     }
5953 
oneMember(Dsymbol * ps,Identifier ident)5954     override bool oneMember(Dsymbol* ps, Identifier ident)
5955     {
5956         *ps = null;
5957         return true;
5958     }
5959 
toChars()5960     override const(char)* toChars() const
5961     {
5962         OutBuffer buf;
5963         toCBufferInstance(this, &buf);
5964         return buf.extractChars();
5965     }
5966 
toPrettyCharsHelper()5967     override final const(char)* toPrettyCharsHelper()
5968     {
5969         OutBuffer buf;
5970         toCBufferInstance(this, &buf, true);
5971         return buf.extractChars();
5972     }
5973 
5974     /**************************************
5975      * Given an error instantiating the TemplateInstance,
5976      * give the nested TemplateInstance instantiations that got
5977      * us here. Those are a list threaded into the nested scopes.
5978      */
5979     extern(D) final void printInstantiationTrace(Classification cl = Classification.error)
5980     {
5981         if (global.gag)
5982             return;
5983 
5984         // Print full trace for verbose mode, otherwise only short traces
5985         const(uint) max_shown = !global.params.verbose ? 6 : uint.max;
5986         const(char)* format = "instantiated from here: `%s`";
5987 
5988         // This returns a function pointer
5989         scope printFn = () {
5990             final switch (cl)
5991             {
5992                 case Classification.error:
5993                     return &errorSupplemental;
5994                 case Classification.warning:
5995                     return &warningSupplemental;
5996                 case Classification.deprecation:
5997                     return &deprecationSupplemental;
5998                 case Classification.gagged, Classification.tip:
5999                     assert(0);
6000             }
6001         }();
6002 
6003         // determine instantiation depth and number of recursive instantiations
6004         int n_instantiations = 1;
6005         int n_totalrecursions = 0;
6006         for (TemplateInstance cur = this; cur; cur = cur.tinst)
6007         {
6008             ++n_instantiations;
6009             // Set error here as we don't want it to depend on the number of
6010             // entries that are being printed.
6011             if (cl == Classification.error ||
6012                 (cl == Classification.warning && global.params.warnings == DiagnosticReporting.error) ||
6013                 (cl == Classification.deprecation && global.params.useDeprecated == DiagnosticReporting.error))
6014                 cur.errors = true;
6015 
6016             // If two instantiations use the same declaration, they are recursive.
6017             // (this works even if they are instantiated from different places in the
6018             // same template).
6019             // In principle, we could also check for multiple-template recursion, but it's
6020             // probably not worthwhile.
6021             if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
6022                 ++n_totalrecursions;
6023         }
6024 
6025         if (n_instantiations <= max_shown)
6026         {
6027             for (TemplateInstance cur = this; cur; cur = cur.tinst)
6028                 printFn(cur.loc, format, cur.toChars());
6029         }
6030         else if (n_instantiations - n_totalrecursions <= max_shown)
6031         {
6032             // By collapsing recursive instantiations into a single line,
6033             // we can stay under the limit.
6034             int recursionDepth = 0;
6035             for (TemplateInstance cur = this; cur; cur = cur.tinst)
6036             {
6037                 if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
6038                 {
6039                     ++recursionDepth;
6040                 }
6041                 else
6042                 {
6043                     if (recursionDepth)
6044                         printFn(cur.loc, "%d recursive instantiations from here: `%s`", recursionDepth + 2, cur.toChars());
6045                     else
6046                         printFn(cur.loc, format, cur.toChars());
6047                     recursionDepth = 0;
6048                 }
6049             }
6050         }
6051         else
6052         {
6053             // Even after collapsing the recursions, the depth is too deep.
6054             // Just display the first few and last few instantiations.
6055             uint i = 0;
6056             for (TemplateInstance cur = this; cur; cur = cur.tinst)
6057             {
6058                 if (i == max_shown / 2)
6059                     printFn(cur.loc, "... (%d instantiations, -v to show) ...", n_instantiations - max_shown);
6060 
6061                 if (i < max_shown / 2 || i >= n_instantiations - max_shown + max_shown / 2)
6062                     printFn(cur.loc, format, cur.toChars());
6063                 ++i;
6064             }
6065         }
6066     }
6067 
6068     /*************************************
6069      * Lazily generate identifier for template instance.
6070      * This is because 75% of the ident's are never needed.
6071      */
getIdent()6072     override final Identifier getIdent()
6073     {
6074         if (!ident && inst && !errors)
6075             ident = genIdent(tiargs); // need an identifier for name mangling purposes.
6076         return ident;
6077     }
6078 
6079     /*************************************
6080      * Compare proposed template instantiation with existing template instantiation.
6081      * Note that this is not commutative because of the auto ref check.
6082      * Params:
6083      *  ti = existing template instantiation
6084      * Returns:
6085      *  true for match
6086      */
equalsx(TemplateInstance ti)6087     final bool equalsx(TemplateInstance ti)
6088     {
6089         //printf("this = %p, ti = %p\n", this, ti);
6090         assert(tdtypes.dim == ti.tdtypes.dim);
6091 
6092         // Nesting must match
6093         if (enclosing != ti.enclosing)
6094         {
6095             //printf("test2 enclosing %s ti.enclosing %s\n", enclosing ? enclosing.toChars() : "", ti.enclosing ? ti.enclosing.toChars() : "");
6096             goto Lnotequals;
6097         }
6098         //printf("parent = %s, ti.parent = %s\n", parent.toPrettyChars(), ti.parent.toPrettyChars());
6099 
6100         if (!arrayObjectMatch(&tdtypes, &ti.tdtypes))
6101             goto Lnotequals;
6102 
6103         /* Template functions may have different instantiations based on
6104          * "auto ref" parameters.
6105          */
6106         if (auto fd = ti.toAlias().isFuncDeclaration())
6107         {
6108             if (!fd.errors)
6109             {
6110                 auto fparameters = fd.getParameterList();
6111                 size_t nfparams = fparameters.length;   // Num function parameters
6112                 for (size_t j = 0; j < nfparams; j++)
6113                 {
6114                     Parameter fparam = fparameters[j];
6115                     if (fparam.storageClass & STC.autoref)       // if "auto ref"
6116                     {
6117                         Expression farg = fargs && j < fargs.dim ? (*fargs)[j] : fparam.defaultArg;
6118                         if (!farg)
6119                             goto Lnotequals;
6120                         if (farg.isLvalue())
6121                         {
6122                             if (!(fparam.storageClass & STC.ref_))
6123                                 goto Lnotequals; // auto ref's don't match
6124                         }
6125                         else
6126                         {
6127                             if (fparam.storageClass & STC.ref_)
6128                                 goto Lnotequals; // auto ref's don't match
6129                         }
6130                     }
6131                 }
6132             }
6133         }
6134         return true;
6135 
6136     Lnotequals:
6137         return false;
6138     }
6139 
toHash()6140     final size_t toHash()
6141     {
6142         if (!hash)
6143         {
6144             hash = cast(size_t)cast(void*)enclosing;
6145             hash += arrayObjectHash(&tdtypes);
6146             hash += hash == 0;
6147         }
6148         return hash;
6149     }
6150 
6151     /**
6152         Returns: true if the instances' innards are discardable.
6153 
6154         The idea of this function is to see if the template instantiation
6155         can be 100% replaced with its eponymous member. All other members
6156         can be discarded, even in the compiler to free memory (for example,
6157         the template could be expanded in a region allocator, deemed trivial,
6158         the end result copied back out independently and the entire region freed),
6159         and can be elided entirely from the binary.
6160 
6161         The current implementation affects code that generally looks like:
6162 
6163         ---
6164         template foo(args...) {
6165             some_basic_type_or_string helper() { .... }
6166             enum foo = helper();
6167         }
6168         ---
6169 
6170         since it was the easiest starting point of implementation but it can and
6171         should be expanded more later.
6172     */
isDiscardable()6173     final bool isDiscardable()
6174     {
6175         if (aliasdecl is null)
6176             return false;
6177 
6178         auto v = aliasdecl.isVarDeclaration();
6179         if (v is null)
6180             return false;
6181 
6182         if (!(v.storage_class & STC.manifest))
6183             return false;
6184 
6185         // Currently only doing basic types here because it is the easiest proof-of-concept
6186         // implementation with minimal risk of side effects, but it could likely be
6187         // expanded to any type that already exists outside this particular instance.
6188         if (!(v.type.equals(Type.tstring) || (v.type.isTypeBasic() !is null)))
6189             return false;
6190 
6191         // Static ctors and dtors, even in an eponymous enum template, are still run,
6192         // so if any of them are in here, we'd better not assume it is trivial lest
6193         // we break useful code
6194         foreach(member; *members)
6195         {
6196             if(member.hasStaticCtorOrDtor())
6197                 return false;
6198             if(member.isStaticDtorDeclaration())
6199                 return false;
6200             if(member.isStaticCtorDeclaration())
6201                 return false;
6202         }
6203 
6204         // but if it passes through this gauntlet... it should be fine. D code will
6205         // see only the eponymous member, outside stuff can never access it, even through
6206         // reflection; the outside world ought to be none the wiser. Even dmd should be
6207         // able to simply free the memory of everything except the final result.
6208 
6209         return true;
6210     }
6211 
6212 
6213     /***********************************************
6214      * Returns true if this is not instantiated in non-root module, and
6215      * is a part of non-speculative instantiatiation.
6216      *
6217      * Note: minst does not stabilize until semantic analysis is completed,
6218      * so don't call this function during semantic analysis to return precise result.
6219      */
needsCodegen()6220     final bool needsCodegen()
6221     {
6222         // minst is finalized after the 1st invocation.
6223         // tnext and tinst are only needed for the 1st invocation and
6224         // cleared for further invocations.
6225         TemplateInstance tnext = this.tnext;
6226         TemplateInstance tinst = this.tinst;
6227         this.tnext = null;
6228         this.tinst = null;
6229 
6230         if (errors || (inst && inst.isDiscardable()))
6231         {
6232             minst = null; // mark as speculative
6233             return false;
6234         }
6235 
6236         if (global.params.allInst)
6237         {
6238             // Do codegen if there is an instantiation from a root module, to maximize link-ability.
6239 
6240             // Do codegen if `this` is instantiated from a root module.
6241             if (minst && minst.isRoot())
6242                 return true;
6243 
6244             // Do codegen if the ancestor needs it.
6245             if (tinst && tinst.needsCodegen())
6246             {
6247                 minst = tinst.minst; // cache result
6248                 assert(minst);
6249                 assert(minst.isRoot());
6250                 return true;
6251             }
6252 
6253             // Do codegen if a sibling needs it.
6254             if (tnext)
6255             {
6256                 if (tnext.needsCodegen())
6257                 {
6258                     minst = tnext.minst; // cache result
6259                     assert(minst);
6260                     assert(minst.isRoot());
6261                     return true;
6262                 }
6263                 else if (!minst && tnext.minst)
6264                 {
6265                     minst = tnext.minst; // cache result from non-speculative sibling
6266                     return false;
6267                 }
6268             }
6269 
6270             // Elide codegen because there's no instantiation from any root modules.
6271             return false;
6272         }
6273         else
6274         {
6275             // Prefer instantiations from non-root modules, to minimize object code size.
6276 
6277             /* If a TemplateInstance is ever instantiated from a non-root module,
6278              * we do not have to generate code for it,
6279              * because it will be generated when the non-root module is compiled.
6280              *
6281              * But, if the non-root 'minst' imports any root modules, it might still need codegen.
6282              *
6283              * The problem is if A imports B, and B imports A, and both A
6284              * and B instantiate the same template, does the compilation of A
6285              * or the compilation of B do the actual instantiation?
6286              *
6287              * See https://issues.dlang.org/show_bug.cgi?id=2500.
6288              *
6289              * => Elide codegen if there is at least one instantiation from a non-root module
6290              *    which doesn't import any root modules.
6291              */
6292 
6293             // If the ancestor isn't speculative,
6294             // 1. do codegen if the ancestor needs it
6295             // 2. elide codegen if the ancestor doesn't need it (non-root instantiation of ancestor incl. subtree)
6296             if (tinst)
6297             {
6298                 const needsCodegen = tinst.needsCodegen(); // sets tinst.minst
6299                 if (tinst.minst) // not speculative
6300                 {
6301                     minst = tinst.minst; // cache result
6302                     return needsCodegen;
6303                 }
6304             }
6305 
6306             // Elide codegen if `this` doesn't need it.
6307             if (minst && !minst.isRoot() && !minst.rootImports())
6308                 return false;
6309 
6310             // Elide codegen if a (non-speculative) sibling doesn't need it.
6311             if (tnext)
6312             {
6313                 const needsCodegen = tnext.needsCodegen(); // sets tnext.minst
6314                 if (tnext.minst) // not speculative
6315                 {
6316                     if (!needsCodegen)
6317                     {
6318                         minst = tnext.minst; // cache result
6319                         assert(!minst.isRoot() && !minst.rootImports());
6320                         return false;
6321                     }
6322                     else if (!minst)
6323                     {
6324                         minst = tnext.minst; // cache result from non-speculative sibling
6325                         return true;
6326                     }
6327                 }
6328             }
6329 
6330             // Unless `this` is still speculative (=> all further siblings speculative too),
6331             // do codegen because we found no guaranteed-codegen'd non-root instantiation.
6332             return minst !is null;
6333         }
6334     }
6335 
6336     /**********************************************
6337      * Find template declaration corresponding to template instance.
6338      *
6339      * Returns:
6340      *      false if finding fails.
6341      * Note:
6342      *      This function is reentrant against error occurrence. If returns false,
6343      *      any members of this object won't be modified, and repetition call will
6344      *      reproduce same error.
6345      */
findTempDecl(Scope * sc,WithScopeSymbol * pwithsym)6346     extern (D) final bool findTempDecl(Scope* sc, WithScopeSymbol* pwithsym)
6347     {
6348         if (pwithsym)
6349             *pwithsym = null;
6350 
6351         if (havetempdecl)
6352             return true;
6353 
6354         //printf("TemplateInstance.findTempDecl() %s\n", toChars());
6355         if (!tempdecl)
6356         {
6357             /* Given:
6358              *    foo!( ... )
6359              * figure out which TemplateDeclaration foo refers to.
6360              */
6361             Identifier id = name;
6362             Dsymbol scopesym;
6363             Dsymbol s = sc.search(loc, id, &scopesym);
6364             if (!s)
6365             {
6366                 s = sc.search_correct(id);
6367                 if (s)
6368                     error("template `%s` is not defined, did you mean %s?", id.toChars(), s.toChars());
6369                 else
6370                     error("template `%s` is not defined", id.toChars());
6371                 return false;
6372             }
6373             static if (LOG)
6374             {
6375                 printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind());
6376                 if (s.parent)
6377                     printf("s.parent = '%s'\n", s.parent.toChars());
6378             }
6379             if (pwithsym)
6380                 *pwithsym = scopesym.isWithScopeSymbol();
6381 
6382             /* We might have found an alias within a template when
6383              * we really want the template.
6384              */
6385             TemplateInstance ti;
6386             if (s.parent && (ti = s.parent.isTemplateInstance()) !is null)
6387             {
6388                 if (ti.tempdecl && ti.tempdecl.ident == id)
6389                 {
6390                     /* This is so that one can refer to the enclosing
6391                      * template, even if it has the same name as a member
6392                      * of the template, if it has a !(arguments)
6393                      */
6394                     TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
6395                     assert(td);
6396                     if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
6397                         td = td.overroot; // then get the start
6398                     s = td;
6399                 }
6400             }
6401 
6402             // The template might originate from a selective import which implies that
6403             // s is a lowered AliasDeclaration of the actual TemplateDeclaration.
6404             // This is the last place where we see the deprecated alias because it is
6405             // stripped below, so check if the selective import was deprecated.
6406             // See https://issues.dlang.org/show_bug.cgi?id=20840.
6407             if (s.isAliasDeclaration())
6408                 s.checkDeprecated(this.loc, sc);
6409 
6410             if (!updateTempDecl(sc, s))
6411             {
6412                 return false;
6413             }
6414         }
6415         assert(tempdecl);
6416 
6417         // Look for forward references
6418         auto tovers = tempdecl.isOverloadSet();
6419         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
6420         {
6421             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
6422             int r = overloadApply(dstart, (Dsymbol s)
6423             {
6424                 auto td = s.isTemplateDeclaration();
6425                 if (!td)
6426                     return 0;
6427 
6428                 if (td.semanticRun == PASS.initial)
6429                 {
6430                     if (td._scope)
6431                     {
6432                         // Try to fix forward reference. Ungag errors while doing so.
6433                         Ungag ungag = td.ungagSpeculative();
6434                         td.dsymbolSemantic(td._scope);
6435                     }
6436                     if (td.semanticRun == PASS.initial)
6437                     {
6438                         error("`%s` forward references template declaration `%s`",
6439                             toChars(), td.toChars());
6440                         return 1;
6441                     }
6442                 }
6443                 return 0;
6444             });
6445             if (r)
6446                 return false;
6447         }
6448         return true;
6449     }
6450 
6451     /**********************************************
6452      * Confirm s is a valid template, then store it.
6453      * Input:
6454      *      sc
6455      *      s   candidate symbol of template. It may be:
6456      *          TemplateDeclaration
6457      *          FuncDeclaration with findTemplateDeclRoot() != NULL
6458      *          OverloadSet which contains candidates
6459      * Returns:
6460      *      true if updating succeeds.
6461      */
updateTempDecl(Scope * sc,Dsymbol s)6462     extern (D) final bool updateTempDecl(Scope* sc, Dsymbol s)
6463     {
6464         if (!s)
6465             return tempdecl !is null;
6466 
6467         Identifier id = name;
6468         s = s.toAlias();
6469 
6470         /* If an OverloadSet, look for a unique member that is a template declaration
6471          */
6472         if (OverloadSet os = s.isOverloadSet())
6473         {
6474             s = null;
6475             foreach (s2; os.a)
6476             {
6477                 if (FuncDeclaration f = s2.isFuncDeclaration())
6478                     s2 = f.findTemplateDeclRoot();
6479                 else
6480                     s2 = s2.isTemplateDeclaration();
6481                 if (s2)
6482                 {
6483                     if (s)
6484                     {
6485                         tempdecl = os;
6486                         return true;
6487                     }
6488                     s = s2;
6489                 }
6490             }
6491             if (!s)
6492             {
6493                 error("template `%s` is not defined", id.toChars());
6494                 return false;
6495             }
6496         }
6497 
6498         if (OverDeclaration od = s.isOverDeclaration())
6499         {
6500             tempdecl = od; // TODO: more strict check
6501             return true;
6502         }
6503 
6504         /* It should be a TemplateDeclaration, not some other symbol
6505          */
6506         if (FuncDeclaration f = s.isFuncDeclaration())
6507             tempdecl = f.findTemplateDeclRoot();
6508         else
6509             tempdecl = s.isTemplateDeclaration();
6510 
6511         // We're done
6512         if (tempdecl)
6513             return true;
6514 
6515         // Error already issued, just return `false`
6516         if (!s.parent && global.errors)
6517             return false;
6518 
6519         if (!s.parent && s.getType())
6520         {
6521             Dsymbol s2 = s.getType().toDsymbol(sc);
6522             if (!s2)
6523             {
6524                 .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());
6525                 return false;
6526             }
6527             // because s can be the alias created for a TemplateParameter
6528             const AliasDeclaration ad = s.isAliasDeclaration();
6529             version (none)
6530             {
6531                 if (ad && ad.isAliasedTemplateParameter())
6532                     printf("`%s` is an alias created from a template parameter\n", s.toChars());
6533             }
6534             if (!ad || !ad.isAliasedTemplateParameter())
6535                 s = s2;
6536         }
6537 
6538         TemplateInstance ti = s.parent ? s.parent.isTemplateInstance() : null;
6539         if (ti && (ti.name == s.ident || ti.toAlias().ident == s.ident) && ti.tempdecl)
6540         {
6541             /* This is so that one can refer to the enclosing
6542              * template, even if it has the same name as a member
6543              * of the template, if it has a !(arguments)
6544              */
6545             TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
6546             assert(td);
6547             if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
6548                 td = td.overroot; // then get the start
6549             tempdecl = td;
6550             return true;
6551         }
6552         else
6553         {
6554             error("`%s` is not a template declaration, it is a %s", id.toChars(), s.kind());
6555             return false;
6556         }
6557     }
6558 
6559     /**********************************
6560      * Run semantic of tiargs as arguments of template.
6561      * Input:
6562      *      loc
6563      *      sc
6564      *      tiargs  array of template arguments
6565      *      flags   1: replace const variables with their initializers
6566      *              2: don't devolve Parameter to Type
6567      * Returns:
6568      *      false if one or more arguments have errors.
6569      */
semanticTiargs(const ref Loc loc,Scope * sc,Objects * tiargs,int flags)6570     extern (D) static bool semanticTiargs(const ref Loc loc, Scope* sc, Objects* tiargs, int flags)
6571     {
6572         // Run semantic on each argument, place results in tiargs[]
6573         //printf("+TemplateInstance.semanticTiargs()\n");
6574         if (!tiargs)
6575             return true;
6576         bool err = false;
6577         for (size_t j = 0; j < tiargs.dim; j++)
6578         {
6579             RootObject o = (*tiargs)[j];
6580             Type ta = isType(o);
6581             Expression ea = isExpression(o);
6582             Dsymbol sa = isDsymbol(o);
6583 
6584             //printf("1: (*tiargs)[%d] = %p, s=%p, v=%p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
6585             if (ta)
6586             {
6587                 //printf("type %s\n", ta.toChars());
6588 
6589                 // It might really be an Expression or an Alias
6590                 ta.resolve(loc, sc, ea, ta, sa, (flags & 1) != 0);
6591                 if (ea)
6592                     goto Lexpr;
6593                 if (sa)
6594                     goto Ldsym;
6595                 if (ta is null)
6596                 {
6597                     assert(global.errors);
6598                     ta = Type.terror;
6599                 }
6600 
6601             Ltype:
6602                 if (ta.ty == Ttuple)
6603                 {
6604                     // Expand tuple
6605                     TypeTuple tt = cast(TypeTuple)ta;
6606                     size_t dim = tt.arguments.dim;
6607                     tiargs.remove(j);
6608                     if (dim)
6609                     {
6610                         tiargs.reserve(dim);
6611                         foreach (i, arg; *tt.arguments)
6612                         {
6613                             if (flags & 2 && (arg.storageClass & STC.parameter))
6614                                 tiargs.insert(j + i, arg);
6615                             else
6616                                 tiargs.insert(j + i, arg.type);
6617                         }
6618                     }
6619                     j--;
6620                     continue;
6621                 }
6622                 if (ta.ty == Terror)
6623                 {
6624                     err = true;
6625                     continue;
6626                 }
6627                 (*tiargs)[j] = ta.merge2();
6628             }
6629             else if (ea)
6630             {
6631             Lexpr:
6632                 //printf("+[%d] ea = %s %s\n", j, EXPtoString(ea.op).ptr, ea.toChars());
6633                 if (flags & 1) // only used by __traits
6634                 {
6635                     ea = ea.expressionSemantic(sc);
6636 
6637                     // must not interpret the args, excepting template parameters
6638                     if (ea.op != EXP.variable || ((cast(VarExp)ea).var.storage_class & STC.templateparameter))
6639                     {
6640                         ea = ea.optimize(WANTvalue);
6641                     }
6642                 }
6643                 else
6644                 {
6645                     sc = sc.startCTFE();
6646                     ea = ea.expressionSemantic(sc);
6647                     sc = sc.endCTFE();
6648 
6649                     if (ea.op == EXP.variable)
6650                     {
6651                         /* If the parameter is a function that is not called
6652                          * explicitly, i.e. `foo!func` as opposed to `foo!func()`,
6653                          * then it is a dsymbol, not the return value of `func()`
6654                          */
6655                         Declaration vd = (cast(VarExp)ea).var;
6656                         if (auto fd = vd.isFuncDeclaration())
6657                         {
6658                             sa = fd;
6659                             goto Ldsym;
6660                         }
6661                         /* Otherwise skip substituting a const var with
6662                          * its initializer. The problem is the initializer won't
6663                          * match with an 'alias' parameter. Instead, do the
6664                          * const substitution in TemplateValueParameter.matchArg().
6665                          */
6666                     }
6667                     else if (definitelyValueParameter(ea))
6668                     {
6669                         if (ea.checkValue()) // check void expression
6670                             ea = ErrorExp.get();
6671                         uint olderrs = global.errors;
6672                         ea = ea.ctfeInterpret();
6673                         if (global.errors != olderrs)
6674                             ea = ErrorExp.get();
6675                     }
6676                 }
6677                 //printf("-[%d] ea = %s %s\n", j, EXPtoString(ea.op).ptr, ea.toChars());
6678                 if (ea.op == EXP.tuple)
6679                 {
6680                     // Expand tuple
6681                     TupleExp te = cast(TupleExp)ea;
6682                     size_t dim = te.exps.dim;
6683                     tiargs.remove(j);
6684                     if (dim)
6685                     {
6686                         tiargs.reserve(dim);
6687                         foreach (i, exp; *te.exps)
6688                             tiargs.insert(j + i, exp);
6689                     }
6690                     j--;
6691                     continue;
6692                 }
6693                 if (ea.op == EXP.error)
6694                 {
6695                     err = true;
6696                     continue;
6697                 }
6698                 (*tiargs)[j] = ea;
6699 
6700                 if (ea.op == EXP.type)
6701                 {
6702                     ta = ea.type;
6703                     goto Ltype;
6704                 }
6705                 if (ea.op == EXP.scope_)
6706                 {
6707                     sa = (cast(ScopeExp)ea).sds;
6708                     goto Ldsym;
6709                 }
6710                 if (ea.op == EXP.function_)
6711                 {
6712                     FuncExp fe = cast(FuncExp)ea;
6713                     /* A function literal, that is passed to template and
6714                      * already semanticed as function pointer, never requires
6715                      * outer frame. So convert it to global function is valid.
6716                      */
6717                     if (fe.fd.tok == TOK.reserved && fe.type.ty == Tpointer)
6718                     {
6719                         // change to non-nested
6720                         fe.fd.tok = TOK.function_;
6721                         fe.fd.vthis = null;
6722                     }
6723                     else if (fe.td)
6724                     {
6725                         /* If template argument is a template lambda,
6726                          * get template declaration itself. */
6727                         //sa = fe.td;
6728                         //goto Ldsym;
6729                     }
6730                 }
6731                 if (ea.op == EXP.dotVariable && !(flags & 1))
6732                 {
6733                     // translate expression to dsymbol.
6734                     sa = (cast(DotVarExp)ea).var;
6735                     goto Ldsym;
6736                 }
6737                 if (ea.op == EXP.template_)
6738                 {
6739                     sa = (cast(TemplateExp)ea).td;
6740                     goto Ldsym;
6741                 }
6742                 if (ea.op == EXP.dotTemplateDeclaration && !(flags & 1))
6743                 {
6744                     // translate expression to dsymbol.
6745                     sa = (cast(DotTemplateExp)ea).td;
6746                     goto Ldsym;
6747                 }
6748                 if (ea.op == EXP.dot)
6749                 {
6750                     if (auto se = (cast(DotExp)ea).e2.isScopeExp())
6751                     {
6752                         sa = se.sds;
6753                         goto Ldsym;
6754                     }
6755                 }
6756             }
6757             else if (sa)
6758             {
6759             Ldsym:
6760                 //printf("dsym %s %s\n", sa.kind(), sa.toChars());
6761                 if (sa.errors)
6762                 {
6763                     err = true;
6764                     continue;
6765                 }
6766 
6767                 TupleDeclaration d = sa.toAlias().isTupleDeclaration();
6768                 if (d)
6769                 {
6770                     // Expand tuple
6771                     tiargs.remove(j);
6772                     tiargs.insert(j, d.objects);
6773                     j--;
6774                     continue;
6775                 }
6776                 if (FuncAliasDeclaration fa = sa.isFuncAliasDeclaration())
6777                 {
6778                     FuncDeclaration f = fa.toAliasFunc();
6779                     if (!fa.hasOverloads && f.isUnique())
6780                     {
6781                         // Strip FuncAlias only when the aliased function
6782                         // does not have any overloads.
6783                         sa = f;
6784                     }
6785                 }
6786                 (*tiargs)[j] = sa;
6787 
6788                 TemplateDeclaration td = sa.isTemplateDeclaration();
6789                 if (td && td.semanticRun == PASS.initial && td.literal)
6790                 {
6791                     td.dsymbolSemantic(sc);
6792                 }
6793                 FuncDeclaration fd = sa.isFuncDeclaration();
6794                 if (fd)
6795                     fd.functionSemantic();
6796             }
6797             else if (isParameter(o))
6798             {
6799             }
6800             else
6801             {
6802                 assert(0);
6803             }
6804             //printf("1: (*tiargs)[%d] = %p\n", j, (*tiargs)[j]);
6805         }
6806         version (none)
6807         {
6808             printf("-TemplateInstance.semanticTiargs()\n");
6809             for (size_t j = 0; j < tiargs.dim; j++)
6810             {
6811                 RootObject o = (*tiargs)[j];
6812                 Type ta = isType(o);
6813                 Expression ea = isExpression(o);
6814                 Dsymbol sa = isDsymbol(o);
6815                 Tuple va = isTuple(o);
6816                 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
6817             }
6818         }
6819         return !err;
6820     }
6821 
6822     /**********************************
6823      * Run semantic on the elements of tiargs.
6824      * Input:
6825      *      sc
6826      * Returns:
6827      *      false if one or more arguments have errors.
6828      * Note:
6829      *      This function is reentrant against error occurrence. If returns false,
6830      *      all elements of tiargs won't be modified.
6831      */
semanticTiargs(Scope * sc)6832     extern (D) final bool semanticTiargs(Scope* sc)
6833     {
6834         //printf("+TemplateInstance.semanticTiargs() %s\n", toChars());
6835         if (semantictiargsdone)
6836             return true;
6837         if (semanticTiargs(loc, sc, tiargs, 0))
6838         {
6839             // cache the result iff semantic analysis succeeded entirely
6840             semantictiargsdone = 1;
6841             return true;
6842         }
6843         return false;
6844     }
6845 
6846     /**********************************
6847      * Find the TemplateDeclaration that matches this TemplateInstance best.
6848      *
6849      * Params:
6850      *   sc    = the scope this TemplateInstance resides in
6851      *   fargs = function arguments in case of a template function, null otherwise
6852      *
6853      * Returns:
6854      *   `true` if a match was found, `false` otherwise
6855      */
findBestMatch(Scope * sc,Expressions * fargs)6856     extern (D) final bool findBestMatch(Scope* sc, Expressions* fargs)
6857     {
6858         if (havetempdecl)
6859         {
6860             TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
6861             assert(tempdecl);
6862             assert(tempdecl._scope);
6863             // Deduce tdtypes
6864             tdtypes.setDim(tempdecl.parameters.dim);
6865             if (!tempdecl.matchWithInstance(sc, this, &tdtypes, fargs, 2))
6866             {
6867                 error("incompatible arguments for template instantiation");
6868                 return false;
6869             }
6870             // TODO: Normalizing tiargs for https://issues.dlang.org/show_bug.cgi?id=7469 is necessary?
6871             return true;
6872         }
6873 
6874         static if (LOG)
6875         {
6876             printf("TemplateInstance.findBestMatch()\n");
6877         }
6878 
6879         uint errs = global.errors;
6880         TemplateDeclaration td_last = null;
6881         Objects dedtypes;
6882 
6883         /* Since there can be multiple TemplateDeclaration's with the same
6884          * name, look for the best match.
6885          */
6886         auto tovers = tempdecl.isOverloadSet();
6887         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
6888         {
6889             TemplateDeclaration td_best;
6890             TemplateDeclaration td_ambig;
6891             MATCH m_best = MATCH.nomatch;
6892 
6893             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
6894             overloadApply(dstart, (Dsymbol s)
6895             {
6896                 auto td = s.isTemplateDeclaration();
6897                 if (!td)
6898                     return 0;
6899                 if (td.inuse)
6900                 {
6901                     td.error(loc, "recursive template expansion");
6902                     return 1;
6903                 }
6904                 if (td == td_best)   // skip duplicates
6905                     return 0;
6906 
6907                 //printf("td = %s\n", td.toPrettyChars());
6908                 // If more arguments than parameters,
6909                 // then this is no match.
6910                 if (td.parameters.dim < tiargs.dim)
6911                 {
6912                     if (!td.isVariadic())
6913                         return 0;
6914                 }
6915 
6916                 dedtypes.setDim(td.parameters.dim);
6917                 dedtypes.zero();
6918                 assert(td.semanticRun != PASS.initial);
6919 
6920                 MATCH m = td.matchWithInstance(sc, this, &dedtypes, fargs, 0);
6921                 //printf("matchWithInstance = %d\n", m);
6922                 if (m == MATCH.nomatch) // no match at all
6923                     return 0;
6924                 if (m < m_best) goto Ltd_best;
6925                 if (m > m_best) goto Ltd;
6926 
6927                 // Disambiguate by picking the most specialized TemplateDeclaration
6928                 {
6929                 MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs);
6930                 MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs);
6931                 //printf("c1 = %d, c2 = %d\n", c1, c2);
6932                 if (c1 > c2) goto Ltd;
6933                 if (c1 < c2) goto Ltd_best;
6934                 }
6935 
6936                 td_ambig = td;
6937                 return 0;
6938 
6939             Ltd_best:
6940                 // td_best is the best match so far
6941                 td_ambig = null;
6942                 return 0;
6943 
6944             Ltd:
6945                 // td is the new best match
6946                 td_ambig = null;
6947                 td_best = td;
6948                 m_best = m;
6949                 tdtypes.setDim(dedtypes.dim);
6950                 memcpy(tdtypes.tdata(), dedtypes.tdata(), tdtypes.dim * (void*).sizeof);
6951                 return 0;
6952             });
6953 
6954             if (td_ambig)
6955             {
6956                 .error(loc, "%s `%s.%s` matches more than one template declaration:\n%s:     `%s`\nand\n%s:     `%s`",
6957                     td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars(),
6958                     td_best.loc.toChars(), td_best.toChars(),
6959                     td_ambig.loc.toChars(), td_ambig.toChars());
6960                 return false;
6961             }
6962             if (td_best)
6963             {
6964                 if (!td_last)
6965                     td_last = td_best;
6966                 else if (td_last != td_best)
6967                 {
6968                     ScopeDsymbol.multiplyDefined(loc, td_last, td_best);
6969                     return false;
6970                 }
6971             }
6972         }
6973 
6974         if (td_last)
6975         {
6976             /* https://issues.dlang.org/show_bug.cgi?id=7469
6977              * Normalize tiargs by using corresponding deduced
6978              * template value parameters and tuples for the correct mangling.
6979              *
6980              * By doing this before hasNestedArgs, CTFEable local variable will be
6981              * accepted as a value parameter. For example:
6982              *
6983              *  void foo() {
6984              *    struct S(int n) {}   // non-global template
6985              *    const int num = 1;   // CTFEable local variable
6986              *    S!num s;             // S!1 is instantiated, not S!num
6987              *  }
6988              */
6989             size_t dim = td_last.parameters.dim - (td_last.isVariadic() ? 1 : 0);
6990             for (size_t i = 0; i < dim; i++)
6991             {
6992                 if (tiargs.dim <= i)
6993                     tiargs.push(tdtypes[i]);
6994                 assert(i < tiargs.dim);
6995 
6996                 auto tvp = (*td_last.parameters)[i].isTemplateValueParameter();
6997                 if (!tvp)
6998                     continue;
6999                 assert(tdtypes[i]);
7000                 // tdtypes[i] is already normalized to the required type in matchArg
7001 
7002                 (*tiargs)[i] = tdtypes[i];
7003             }
7004             if (td_last.isVariadic() && tiargs.dim == dim && tdtypes[dim])
7005             {
7006                 Tuple va = isTuple(tdtypes[dim]);
7007                 assert(va);
7008                 tiargs.pushSlice(va.objects[]);
7009             }
7010         }
7011         else if (errors && inst)
7012         {
7013             // instantiation was failed with error reporting
7014             assert(global.errors);
7015             return false;
7016         }
7017         else
7018         {
7019             auto tdecl = tempdecl.isTemplateDeclaration();
7020 
7021             if (errs != global.errors)
7022                 errorSupplemental(loc, "while looking for match for `%s`", toChars());
7023             else if (tdecl && !tdecl.overnext)
7024             {
7025                 // Only one template, so we can give better error message
7026                 const(char)* msg = "does not match template declaration";
7027                 const(char)* tip;
7028                 const tmsg = tdecl.toCharsNoConstraints();
7029                 const cmsg = tdecl.getConstraintEvalError(tip);
7030                 if (cmsg)
7031                 {
7032                     error("%s `%s`\n%s", msg, tmsg, cmsg);
7033                     if (tip)
7034                         .tip(tip);
7035                 }
7036                 else
7037                 {
7038                     error("%s `%s`", msg, tmsg);
7039 
7040                     if (tdecl.parameters.dim == tiargs.dim)
7041                     {
7042                         // https://issues.dlang.org/show_bug.cgi?id=7352
7043                         // print additional information, e.g. `foo` is not a type
7044                         foreach (i, param; *tdecl.parameters)
7045                         {
7046                             MATCH match = param.matchArg(loc, sc, tiargs, i, tdecl.parameters, &dedtypes, null);
7047                             auto arg = (*tiargs)[i];
7048                             auto sym = arg.isDsymbol;
7049                             auto exp = arg.isExpression;
7050 
7051                             if (exp)
7052                                 exp = exp.optimize(WANTvalue);
7053 
7054                             if (match == MATCH.nomatch &&
7055                                 ((sym && sym.isFuncDeclaration) ||
7056                                  (exp && exp.isVarExp)))
7057                             {
7058                                 if (param.isTemplateTypeParameter)
7059                                     errorSupplemental(loc, "`%s` is not a type", arg.toChars);
7060                                 else if (auto tvp = param.isTemplateValueParameter)
7061                                     errorSupplemental(loc, "`%s` is not of a value of type `%s`",
7062                                                       arg.toChars, tvp.valType.toChars);
7063 
7064                             }
7065                         }
7066                     }
7067                 }
7068             }
7069             else
7070                 .error(loc, "%s `%s.%s` does not match any template declaration", tempdecl.kind(), tempdecl.parent.toPrettyChars(), tempdecl.ident.toChars());
7071             return false;
7072         }
7073 
7074         /* The best match is td_last
7075          */
7076         tempdecl = td_last;
7077 
7078         static if (LOG)
7079         {
7080             printf("\tIt's a match with template declaration '%s'\n", tempdecl.toChars());
7081         }
7082         return (errs == global.errors);
7083     }
7084 
7085     /*****************************************************
7086      * Determine if template instance is really a template function,
7087      * and that template function needs to infer types from the function
7088      * arguments.
7089      *
7090      * Like findBestMatch, iterate possible template candidates,
7091      * but just looks only the necessity of type inference.
7092      */
7093     extern (D) final bool needsTypeInference(Scope* sc, int flag = 0)
7094     {
7095         //printf("TemplateInstance.needsTypeInference() %s\n", toChars());
7096         if (semanticRun != PASS.initial)
7097             return false;
7098 
7099         uint olderrs = global.errors;
7100         Objects dedtypes;
7101         size_t count = 0;
7102 
7103         auto tovers = tempdecl.isOverloadSet();
7104         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
7105         {
7106             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7107             int r = overloadApply(dstart, (Dsymbol s)
7108             {
7109                 auto td = s.isTemplateDeclaration();
7110                 if (!td)
7111                     return 0;
7112                 if (td.inuse)
7113                 {
7114                     td.error(loc, "recursive template expansion");
7115                     return 1;
7116                 }
7117 
7118                 /* If any of the overloaded template declarations need inference,
7119                  * then return true
7120                  */
7121                 if (!td.onemember)
7122                     return 0;
7123                 if (auto td2 = td.onemember.isTemplateDeclaration())
7124                 {
7125                     if (!td2.onemember || !td2.onemember.isFuncDeclaration())
7126                         return 0;
7127                     if (tiargs.dim >= td.parameters.dim - (td.isVariadic() ? 1 : 0))
7128                         return 0;
7129                     return 1;
7130                 }
7131                 auto fd = td.onemember.isFuncDeclaration();
7132                 if (!fd || fd.type.ty != Tfunction)
7133                     return 0;
7134 
7135                 foreach (tp; *td.parameters)
7136                 {
7137                     if (tp.isTemplateThisParameter())
7138                         return 1;
7139                 }
7140 
7141                 /* Determine if the instance arguments, tiargs, are all that is necessary
7142                  * to instantiate the template.
7143                  */
7144                 //printf("tp = %p, td.parameters.dim = %d, tiargs.dim = %d\n", tp, td.parameters.dim, tiargs.dim);
7145                 auto tf = cast(TypeFunction)fd.type;
7146                 if (tf.parameterList.length)
7147                 {
7148                     auto tp = td.isVariadic();
7149                     if (tp && td.parameters.dim > 1)
7150                         return 1;
7151 
7152                     if (!tp && tiargs.dim < td.parameters.dim)
7153                     {
7154                         // Can remain tiargs be filled by default arguments?
7155                         foreach (size_t i; tiargs.dim .. td.parameters.dim)
7156                         {
7157                             if (!(*td.parameters)[i].hasDefaultArg())
7158                                 return 1;
7159                         }
7160                     }
7161 
7162                     foreach (i, fparam; tf.parameterList)
7163                     {
7164                         // 'auto ref' needs inference.
7165                         if (fparam.storageClass & STC.auto_)
7166                             return 1;
7167                     }
7168                 }
7169 
7170                 if (!flag)
7171                 {
7172                     /* Calculate the need for overload resolution.
7173                      * When only one template can match with tiargs, inference is not necessary.
7174                      */
7175                     dedtypes.setDim(td.parameters.dim);
7176                     dedtypes.zero();
7177                     if (td.semanticRun == PASS.initial)
7178                     {
7179                         if (td._scope)
7180                         {
7181                             // Try to fix forward reference. Ungag errors while doing so.
7182                             Ungag ungag = td.ungagSpeculative();
7183                             td.dsymbolSemantic(td._scope);
7184                         }
7185                         if (td.semanticRun == PASS.initial)
7186                         {
7187                             error("`%s` forward references template declaration `%s`", toChars(), td.toChars());
7188                             return 1;
7189                         }
7190                     }
7191                     MATCH m = td.matchWithInstance(sc, this, &dedtypes, null, 0);
7192                     if (m == MATCH.nomatch)
7193                         return 0;
7194                 }
7195 
7196                 /* If there is more than one function template which matches, we may
7197                  * need type inference (see https://issues.dlang.org/show_bug.cgi?id=4430)
7198                  */
7199                 return ++count > 1 ? 1 : 0;
7200             });
7201             if (r)
7202                 return true;
7203         }
7204 
7205         if (olderrs != global.errors)
7206         {
7207             if (!global.gag)
7208             {
7209                 errorSupplemental(loc, "while looking for match for `%s`", toChars());
7210                 semanticRun = PASS.semanticdone;
7211                 inst = this;
7212             }
7213             errors = true;
7214         }
7215         //printf("false\n");
7216         return false;
7217     }
7218 
7219     /*****************************************
7220      * Determines if a TemplateInstance will need a nested
7221      * generation of the TemplateDeclaration.
7222      * Sets enclosing property if so, and returns != 0;
7223      */
hasNestedArgs(Objects * args,bool isstatic)7224     extern (D) final bool hasNestedArgs(Objects* args, bool isstatic)
7225     {
7226         int nested = 0;
7227         //printf("TemplateInstance.hasNestedArgs('%s')\n", tempdecl.ident.toChars());
7228 
7229         // arguments from parent instances are also accessible
7230         if (!enclosing)
7231         {
7232             if (TemplateInstance ti = tempdecl.toParent().isTemplateInstance())
7233                 enclosing = ti.enclosing;
7234         }
7235 
7236         /* A nested instance happens when an argument references a local
7237          * symbol that is on the stack.
7238          */
7239         foreach (o; *args)
7240         {
7241             Expression ea = isExpression(o);
7242             Dsymbol sa = isDsymbol(o);
7243             Tuple va = isTuple(o);
7244             if (ea)
7245             {
7246                 if (ea.op == EXP.variable)
7247                 {
7248                     sa = (cast(VarExp)ea).var;
7249                     goto Lsa;
7250                 }
7251                 if (ea.op == EXP.this_)
7252                 {
7253                     sa = (cast(ThisExp)ea).var;
7254                     goto Lsa;
7255                 }
7256                 if (ea.op == EXP.function_)
7257                 {
7258                     if ((cast(FuncExp)ea).td)
7259                         sa = (cast(FuncExp)ea).td;
7260                     else
7261                         sa = (cast(FuncExp)ea).fd;
7262                     goto Lsa;
7263                 }
7264                 // Emulate Expression.toMangleBuffer call that had exist in TemplateInstance.genIdent.
7265                 if (ea.op != EXP.int64 && ea.op != EXP.float64 && ea.op != EXP.complex80 && ea.op != EXP.null_ && ea.op != EXP.string_ && ea.op != EXP.arrayLiteral && ea.op != EXP.assocArrayLiteral && ea.op != EXP.structLiteral)
7266                 {
7267                     ea.error("expression `%s` is not a valid template value argument", ea.toChars());
7268                     errors = true;
7269                 }
7270             }
7271             else if (sa)
7272             {
7273             Lsa:
7274                 sa = sa.toAlias();
7275                 TemplateDeclaration td = sa.isTemplateDeclaration();
7276                 if (td)
7277                 {
7278                     TemplateInstance ti = sa.toParent().isTemplateInstance();
7279                     if (ti && ti.enclosing)
7280                         sa = ti;
7281                 }
7282                 TemplateInstance ti = sa.isTemplateInstance();
7283                 Declaration d = sa.isDeclaration();
7284                 if ((td && td.literal) || (ti && ti.enclosing) || (d && !d.isDataseg() && !(d.storage_class & STC.manifest) && (!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) && !isTemplateMixin()))
7285                 {
7286                     Dsymbol dparent = sa.toParent2();
7287                     if (!dparent || dparent.isModule)
7288                         goto L1;
7289                     else if (!enclosing)
7290                         enclosing = dparent;
7291                     else if (enclosing != dparent)
7292                     {
7293                         /* Select the more deeply nested of the two.
7294                          * Error if one is not nested inside the other.
7295                          */
7296                         for (Dsymbol p = enclosing; p; p = p.parent)
7297                         {
7298                             if (p == dparent)
7299                                 goto L1; // enclosing is most nested
7300                         }
7301                         for (Dsymbol p = dparent; p; p = p.parent)
7302                         {
7303                             if (p == enclosing)
7304                             {
7305                                 enclosing = dparent;
7306                                 goto L1; // dparent is most nested
7307                             }
7308                         }
7309                         //https://issues.dlang.org/show_bug.cgi?id=17870
7310                         if (dparent.isClassDeclaration() && enclosing.isClassDeclaration())
7311                         {
7312                             auto pc = dparent.isClassDeclaration();
7313                             auto ec = enclosing.isClassDeclaration();
7314                             if (pc.isBaseOf(ec, null))
7315                                 goto L1;
7316                             else if (ec.isBaseOf(pc, null))
7317                             {
7318                                 enclosing = dparent;
7319                                 goto L1;
7320                             }
7321                         }
7322                         error("`%s` is nested in both `%s` and `%s`", toChars(), enclosing.toChars(), dparent.toChars());
7323                         errors = true;
7324                     }
7325                 L1:
7326                     //printf("\tnested inside %s\n", enclosing.toChars());
7327                     nested |= 1;
7328                 }
7329             }
7330             else if (va)
7331             {
7332                 nested |= cast(int)hasNestedArgs(&va.objects, isstatic);
7333             }
7334         }
7335         //printf("-TemplateInstance.hasNestedArgs('%s') = %d\n", tempdecl.ident.toChars(), nested);
7336         return nested != 0;
7337     }
7338 
7339     /*****************************************
7340      * Append 'this' to the specific module members[]
7341      */
appendToModuleMember()7342     extern (D) final Dsymbols* appendToModuleMember()
7343     {
7344         Module mi = minst; // instantiated . inserted module
7345 
7346         //printf("%s.appendToModuleMember() enclosing = %s mi = %s\n",
7347         //    toPrettyChars(),
7348         //    enclosing ? enclosing.toPrettyChars() : null,
7349         //    mi ? mi.toPrettyChars() : null);
7350         if (global.params.allInst || !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 (needsCodegen()).
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             {
7374                 if (mi.importedFrom)
7375                 {
7376                     mi = mi.importedFrom;
7377                     assert(mi.isRoot());
7378                 }
7379                 else
7380                 {
7381                     // This can happen when using the frontend as a library.
7382                     // Append it to the non-root module.
7383                 }
7384             }
7385         }
7386         else
7387         {
7388             /* If the instantiated module is non-root, insert to the member of the
7389              * non-root module. Then:
7390              *  - semantic3 pass won't be called on the instance.
7391              *  - codegen pass won't reach to the instance.
7392              * Unless it is re-appended to a root module later (with changed minst).
7393              */
7394         }
7395         //printf("\t-. mi = %s\n", mi.toPrettyChars());
7396 
7397         assert(!memberOf || (!memberOf.isRoot() && mi.isRoot()), "can only re-append from non-root to root module");
7398 
7399         Dsymbols* a = mi.members;
7400         a.push(this);
7401         memberOf = mi;
7402         if (mi.semanticRun >= PASS.semantic2done && mi.isRoot())
7403             Module.addDeferredSemantic2(this);
7404         if (mi.semanticRun >= PASS.semantic3done && mi.isRoot())
7405             Module.addDeferredSemantic3(this);
7406         return a;
7407     }
7408 
7409     /****************************************************
7410      * Declare parameters of template instance, initialize them with the
7411      * template instance arguments.
7412      */
declareParameters(Scope * sc)7413     extern (D) final void declareParameters(Scope* sc)
7414     {
7415         TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
7416         assert(tempdecl);
7417 
7418         //printf("TemplateInstance.declareParameters()\n");
7419         foreach (i, o; tdtypes) // initializer for tp
7420         {
7421             TemplateParameter tp = (*tempdecl.parameters)[i];
7422             //printf("\ttdtypes[%d] = %p\n", i, o);
7423             tempdecl.declareParameter(sc, tp, o);
7424         }
7425     }
7426 
7427     /****************************************
7428      * This instance needs an identifier for name mangling purposes.
7429      * Create one by taking the template declaration name and adding
7430      * the type signature for it.
7431      */
genIdent(Objects * args)7432     extern (D) final Identifier genIdent(Objects* args)
7433     {
7434         //printf("TemplateInstance.genIdent('%s')\n", tempdecl.ident.toChars());
7435         assert(args is tiargs);
7436         OutBuffer buf;
7437         mangleToBuffer(this, &buf);
7438         //printf("\tgenIdent = %s\n", buf.peekChars());
7439         return Identifier.idPool(buf[]);
7440     }
7441 
expandMembers(Scope * sc2)7442     extern (D) final void expandMembers(Scope* sc2)
7443     {
7444         members.foreachDsymbol( (s) { s.setScope (sc2); } );
7445 
7446         members.foreachDsymbol( (s) { s.importAll(sc2); } );
7447 
7448         void symbolDg(Dsymbol s)
7449         {
7450             //printf("\t semantic on '%s' %p kind %s in '%s'\n",  s.toChars(), s, s.kind(), this.toChars());
7451             //printf("test: enclosing = %d, sc2.parent = %s\n", enclosing, sc2.parent.toChars());
7452             //if (enclosing)
7453             //    s.parent = sc.parent;
7454             //printf("test3: enclosing = %d, s.parent = %s\n", enclosing, s.parent.toChars());
7455             s.dsymbolSemantic(sc2);
7456             //printf("test4: enclosing = %d, s.parent = %s\n", enclosing, s.parent.toChars());
7457             Module.runDeferredSemantic();
7458         }
7459 
7460         members.foreachDsymbol(&symbolDg);
7461     }
7462 
tryExpandMembers(Scope * sc2)7463     extern (D) final void tryExpandMembers(Scope* sc2)
7464     {
7465         __gshared int nest;
7466         // extracted to a function to allow windows SEH to work without destructors in the same function
7467         //printf("%d\n", nest);
7468         if (++nest > global.recursionLimit)
7469         {
7470             global.gag = 0; // ensure error message gets printed
7471             error("recursive expansion exceeded allowed nesting limit");
7472             fatal();
7473         }
7474 
7475         expandMembers(sc2);
7476 
7477         nest--;
7478     }
7479 
trySemantic3(Scope * sc2)7480     extern (D) final void trySemantic3(Scope* sc2)
7481     {
7482         // extracted to a function to allow windows SEH to work without destructors in the same function
7483         __gshared int nest;
7484         //printf("%d\n", nest);
7485         if (++nest > global.recursionLimit)
7486         {
7487             global.gag = 0; // ensure error message gets printed
7488             error("recursive expansion exceeded allowed nesting limit");
7489             fatal();
7490         }
7491 
7492         semantic3(this, sc2);
7493 
7494         --nest;
7495     }
7496 
inout(TemplateInstance)7497     override final inout(TemplateInstance) isTemplateInstance() inout
7498     {
7499         return this;
7500     }
7501 
accept(Visitor v)7502     override void accept(Visitor v)
7503     {
7504         v.visit(this);
7505     }
7506 }
7507 
7508 /**************************************
7509  * IsExpression can evaluate the specified type speculatively, and even if
7510  * it instantiates any symbols, they are normally unnecessary for the
7511  * final executable.
7512  * However, if those symbols leak to the actual code, compiler should remark
7513  * them as non-speculative to generate their code and link to the final executable.
7514  */
unSpeculative(Scope * sc,RootObject o)7515 void unSpeculative(Scope* sc, RootObject o)
7516 {
7517     if (!o)
7518         return;
7519 
7520     if (Tuple tup = isTuple(o))
7521     {
7522         foreach (obj; tup.objects)
7523         {
7524             unSpeculative(sc, obj);
7525         }
7526         return;
7527     }
7528 
7529     Dsymbol s = getDsymbol(o);
7530     if (!s)
7531         return;
7532 
7533     if (Declaration d = s.isDeclaration())
7534     {
7535         if (VarDeclaration vd = d.isVarDeclaration())
7536             o = vd.type;
7537         else if (AliasDeclaration ad = d.isAliasDeclaration())
7538         {
7539             o = ad.getType();
7540             if (!o)
7541                 o = ad.toAlias();
7542         }
7543         else
7544             o = d.toAlias();
7545 
7546         s = getDsymbol(o);
7547         if (!s)
7548             return;
7549     }
7550 
7551     if (TemplateInstance ti = s.isTemplateInstance())
7552     {
7553         // If the instance is already non-speculative,
7554         // or it is leaked to the speculative scope.
7555         if (ti.minst !is null || sc.minst is null)
7556             return;
7557 
7558         // Remark as non-speculative instance.
7559         ti.minst = sc.minst;
7560         if (!ti.tinst)
7561             ti.tinst = sc.tinst;
7562 
7563         unSpeculative(sc, ti.tempdecl);
7564     }
7565 
7566     if (TemplateInstance ti = s.isInstantiated())
7567         unSpeculative(sc, ti);
7568 }
7569 
7570 /**********************************
7571  * Return true if e could be valid only as a template value parameter.
7572  * Return false if it might be an alias or tuple.
7573  * (Note that even in this case, it could still turn out to be a value).
7574  */
definitelyValueParameter(Expression e)7575 bool definitelyValueParameter(Expression e)
7576 {
7577     // None of these can be value parameters
7578     if (e.op == EXP.tuple || e.op == EXP.scope_ ||
7579         e.op == EXP.type || e.op == EXP.dotType ||
7580         e.op == EXP.template_ || e.op == EXP.dotTemplateDeclaration ||
7581         e.op == EXP.function_ || e.op == EXP.error ||
7582         e.op == EXP.this_ || e.op == EXP.super_ ||
7583         e.op == EXP.dot)
7584         return false;
7585 
7586     if (e.op != EXP.dotVariable)
7587         return true;
7588 
7589     /* Template instantiations involving a DotVar expression are difficult.
7590      * In most cases, they should be treated as a value parameter, and interpreted.
7591      * But they might also just be a fully qualified name, which should be treated
7592      * as an alias.
7593      */
7594 
7595     // x.y.f cannot be a value
7596     FuncDeclaration f = (cast(DotVarExp)e).var.isFuncDeclaration();
7597     if (f)
7598         return false;
7599 
7600     while (e.op == EXP.dotVariable)
7601     {
7602         e = (cast(DotVarExp)e).e1;
7603     }
7604     // this.x.y and super.x.y couldn't possibly be valid values.
7605     if (e.op == EXP.this_ || e.op == EXP.super_)
7606         return false;
7607 
7608     // e.type.x could be an alias
7609     if (e.op == EXP.dotType)
7610         return false;
7611 
7612     // var.x.y is the only other possible form of alias
7613     if (e.op != EXP.variable)
7614         return true;
7615 
7616     VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
7617     // func.x.y is not an alias
7618     if (!v)
7619         return true;
7620 
7621     // https://issues.dlang.org/show_bug.cgi?id=16685
7622     // var.x.y where var is a constant available at compile time
7623     if (v.storage_class & STC.manifest)
7624         return true;
7625 
7626     // TODO: Should we force CTFE if it is a global constant?
7627     return false;
7628 }
7629 
7630 /***********************************************************
7631  * https://dlang.org/spec/template-mixin.html
7632  * Syntax:
7633  *    mixin MixinTemplateName [TemplateArguments] [Identifier];
7634  */
7635 extern (C++) final class TemplateMixin : TemplateInstance
7636 {
7637     TypeQualified tqual;
7638 
this(const ref Loc loc,Identifier ident,TypeQualified tqual,Objects * tiargs)7639     extern (D) this(const ref Loc loc, Identifier ident, TypeQualified tqual, Objects* tiargs)
7640     {
7641         super(loc,
7642               tqual.idents.dim ? cast(Identifier)tqual.idents[tqual.idents.dim - 1] : (cast(TypeIdentifier)tqual).ident,
7643               tiargs ? tiargs : new Objects());
7644         //printf("TemplateMixin(ident = '%s')\n", ident ? ident.toChars() : "");
7645         this.ident = ident;
7646         this.tqual = tqual;
7647     }
7648 
syntaxCopy(Dsymbol s)7649     override TemplateInstance syntaxCopy(Dsymbol s)
7650     {
7651         auto tm = new TemplateMixin(loc, ident, tqual.syntaxCopy(), tiargs);
7652         return TemplateInstance.syntaxCopy(tm);
7653     }
7654 
kind()7655     override const(char)* kind() const
7656     {
7657         return "mixin";
7658     }
7659 
oneMember(Dsymbol * ps,Identifier ident)7660     override bool oneMember(Dsymbol* ps, Identifier ident)
7661     {
7662         return Dsymbol.oneMember(ps, ident);
7663     }
7664 
hasPointers()7665     override bool hasPointers()
7666     {
7667         //printf("TemplateMixin.hasPointers() %s\n", toChars());
7668         return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
7669     }
7670 
setFieldOffset(AggregateDeclaration ad,ref FieldState fieldState,bool isunion)7671     override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
7672     {
7673         //printf("TemplateMixin.setFieldOffset() %s\n", toChars());
7674         if (_scope) // if fwd reference
7675             dsymbolSemantic(this, null); // try to resolve it
7676 
7677         members.foreachDsymbol( (s) { s.setFieldOffset(ad, fieldState, isunion); } );
7678     }
7679 
toChars()7680     override const(char)* toChars() const
7681     {
7682         OutBuffer buf;
7683         toCBufferInstance(this, &buf);
7684         return buf.extractChars();
7685     }
7686 
findTempDecl(Scope * sc)7687     extern (D) bool findTempDecl(Scope* sc)
7688     {
7689         // Follow qualifications to find the TemplateDeclaration
7690         if (!tempdecl)
7691         {
7692             Expression e;
7693             Type t;
7694             Dsymbol s;
7695             tqual.resolve(loc, sc, e, t, s);
7696             if (!s)
7697             {
7698                 error("is not defined");
7699                 return false;
7700             }
7701             s = s.toAlias();
7702             tempdecl = s.isTemplateDeclaration();
7703             OverloadSet os = s.isOverloadSet();
7704 
7705             /* If an OverloadSet, look for a unique member that is a template declaration
7706              */
7707             if (os)
7708             {
7709                 Dsymbol ds = null;
7710                 foreach (i, sym; os.a)
7711                 {
7712                     Dsymbol s2 = sym.isTemplateDeclaration();
7713                     if (s2)
7714                     {
7715                         if (ds)
7716                         {
7717                             tempdecl = os;
7718                             break;
7719                         }
7720                         ds = s2;
7721                     }
7722                 }
7723             }
7724             if (!tempdecl)
7725             {
7726                 error("`%s` isn't a template", s.toChars());
7727                 return false;
7728             }
7729         }
7730         assert(tempdecl);
7731 
7732         // Look for forward references
7733         auto tovers = tempdecl.isOverloadSet();
7734         foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
7735         {
7736             Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7737             int r = overloadApply(dstart, (Dsymbol s)
7738             {
7739                 auto td = s.isTemplateDeclaration();
7740                 if (!td)
7741                     return 0;
7742 
7743                 if (td.semanticRun == PASS.initial)
7744                 {
7745                     if (td._scope)
7746                         td.dsymbolSemantic(td._scope);
7747                     else
7748                     {
7749                         semanticRun = PASS.initial;
7750                         return 1;
7751                     }
7752                 }
7753                 return 0;
7754             });
7755             if (r)
7756                 return false;
7757         }
7758         return true;
7759     }
7760 
inout(TemplateMixin)7761     override inout(TemplateMixin) isTemplateMixin() inout
7762     {
7763         return this;
7764     }
7765 
accept(Visitor v)7766     override void accept(Visitor v)
7767     {
7768         v.visit(this);
7769     }
7770 }
7771 
7772 /************************************
7773  * This struct is needed for TemplateInstance to be the key in an associative array.
7774  * Fixing https://issues.dlang.org/show_bug.cgi?id=15812 and
7775  * https://issues.dlang.org/show_bug.cgi?id=15813 would make it unnecessary.
7776  */
7777 struct TemplateInstanceBox
7778 {
7779     TemplateInstance ti;
7780 
thisTemplateInstanceBox7781     this(TemplateInstance ti)
7782     {
7783         this.ti = ti;
7784         this.ti.toHash();
7785         assert(this.ti.hash);
7786     }
7787 
toHashTemplateInstanceBox7788     size_t toHash() const @trusted pure nothrow
7789     {
7790         assert(ti.hash);
7791         return ti.hash;
7792     }
7793 
opEqualsTemplateInstanceBox7794     bool opEquals(ref const TemplateInstanceBox s) @trusted const
7795     {
7796         bool res = void;
7797         if (ti.inst && s.ti.inst)
7798         {
7799             /* This clause is only used when an instance with errors
7800              * is replaced with a correct instance.
7801              */
7802             res = ti is s.ti;
7803         }
7804         else
7805         {
7806             /* Used when a proposed instance is used to see if there's
7807              * an existing instance.
7808              */
7809             static if (__VERSION__ < 2099) // https://issues.dlang.org/show_bug.cgi?id=22717
7810                 res = (cast()s.ti).equalsx(cast()ti);
7811             else
7812                 res = (cast()ti).equalsx(cast()s.ti);
7813         }
7814 
7815         debug (FindExistingInstance) ++(res ? nHits : nCollisions);
7816         return res;
7817     }
7818 
debugTemplateInstanceBox7819     debug (FindExistingInstance)
7820     {
7821         __gshared uint nHits, nCollisions;
7822 
7823         shared static ~this()
7824         {
7825             printf("debug (FindExistingInstance) TemplateInstanceBox.equals hits: %u collisions: %u\n",
7826                    nHits, nCollisions);
7827         }
7828     }
7829 }
7830 
7831 /*******************************************
7832  * Match to a particular TemplateParameter.
7833  * Input:
7834  *      instLoc         location that the template is instantiated.
7835  *      tiargs[]        actual arguments to template instance
7836  *      i               i'th argument
7837  *      parameters[]    template parameters
7838  *      dedtypes[]      deduced arguments to template instance
7839  *      *psparam        set to symbol declared and initialized to dedtypes[i]
7840  */
matchArg(TemplateParameter tp,Loc instLoc,Scope * sc,Objects * tiargs,size_t i,TemplateParameters * parameters,Objects * dedtypes,Declaration * psparam)7841 MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
7842 {
7843     MATCH matchArgNoMatch()
7844     {
7845         if (psparam)
7846             *psparam = null;
7847         return MATCH.nomatch;
7848     }
7849 
7850     MATCH matchArgParameter()
7851     {
7852         RootObject oarg;
7853 
7854         if (i < tiargs.dim)
7855             oarg = (*tiargs)[i];
7856         else
7857         {
7858             // Get default argument instead
7859             oarg = tp.defaultArg(instLoc, sc);
7860             if (!oarg)
7861             {
7862                 assert(i < dedtypes.dim);
7863                 // It might have already been deduced
7864                 oarg = (*dedtypes)[i];
7865                 if (!oarg)
7866                     return matchArgNoMatch();
7867             }
7868         }
7869         return tp.matchArg(sc, oarg, i, parameters, dedtypes, psparam);
7870     }
7871 
7872     MATCH matchArgTuple(TemplateTupleParameter ttp)
7873     {
7874         /* The rest of the actual arguments (tiargs[]) form the match
7875          * for the variadic parameter.
7876          */
7877         assert(i + 1 == dedtypes.dim); // must be the last one
7878         Tuple ovar;
7879 
7880         if (Tuple u = isTuple((*dedtypes)[i]))
7881         {
7882             // It has already been deduced
7883             ovar = u;
7884         }
7885         else if (i + 1 == tiargs.dim && isTuple((*tiargs)[i]))
7886             ovar = isTuple((*tiargs)[i]);
7887         else
7888         {
7889             ovar = new Tuple();
7890             //printf("ovar = %p\n", ovar);
7891             if (i < tiargs.dim)
7892             {
7893                 //printf("i = %d, tiargs.dim = %d\n", i, tiargs.dim);
7894                 ovar.objects.setDim(tiargs.dim - i);
7895                 foreach (j, ref obj; ovar.objects)
7896                     obj = (*tiargs)[i + j];
7897             }
7898         }
7899         return ttp.matchArg(sc, ovar, i, parameters, dedtypes, psparam);
7900     }
7901 
7902     if (auto ttp = tp.isTemplateTupleParameter())
7903         return matchArgTuple(ttp);
7904     else
7905         return matchArgParameter();
7906 }
7907 
matchArg(TemplateParameter tp,Scope * sc,RootObject oarg,size_t i,TemplateParameters * parameters,Objects * dedtypes,Declaration * psparam)7908 MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
7909 {
7910     MATCH matchArgNoMatch()
7911     {
7912         //printf("\tm = %d\n", MATCH.nomatch);
7913         if (psparam)
7914             *psparam = null;
7915         return MATCH.nomatch;
7916     }
7917 
7918     MATCH matchArgType(TemplateTypeParameter ttp)
7919     {
7920         //printf("TemplateTypeParameter.matchArg('%s')\n", ttp.ident.toChars());
7921         MATCH m = MATCH.exact;
7922         Type ta = isType(oarg);
7923         if (!ta)
7924         {
7925             //printf("%s %p %p %p\n", oarg.toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
7926             return matchArgNoMatch();
7927         }
7928         //printf("ta is %s\n", ta.toChars());
7929 
7930         if (ttp.specType)
7931         {
7932             if (!ta || ta == TemplateTypeParameter.tdummy)
7933                 return matchArgNoMatch();
7934 
7935             //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta.toChars(), ttp.specType.toChars());
7936             MATCH m2 = deduceType(ta, sc, ttp.specType, parameters, dedtypes);
7937             if (m2 == MATCH.nomatch)
7938             {
7939                 //printf("\tfailed deduceType\n");
7940                 return matchArgNoMatch();
7941             }
7942 
7943             if (m2 < m)
7944                 m = m2;
7945             if ((*dedtypes)[i])
7946             {
7947                 Type t = cast(Type)(*dedtypes)[i];
7948 
7949                 if (ttp.dependent && !t.equals(ta)) // https://issues.dlang.org/show_bug.cgi?id=14357
7950                     return matchArgNoMatch();
7951 
7952                 /* This is a self-dependent parameter. For example:
7953                  *  template X(T : T*) {}
7954                  *  template X(T : S!T, alias S) {}
7955                  */
7956                 //printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
7957                 ta = t;
7958             }
7959         }
7960         else
7961         {
7962             if ((*dedtypes)[i])
7963             {
7964                 // Must match already deduced type
7965                 Type t = cast(Type)(*dedtypes)[i];
7966 
7967                 if (!t.equals(ta))
7968                 {
7969                     //printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
7970                     return matchArgNoMatch();
7971                 }
7972             }
7973             else
7974             {
7975                 // So that matches with specializations are better
7976                 m = MATCH.convert;
7977             }
7978         }
7979         (*dedtypes)[i] = ta;
7980 
7981         if (psparam)
7982             *psparam = new AliasDeclaration(ttp.loc, ttp.ident, ta);
7983         //printf("\tm = %d\n", m);
7984         return ttp.dependent ? MATCH.exact : m;
7985     }
7986 
7987     MATCH matchArgValue(TemplateValueParameter tvp)
7988     {
7989         //printf("TemplateValueParameter.matchArg('%s')\n", tvp.ident.toChars());
7990         MATCH m = MATCH.exact;
7991 
7992         Expression ei = isExpression(oarg);
7993         Type vt;
7994 
7995         if (!ei && oarg)
7996         {
7997             Dsymbol si = isDsymbol(oarg);
7998             FuncDeclaration f = si ? si.isFuncDeclaration() : null;
7999             if (!f || !f.fbody || f.needThis())
8000                 return matchArgNoMatch();
8001 
8002             ei = new VarExp(tvp.loc, f);
8003             ei = ei.expressionSemantic(sc);
8004 
8005             /* If a function is really property-like, and then
8006              * it's CTFEable, ei will be a literal expression.
8007              */
8008             uint olderrors = global.startGagging();
8009             ei = resolveProperties(sc, ei);
8010             ei = ei.ctfeInterpret();
8011             if (global.endGagging(olderrors) || ei.op == EXP.error)
8012                 return matchArgNoMatch();
8013 
8014             /* https://issues.dlang.org/show_bug.cgi?id=14520
8015              * A property-like function can match to both
8016              * TemplateAlias and ValueParameter. But for template overloads,
8017              * it should always prefer alias parameter to be consistent
8018              * template match result.
8019              *
8020              *   template X(alias f) { enum X = 1; }
8021              *   template X(int val) { enum X = 2; }
8022              *   int f1() { return 0; }  // CTFEable
8023              *   int f2();               // body-less function is not CTFEable
8024              *   enum x1 = X!f1;    // should be 1
8025              *   enum x2 = X!f2;    // should be 1
8026              *
8027              * e.g. The x1 value must be same even if the f1 definition will be moved
8028              *      into di while stripping body code.
8029              */
8030             m = MATCH.convert;
8031         }
8032 
8033         if (ei && ei.op == EXP.variable)
8034         {
8035             // Resolve const variables that we had skipped earlier
8036             ei = ei.ctfeInterpret();
8037         }
8038 
8039         //printf("\tvalType: %s, ty = %d\n", tvp.valType.toChars(), tvp.valType.ty);
8040         vt = tvp.valType.typeSemantic(tvp.loc, sc);
8041         //printf("ei: %s, ei.type: %s\n", ei.toChars(), ei.type.toChars());
8042         //printf("vt = %s\n", vt.toChars());
8043 
8044         if (ei.type)
8045         {
8046             MATCH m2 = ei.implicitConvTo(vt);
8047             //printf("m: %d\n", m);
8048             if (m2 < m)
8049                 m = m2;
8050             if (m == MATCH.nomatch)
8051                 return matchArgNoMatch();
8052             ei = ei.implicitCastTo(sc, vt);
8053             ei = ei.ctfeInterpret();
8054         }
8055 
8056         if (tvp.specValue)
8057         {
8058             if (ei is null || (cast(void*)ei.type in TemplateValueParameter.edummies &&
8059                                TemplateValueParameter.edummies[cast(void*)ei.type] == ei))
8060                 return matchArgNoMatch();
8061 
8062             Expression e = tvp.specValue;
8063 
8064             sc = sc.startCTFE();
8065             e = e.expressionSemantic(sc);
8066             e = resolveProperties(sc, e);
8067             sc = sc.endCTFE();
8068             e = e.implicitCastTo(sc, vt);
8069             e = e.ctfeInterpret();
8070 
8071             ei = ei.syntaxCopy();
8072             sc = sc.startCTFE();
8073             ei = ei.expressionSemantic(sc);
8074             sc = sc.endCTFE();
8075             ei = ei.implicitCastTo(sc, vt);
8076             ei = ei.ctfeInterpret();
8077             //printf("\tei: %s, %s\n", ei.toChars(), ei.type.toChars());
8078             //printf("\te : %s, %s\n", e.toChars(), e.type.toChars());
8079             if (!ei.equals(e))
8080                 return matchArgNoMatch();
8081         }
8082         else
8083         {
8084             if ((*dedtypes)[i])
8085             {
8086                 // Must match already deduced value
8087                 Expression e = cast(Expression)(*dedtypes)[i];
8088                 if (!ei || !ei.equals(e))
8089                     return matchArgNoMatch();
8090             }
8091         }
8092         (*dedtypes)[i] = ei;
8093 
8094         if (psparam)
8095         {
8096             Initializer _init = new ExpInitializer(tvp.loc, ei);
8097             Declaration sparam = new VarDeclaration(tvp.loc, vt, tvp.ident, _init);
8098             sparam.storage_class = STC.manifest;
8099             *psparam = sparam;
8100         }
8101         return tvp.dependent ? MATCH.exact : m;
8102     }
8103 
8104     MATCH matchArgAlias(TemplateAliasParameter tap)
8105     {
8106         //printf("TemplateAliasParameter.matchArg('%s')\n", tap.ident.toChars());
8107         MATCH m = MATCH.exact;
8108         Type ta = isType(oarg);
8109         RootObject sa = ta && !ta.deco ? null : getDsymbol(oarg);
8110         Expression ea = isExpression(oarg);
8111         if (ea && (ea.op == EXP.this_ || ea.op == EXP.super_))
8112             sa = (cast(ThisExp)ea).var;
8113         else if (ea && ea.op == EXP.scope_)
8114             sa = (cast(ScopeExp)ea).sds;
8115         if (sa)
8116         {
8117             if ((cast(Dsymbol)sa).isAggregateDeclaration())
8118                 m = MATCH.convert;
8119 
8120             /* specType means the alias must be a declaration with a type
8121              * that matches specType.
8122              */
8123             if (tap.specType)
8124             {
8125                 Declaration d = (cast(Dsymbol)sa).isDeclaration();
8126                 if (!d)
8127                     return matchArgNoMatch();
8128                 if (!d.type.equals(tap.specType))
8129                     return matchArgNoMatch();
8130             }
8131         }
8132         else
8133         {
8134             sa = oarg;
8135             if (ea)
8136             {
8137                 if (tap.specType)
8138                 {
8139                     if (!ea.type.equals(tap.specType))
8140                         return matchArgNoMatch();
8141                 }
8142             }
8143             else if (ta && ta.ty == Tinstance && !tap.specAlias)
8144             {
8145                 /* Specialized parameter should be preferred
8146                  * match to the template type parameter.
8147                  *  template X(alias a) {}                      // a == this
8148                  *  template X(alias a : B!A, alias B, A...) {} // B!A => ta
8149                  */
8150             }
8151             else if (sa && sa == TemplateTypeParameter.tdummy)
8152             {
8153                 /* https://issues.dlang.org/show_bug.cgi?id=2025
8154                  * Aggregate Types should preferentially
8155                  * match to the template type parameter.
8156                  *  template X(alias a) {}  // a == this
8157                  *  template X(T) {}        // T => sa
8158                  */
8159             }
8160             else if (ta && ta.ty != Tident)
8161             {
8162                 /* Match any type that's not a TypeIdentifier to alias parameters,
8163                  * but prefer type parameter.
8164                  * template X(alias a) { }  // a == ta
8165                  *
8166                  * TypeIdentifiers are excluded because they might be not yet resolved aliases.
8167                  */
8168                 m = MATCH.convert;
8169             }
8170             else
8171                 return matchArgNoMatch();
8172         }
8173 
8174         if (tap.specAlias)
8175         {
8176             if (sa == TemplateAliasParameter.sdummy)
8177                 return matchArgNoMatch();
8178             // check specialization if template arg is a symbol
8179             Dsymbol sx = isDsymbol(sa);
8180             if (sa != tap.specAlias && sx)
8181             {
8182                 Type talias = isType(tap.specAlias);
8183                 if (!talias)
8184                     return matchArgNoMatch();
8185 
8186                 TemplateInstance ti = sx.isTemplateInstance();
8187                 if (!ti && sx.parent)
8188                 {
8189                     ti = sx.parent.isTemplateInstance();
8190                     if (ti && ti.name != sx.ident)
8191                         return matchArgNoMatch();
8192                 }
8193                 if (!ti)
8194                     return matchArgNoMatch();
8195 
8196                 Type t = new TypeInstance(Loc.initial, ti);
8197                 MATCH m2 = deduceType(t, sc, talias, parameters, dedtypes);
8198                 if (m2 == MATCH.nomatch)
8199                     return matchArgNoMatch();
8200             }
8201             // check specialization if template arg is a type
8202             else if (ta)
8203             {
8204                 if (Type tspec = isType(tap.specAlias))
8205                 {
8206                     MATCH m2 = ta.implicitConvTo(tspec);
8207                     if (m2 == MATCH.nomatch)
8208                         return matchArgNoMatch();
8209                 }
8210                 else
8211                 {
8212                     error(tap.loc, "template parameter specialization for a type must be a type and not `%s`",
8213                         tap.specAlias.toChars());
8214                     return matchArgNoMatch();
8215                 }
8216             }
8217         }
8218         else if ((*dedtypes)[i])
8219         {
8220             // Must match already deduced symbol
8221             RootObject si = (*dedtypes)[i];
8222             if (!sa || si != sa)
8223                 return matchArgNoMatch();
8224         }
8225         (*dedtypes)[i] = sa;
8226 
8227         if (psparam)
8228         {
8229             if (Dsymbol s = isDsymbol(sa))
8230             {
8231                 *psparam = new AliasDeclaration(tap.loc, tap.ident, s);
8232             }
8233             else if (Type t = isType(sa))
8234             {
8235                 *psparam = new AliasDeclaration(tap.loc, tap.ident, t);
8236             }
8237             else
8238             {
8239                 assert(ea);
8240 
8241                 // Declare manifest constant
8242                 Initializer _init = new ExpInitializer(tap.loc, ea);
8243                 auto v = new VarDeclaration(tap.loc, null, tap.ident, _init);
8244                 v.storage_class = STC.manifest;
8245                 v.dsymbolSemantic(sc);
8246                 *psparam = v;
8247             }
8248         }
8249         return tap.dependent ? MATCH.exact : m;
8250     }
8251 
8252     MATCH matchArgTuple(TemplateTupleParameter ttp)
8253     {
8254         //printf("TemplateTupleParameter.matchArg('%s')\n", ttp.ident.toChars());
8255         Tuple ovar = isTuple(oarg);
8256         if (!ovar)
8257             return MATCH.nomatch;
8258         if ((*dedtypes)[i])
8259         {
8260             Tuple tup = isTuple((*dedtypes)[i]);
8261             if (!tup)
8262                 return MATCH.nomatch;
8263             if (!match(tup, ovar))
8264                 return MATCH.nomatch;
8265         }
8266         (*dedtypes)[i] = ovar;
8267 
8268         if (psparam)
8269             *psparam = new TupleDeclaration(ttp.loc, ttp.ident, &ovar.objects);
8270         return ttp.dependent ? MATCH.exact : MATCH.convert;
8271     }
8272 
8273     if (auto ttp = tp.isTemplateTypeParameter())
8274         return matchArgType(ttp);
8275     else if (auto tvp = tp.isTemplateValueParameter())
8276         return matchArgValue(tvp);
8277     else if (auto tap = tp.isTemplateAliasParameter())
8278         return matchArgAlias(tap);
8279     else if (auto ttp = tp.isTemplateTupleParameter())
8280         return matchArgTuple(ttp);
8281     else
8282         assert(0);
8283 }
8284 
8285 
8286 /***********************************************
8287  * Collect and print statistics on template instantiations.
8288  */
8289 struct TemplateStats
8290 {
8291     __gshared TemplateStats[const void*] stats;
8292 
8293     uint numInstantiations;     // number of instantiations of the template
8294     uint uniqueInstantiations;  // number of unique instantiations of the template
8295 
8296     TemplateInstances* allInstances;
8297 
8298     /*******************************
8299      * Add this instance
8300      */
incInstanceTemplateStats8301     static void incInstance(const TemplateDeclaration td,
8302                             const TemplateInstance ti)
8303     {
8304         void log(ref TemplateStats ts)
8305         {
8306             if (ts.allInstances is null)
8307                 ts.allInstances = new TemplateInstances();
8308             if (global.params.vtemplatesListInstances)
8309                 ts.allInstances.push(cast() ti);
8310         }
8311 
8312     // message(ti.loc, "incInstance %p %p", td, ti);
8313         if (!global.params.vtemplates)
8314             return;
8315         if (!td)
8316             return;
8317         assert(ti);
8318         if (auto ts = cast(const void*) td in stats)
8319         {
8320             log(*ts);
8321             ++ts.numInstantiations;
8322         }
8323         else
8324         {
8325             stats[cast(const void*) td] = TemplateStats(1, 0);
8326             log(stats[cast(const void*) td]);
8327         }
8328     }
8329 
8330     /*******************************
8331      * Add this unique instance
8332      */
incUniqueTemplateStats8333     static void incUnique(const TemplateDeclaration td,
8334                           const TemplateInstance ti)
8335     {
8336         // message(ti.loc, "incUnique %p %p", td, ti);
8337         if (!global.params.vtemplates)
8338             return;
8339         if (!td)
8340             return;
8341         assert(ti);
8342         if (auto ts = cast(const void*) td in stats)
8343             ++ts.uniqueInstantiations;
8344         else
8345             stats[cast(const void*) td] = TemplateStats(0, 1);
8346     }
8347 }
8348 
printTemplateStats()8349 extern (C++) void printTemplateStats()
8350 {
8351     static struct TemplateDeclarationStats
8352     {
8353         TemplateDeclaration td;
8354         TemplateStats ts;
8355         static int compare(scope const TemplateDeclarationStats* a,
8356                            scope const TemplateDeclarationStats* b) @safe nothrow @nogc pure
8357         {
8358             auto diff = b.ts.uniqueInstantiations - a.ts.uniqueInstantiations;
8359             if (diff)
8360                 return diff;
8361             else
8362                 return b.ts.numInstantiations - a.ts.numInstantiations;
8363         }
8364     }
8365 
8366     if (!global.params.vtemplates)
8367         return;
8368 
8369     Array!(TemplateDeclarationStats) sortedStats;
8370     sortedStats.reserve(TemplateStats.stats.length);
8371     foreach (td_, ref ts; TemplateStats.stats)
8372     {
8373         sortedStats.push(TemplateDeclarationStats(cast(TemplateDeclaration) td_, ts));
8374     }
8375 
8376     sortedStats.sort!(TemplateDeclarationStats.compare);
8377 
8378     foreach (const ref ss; sortedStats[])
8379     {
8380         if (global.params.vtemplatesListInstances &&
8381             ss.ts.allInstances)
8382         {
8383             message(ss.td.loc,
8384                     "vtemplate: %u (%u distinct) instantiation(s) of template `%s` found, they are:",
8385                     ss.ts.numInstantiations,
8386                     ss.ts.uniqueInstantiations,
8387                     ss.td.toCharsNoConstraints());
8388             foreach (const ti; (*ss.ts.allInstances)[])
8389             {
8390                 if (ti.tinst)   // if has enclosing instance
8391                     message(ti.loc, "vtemplate: implicit instance `%s`", ti.toChars());
8392                 else
8393                     message(ti.loc, "vtemplate: explicit instance `%s`", ti.toChars());
8394             }
8395         }
8396         else
8397         {
8398             message(ss.td.loc,
8399                     "vtemplate: %u (%u distinct) instantiation(s) of template `%s` found",
8400                     ss.ts.numInstantiations,
8401                     ss.ts.uniqueInstantiations,
8402                     ss.td.toCharsNoConstraints());
8403         }
8404     }
8405 }
8406 
8407 /// Pair of MATCHes
8408 private struct MATCHpair
8409 {
8410     MATCH mta;  /// match template parameters by initial template arguments
8411     MATCH mfa;  /// match template parameters by inferred template arguments
8412 
thisMATCHpair8413     debug this(MATCH mta, MATCH mfa)
8414     {
8415         assert(MATCH.min <= mta && mta <= MATCH.max);
8416         assert(MATCH.min <= mfa && mfa <= MATCH.max);
8417         this.mta = mta;
8418         this.mfa = mfa;
8419     }
8420 }
8421 
write(ref OutBuffer buf,RootObject obj)8422 private void write(ref OutBuffer buf, RootObject obj)
8423 {
8424     if (obj)
8425     {
8426         buf.writestring(obj.toChars());
8427     }
8428 }
8429