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
39module dmd.dtemplate;
40
41import core.stdc.stdio;
42import core.stdc.string;
43import dmd.aggregate;
44import dmd.aliasthis;
45import dmd.arraytypes;
46import dmd.astenums;
47import dmd.ast_node;
48import dmd.dcast;
49import dmd.dclass;
50import dmd.declaration;
51import dmd.dmangle;
52import dmd.dmodule;
53import dmd.dscope;
54import dmd.dsymbol;
55import dmd.dsymbolsem;
56import dmd.errors;
57import dmd.expression;
58import dmd.expressionsem;
59import dmd.func;
60import dmd.globals;
61import dmd.hdrgen;
62import dmd.id;
63import dmd.identifier;
64import dmd.impcnvtab;
65import dmd.init;
66import dmd.initsem;
67import dmd.mtype;
68import dmd.opover;
69import dmd.root.array;
70import dmd.common.outbuffer;
71import dmd.root.rootobject;
72import dmd.semantic2;
73import dmd.semantic3;
74import dmd.tokens;
75import dmd.typesem;
76import dmd.visitor;
77
78import dmd.templateparamsem;
79
80//debug = FindExistingInstance; // print debug stats of findExistingInstance
81private enum LOG = false;
82
83enum IDX_NOTFOUND = 0x12345678;
84
85pure nothrow @nogc
86{
87
88/********************************************
89 * These functions substitute for dynamic_cast. dynamic_cast does not work
90 * on earlier versions of gcc.
91 */
92extern (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
100extern (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
108extern (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
116extern (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
124extern (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
132extern (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 */
142extern (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 */
160bool 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 */
173inout(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
186Dsymbol 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
215private 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 */
231private 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
248private 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 */
258private 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    }
347Lmatch:
348    static if (log)
349        printf("\t. match\n");
350    return true;
351
352Lnomatch:
353    static if (log)
354        printf("\t. nomatch\n");
355    return false;
356}
357
358/************************************
359 * Match an array of them.
360 */
361private 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 */
385private 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 */
417private 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
495RootObject 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
506extern (C++) final class Tuple : RootObject
507{
508    Objects objects;
509
510    extern (D) this() {}
511
512    /**
513    Params:
514        numObjects = The initial number of objects.
515    */
516    extern (D) this(size_t numObjects)
517    {
518        objects.setDim(numObjects);
519    }
520
521    // kludge for template.isType()
522    override DYNCAST dyncast() const
523    {
524        return DYNCAST.tuple;
525    }
526
527    override const(char)* toChars() const
528    {
529        return objects.toChars();
530    }
531}
532
533struct 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 */
545extern (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        }
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
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     */
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
718    override bool hasStaticCtorOrDtor()
719    {
720        return false; // don't scan uninstantiated templates
721    }
722
723    override const(char)* kind() const
724    {
725        return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template";
726    }
727
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     */
736    const(char)* toCharsNoConstraints() const
737    {
738        return toCharsMaybeConstraints(false);
739    }
740
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
780    override Visibility visible() pure nothrow @nogc @safe
781    {
782        return visibility;
783    }
784
785    /****************************
786     * Check to see if constraint is satisfied.
787     */
788    extern (D) bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
789    {
790        /* Detect recursive attempts to instantiate this template declaration,
791         * https://issues.dlang.org/show_bug.cgi?id=4072
792         *  void foo(T)(T x) if (is(typeof(foo(x)))) { }
793         *  static assert(!is(typeof(foo(7))));
794         * Recursive attempts are regarded as a constraint failure.
795         */
796        /* There's a chicken-and-egg problem here. We don't know yet if this template
797         * instantiation will be a local one (enclosing is set), and we won't know until
798         * after selecting the correct template. Thus, function we're nesting inside
799         * is not on the sc scope chain, and this can cause errors in FuncDeclaration.getLevel().
800         * Workaround the problem by setting a flag to relax the checking on frame errors.
801         */
802
803        for (TemplatePrevious* p = previous; p; p = p.prev)
804        {
805            if (!arrayObjectMatch(p.dedargs, dedargs))
806                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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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
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     */
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
2525    extern(C++) override bool isDeprecated() const
2526    {
2527        return this.deprecated_;
2528    }
2529
2530    /***********************************
2531     * We can overload templates.
2532     */
2533    override bool isOverloadable() const
2534    {
2535        return true;
2536    }
2537
2538    override void accept(Visitor v)
2539    {
2540        v.visit(this);
2541    }
2542}
2543
2544extern (C++) final class TypeDeduced : Type
2545{
2546    Type tded;
2547    Expressions argexps; // corresponding expressions
2548    Types tparams; // tparams[i].mod
2549
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
2558    void update(Expression e, Type tparam)
2559    {
2560        argexps.push(e);
2561        tparams.push(tparam);
2562    }
2563
2564    void update(Type tt, Expression e, Type tparam)
2565    {
2566        tded = tt;
2567        argexps.push(e);
2568        tparams.push(tparam);
2569    }
2570
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 */
2606void 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();
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
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
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 */
3158private 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
3169private 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
3180private 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 */
3242private 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
3263private 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 */
3495MATCH 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
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
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
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
3806        override void visit(TypeDArray t)
3807        {
3808            visit(cast(Type)t);
3809        }
3810
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
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
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
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
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
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
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         */
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
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
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
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
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
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
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
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
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
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
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 */
4922bool 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 */
4933private 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 */
5031private 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 */
5291extern (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 =============================== */
5307    extern (D) this(const ref Loc loc, Identifier ident)
5308    {
5309        this.loc = loc;
5310        this.ident = ident;
5311    }
5312
5313    TemplateTypeParameter isTemplateTypeParameter()
5314    {
5315        return null;
5316    }
5317
5318    TemplateValueParameter isTemplateValueParameter()
5319    {
5320        return null;
5321    }
5322
5323    TemplateAliasParameter isTemplateAliasParameter()
5324    {
5325        return null;
5326    }
5327
5328    TemplateThisParameter isTemplateThisParameter()
5329    {
5330        return null;
5331    }
5332
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
5350    override const(char)* toChars() const
5351    {
5352        return this.ident.toChars();
5353    }
5354
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
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 */
5375extern (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
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
5389    override final TemplateTypeParameter isTemplateTypeParameter()
5390    {
5391        return this;
5392    }
5393
5394    override TemplateTypeParameter syntaxCopy()
5395    {
5396        return new TemplateTypeParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5397    }
5398
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
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
5423    override final RootObject specialization()
5424    {
5425        return specType;
5426    }
5427
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
5439    override final bool hasDefaultArg()
5440    {
5441        return defaultType !is null;
5442    }
5443
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
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 */
5468extern (C++) final class TemplateThisParameter : TemplateTypeParameter
5469{
5470    extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType)
5471    {
5472        super(loc, ident, specType, defaultType);
5473    }
5474
5475    override TemplateThisParameter isTemplateThisParameter()
5476    {
5477        return this;
5478    }
5479
5480    override TemplateThisParameter syntaxCopy()
5481    {
5482        return new TemplateThisParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5483    }
5484
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 */
5496extern (C++) final class TemplateValueParameter : TemplateParameter
5497{
5498    Type valType;
5499    Expression specValue;
5500    Expression defaultValue;
5501
5502    extern (D) __gshared Expression[void*] edummies;
5503
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
5513    override TemplateValueParameter isTemplateValueParameter()
5514    {
5515        return this;
5516    }
5517
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
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
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
5556    override RootObject specialization()
5557    {
5558        return specValue;
5559    }
5560
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
5580    override bool hasDefaultArg()
5581    {
5582        return defaultValue !is null;
5583    }
5584
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
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 */
5614extern (C++) final class TemplateAliasParameter : TemplateParameter
5615{
5616    Type specType;
5617    RootObject specAlias;
5618    RootObject defaultAlias;
5619
5620    extern (D) __gshared Dsymbol sdummy = null;
5621
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
5630    override TemplateAliasParameter isTemplateAliasParameter()
5631    {
5632        return this;
5633    }
5634
5635    override TemplateAliasParameter syntaxCopy()
5636    {
5637        return new TemplateAliasParameter(loc, ident, specType ? specType.syntaxCopy() : null, objectSyntaxCopy(specAlias), objectSyntaxCopy(defaultAlias));
5638    }
5639
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
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
5655    override RootObject specialization()
5656    {
5657        return specAlias;
5658    }
5659
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
5677    override bool hasDefaultArg()
5678    {
5679        return defaultAlias !is null;
5680    }
5681
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
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 */
5705extern (C++) final class TemplateTupleParameter : TemplateParameter
5706{
5707    extern (D) this(const ref Loc loc, Identifier ident)
5708    {
5709        super(loc, ident);
5710    }
5711
5712    override TemplateTupleParameter isTemplateTupleParameter()
5713    {
5714        return this;
5715    }
5716
5717    override TemplateTupleParameter syntaxCopy()
5718    {
5719        return new TemplateTupleParameter(loc, ident);
5720    }
5721
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
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
5756    override RootObject specialization()
5757    {
5758        return null;
5759    }
5760
5761    override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5762    {
5763        return null;
5764    }
5765
5766    override bool hasDefaultArg()
5767    {
5768        return false;
5769    }
5770
5771    override RootObject dummyArg()
5772    {
5773        return null;
5774    }
5775
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 */
5789extern (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    {
5836        ushort nest() const { return _nest & Flag.available; }
5837        void nestUp() { assert(nest() < Flag.available); ++_nest; }
5838        void nestDown() { assert(nest() > 0); --_nest; }
5839        /// has semanticTiargs() been done?
5840        bool semantictiargsdone() const { return (_nest & Flag.semantictiargsdone) != 0; }
5841        void semantictiargsdone(bool x)
5842        {
5843            if (x) _nest |= Flag.semantictiargsdone;
5844            else _nest &= ~Flag.semantictiargsdone;
5845        }
5846        /// if used second constructor
5847        bool havetempdecl() const { return (_nest & Flag.havetempdecl) != 0; }
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
5854        bool gagged() const { return (_nest & Flag.gagged) != 0; }
5855        void gagged(bool x)
5856        {
5857            if (x) _nest |= Flag.gagged;
5858            else _nest &= ~Flag.gagged;
5859        }
5860    }
5861
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     */
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
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
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
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
5949    override const(char)* kind() const
5950    {
5951        return "template instance";
5952    }
5953
5954    override bool oneMember(Dsymbol* ps, Identifier ident)
5955    {
5956        *ps = null;
5957        return true;
5958    }
5959
5960    override const(char)* toChars() const
5961    {
5962        OutBuffer buf;
5963        toCBufferInstance(this, &buf);
5964        return buf.extractChars();
5965    }
5966
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     */
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     */
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
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    */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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
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
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
7497    override final inout(TemplateInstance) isTemplateInstance() inout
7498    {
7499        return this;
7500    }
7501
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 */
7515void 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 */
7575bool 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 */
7635extern (C++) final class TemplateMixin : TemplateInstance
7636{
7637    TypeQualified tqual;
7638
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
7649    override TemplateInstance syntaxCopy(Dsymbol s)
7650    {
7651        auto tm = new TemplateMixin(loc, ident, tqual.syntaxCopy(), tiargs);
7652        return TemplateInstance.syntaxCopy(tm);
7653    }
7654
7655    override const(char)* kind() const
7656    {
7657        return "mixin";
7658    }
7659
7660    override bool oneMember(Dsymbol* ps, Identifier ident)
7661    {
7662        return Dsymbol.oneMember(ps, ident);
7663    }
7664
7665    override bool hasPointers()
7666    {
7667        //printf("TemplateMixin.hasPointers() %s\n", toChars());
7668        return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
7669    }
7670
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
7680    override const(char)* toChars() const
7681    {
7682        OutBuffer buf;
7683        toCBufferInstance(this, &buf);
7684        return buf.extractChars();
7685    }
7686
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
7761    override inout(TemplateMixin) isTemplateMixin() inout
7762    {
7763        return this;
7764    }
7765
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 */
7777struct TemplateInstanceBox
7778{
7779    TemplateInstance ti;
7780
7781    this(TemplateInstance ti)
7782    {
7783        this.ti = ti;
7784        this.ti.toHash();
7785        assert(this.ti.hash);
7786    }
7787
7788    size_t toHash() const @trusted pure nothrow
7789    {
7790        assert(ti.hash);
7791        return ti.hash;
7792    }
7793
7794    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
7819    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 */
7841MATCH 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
7908MATCH 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 */
8289struct 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     */
8301    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     */
8333    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
8349extern (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
8408private struct MATCHpair
8409{
8410    MATCH mta;  /// match template parameters by initial template arguments
8411    MATCH mfa;  /// match template parameters by inferred template arguments
8412
8413    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
8422private void write(ref OutBuffer buf, RootObject obj)
8423{
8424    if (obj)
8425    {
8426        buf.writestring(obj.toChars());
8427    }
8428}
8429