d: Merge upstream dmd, druntime f1a045928e
[official-gcc.git] / gcc / d / dmd / dtemplate.d
blobe440b9e2eb659031ca9eb536fea30abdd2869529
1 /**
2 * Defines `TemplateDeclaration`, `TemplateInstance` and a few utilities
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.
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`
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`.
31 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
32 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
33 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
34 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d, _dtemplate.d)
35 * Documentation: https://dlang.org/phobos/dmd_dtemplate.html
36 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dtemplate.d
39 module dmd.dtemplate;
41 import core.stdc.stdio;
42 import core.stdc.string;
43 import dmd.aggregate;
44 import dmd.aliasthis;
45 import dmd.arraytypes;
46 import dmd.astenums;
47 import dmd.ast_node;
48 import dmd.attrib;
49 import dmd.dcast;
50 import dmd.dclass;
51 import dmd.declaration;
52 import dmd.dinterpret;
53 import dmd.dmangle;
54 import dmd.dmodule;
55 import dmd.dscope;
56 import dmd.dsymbol;
57 import dmd.dsymbolsem;
58 import dmd.errors;
59 import dmd.expression;
60 import dmd.expressionsem;
61 import dmd.func;
62 import dmd.globals;
63 import dmd.hdrgen;
64 import dmd.id;
65 import dmd.identifier;
66 import dmd.impcnvtab;
67 import dmd.init;
68 import dmd.initsem;
69 import dmd.location;
70 import dmd.mtype;
71 import dmd.opover;
72 import dmd.optimize;
73 import dmd.root.array;
74 import dmd.common.outbuffer;
75 import dmd.rootobject;
76 import dmd.semantic2;
77 import dmd.semantic3;
78 import dmd.tokens;
79 import dmd.typesem;
80 import dmd.visitor;
82 import dmd.templateparamsem;
84 //debug = FindExistingInstance; // print debug stats of findExistingInstance
85 private enum LOG = false;
87 enum IDX_NOTFOUND = 0x12345678;
89 pure nothrow @nogc @safe
92 /********************************************
93 * These functions substitute for dynamic_cast. dynamic_cast does not work
94 * on earlier versions of gcc.
96 extern (C++) inout(Expression) isExpression(inout RootObject o)
98 //return dynamic_cast<Expression *>(o);
99 if (!o || o.dyncast() != DYNCAST.expression)
100 return null;
101 return cast(inout(Expression))o;
104 extern (C++) inout(Dsymbol) isDsymbol(inout RootObject o)
106 //return dynamic_cast<Dsymbol *>(o);
107 if (!o || o.dyncast() != DYNCAST.dsymbol)
108 return null;
109 return cast(inout(Dsymbol))o;
112 extern (C++) inout(Type) isType(inout RootObject o)
114 //return dynamic_cast<Type *>(o);
115 if (!o || o.dyncast() != DYNCAST.type)
116 return null;
117 return cast(inout(Type))o;
120 extern (C++) inout(Tuple) isTuple(inout RootObject o)
122 //return dynamic_cast<Tuple *>(o);
123 if (!o || o.dyncast() != DYNCAST.tuple)
124 return null;
125 return cast(inout(Tuple))o;
128 extern (C++) inout(Parameter) isParameter(inout RootObject o)
130 //return dynamic_cast<Parameter *>(o);
131 if (!o || o.dyncast() != DYNCAST.parameter)
132 return null;
133 return cast(inout(Parameter))o;
136 extern (C++) inout(TemplateParameter) isTemplateParameter(inout RootObject o)
138 if (!o || o.dyncast() != DYNCAST.templateparameter)
139 return null;
140 return cast(inout(TemplateParameter))o;
143 /**************************************
144 * Is this Object an error?
146 extern (C++) bool isError(const RootObject o)
148 if (const t = isType(o))
149 return (t.ty == Terror);
150 if (const e = isExpression(o))
151 return (e.op == EXP.error || !e.type || e.type.ty == Terror);
152 if (const v = isTuple(o))
153 return arrayObjectIsError(&v.objects);
154 const s = isDsymbol(o);
155 assert(s);
156 if (s.errors)
157 return true;
158 return s.parent ? isError(s.parent) : false;
161 /**************************************
162 * Are any of the Objects an error?
164 bool arrayObjectIsError(const Objects* args)
166 foreach (const o; *args)
168 if (isError(o))
169 return true;
171 return false;
174 /***********************
175 * Try to get arg as a type.
177 inout(Type) getType(inout RootObject o)
179 inout t = isType(o);
180 if (!t)
182 if (inout e = isExpression(o))
183 return e.type;
185 return t;
190 Dsymbol getDsymbol(RootObject oarg)
192 //printf("getDsymbol()\n");
193 //printf("e %p s %p t %p v %p\n", isExpression(oarg), isDsymbol(oarg), isType(oarg), isTuple(oarg));
194 if (auto ea = isExpression(oarg))
196 // Try to convert Expression to symbol
197 if (auto ve = ea.isVarExp())
198 return ve.var;
199 else if (auto fe = ea.isFuncExp())
200 return fe.td ? fe.td : fe.fd;
201 else if (auto te = ea.isTemplateExp())
202 return te.td;
203 else if (auto te = ea.isScopeExp())
204 return te.sds;
205 else
206 return null;
208 else
210 // Try to convert Type to symbol
211 if (auto ta = isType(oarg))
212 return ta.toDsymbol(null);
213 else
214 return isDsymbol(oarg); // if already a symbol
219 private Expression getValue(ref Dsymbol s)
221 if (s)
223 if (VarDeclaration v = s.isVarDeclaration())
225 if (v.storage_class & STC.manifest)
226 return v.getConstInitializer();
229 return null;
232 /***********************
233 * Try to get value from manifest constant
235 private Expression getValue(Expression e)
237 if (!e)
238 return null;
239 if (auto ve = e.isVarExp())
241 if (auto v = ve.var.isVarDeclaration())
243 if (v.storage_class & STC.manifest)
245 e = v.getConstInitializer();
249 return e;
252 private Expression getExpression(RootObject o)
254 auto s = isDsymbol(o);
255 return s ? .getValue(s) : .getValue(isExpression(o));
258 /******************************
259 * If o1 matches o2, return true.
260 * Else, return false.
262 private bool match(RootObject o1, RootObject o2)
264 enum log = false;
266 static if (log)
268 printf("match() o1 = %p %s (%d), o2 = %p %s (%d)\n",
269 o1, o1.toChars(), o1.dyncast(), o2, o2.toChars(), o2.dyncast());
272 /* A proper implementation of the various equals() overrides
273 * should make it possible to just do o1.equals(o2), but
274 * we'll do that another day.
276 /* Manifest constants should be compared by their values,
277 * at least in template arguments.
280 if (auto t1 = isType(o1))
282 auto t2 = isType(o2);
283 if (!t2)
284 goto Lnomatch;
286 static if (log)
288 printf("\tt1 = %s\n", t1.toChars());
289 printf("\tt2 = %s\n", t2.toChars());
291 if (!t1.equals(t2))
292 goto Lnomatch;
294 goto Lmatch;
296 if (auto e1 = getExpression(o1))
298 auto e2 = getExpression(o2);
299 if (!e2)
300 goto Lnomatch;
302 static if (log)
304 printf("\te1 = %s '%s' %s\n", e1.type ? e1.type.toChars() : "null", EXPtoString(e1.op).ptr, e1.toChars());
305 printf("\te2 = %s '%s' %s\n", e2.type ? e2.type.toChars() : "null", EXPtoString(e2.op).ptr, e2.toChars());
308 // two expressions can be equal although they do not have the same
309 // type; that happens when they have the same value. So check type
310 // as well as expression equality to ensure templates are properly
311 // matched.
312 if (!(e1.type && e2.type && e1.type.equals(e2.type)) || !e1.equals(e2))
313 goto Lnomatch;
315 goto Lmatch;
317 if (auto s1 = isDsymbol(o1))
319 auto s2 = isDsymbol(o2);
320 if (!s2)
321 goto Lnomatch;
323 static if (log)
325 printf("\ts1 = %s \n", s1.kind(), s1.toChars());
326 printf("\ts2 = %s \n", s2.kind(), s2.toChars());
328 if (!s1.equals(s2))
329 goto Lnomatch;
330 if (s1.parent != s2.parent && !s1.isFuncDeclaration() && !s2.isFuncDeclaration())
331 goto Lnomatch;
333 goto Lmatch;
335 if (auto u1 = isTuple(o1))
337 auto u2 = isTuple(o2);
338 if (!u2)
339 goto Lnomatch;
341 static if (log)
343 printf("\tu1 = %s\n", u1.toChars());
344 printf("\tu2 = %s\n", u2.toChars());
346 if (!arrayObjectMatch(&u1.objects, &u2.objects))
347 goto Lnomatch;
349 goto Lmatch;
351 Lmatch:
352 static if (log)
353 printf("\t. match\n");
354 return true;
356 Lnomatch:
357 static if (log)
358 printf("\t. nomatch\n");
359 return false;
362 /************************************
363 * Match an array of them.
365 private bool arrayObjectMatch(Objects* oa1, Objects* oa2)
367 if (oa1 == oa2)
368 return true;
369 if (oa1.length != oa2.length)
370 return false;
371 immutable oa1dim = oa1.length;
372 auto oa1d = (*oa1)[].ptr;
373 auto oa2d = (*oa2)[].ptr;
374 foreach (j; 0 .. oa1dim)
376 RootObject o1 = oa1d[j];
377 RootObject o2 = oa2d[j];
378 if (!match(o1, o2))
380 return false;
383 return true;
386 /************************************
387 * Return hash of Objects.
389 private size_t arrayObjectHash(Objects* oa1)
391 import dmd.root.hash : mixHash;
393 size_t hash = 0;
394 foreach (o1; *oa1)
396 /* Must follow the logic of match()
398 if (auto t1 = isType(o1))
399 hash = mixHash(hash, cast(size_t)t1.deco);
400 else if (auto e1 = getExpression(o1))
401 hash = mixHash(hash, expressionHash(e1));
402 else if (auto s1 = isDsymbol(o1))
404 auto fa1 = s1.isFuncAliasDeclaration();
405 if (fa1)
406 s1 = fa1.toAliasFunc();
407 hash = mixHash(hash, mixHash(cast(size_t)cast(void*)s1.getIdent(), cast(size_t)cast(void*)s1.parent));
409 else if (auto u1 = isTuple(o1))
410 hash = mixHash(hash, arrayObjectHash(&u1.objects));
412 return hash;
416 /************************************
417 * Computes hash of expression.
418 * Handles all Expression classes and MUST match their equals method,
419 * i.e. e1.equals(e2) implies expressionHash(e1) == expressionHash(e2).
421 private size_t expressionHash(Expression e)
423 import dmd.root.ctfloat : CTFloat;
424 import dmd.root.hash : calcHash, mixHash;
426 switch (e.op)
428 case EXP.int64:
429 return cast(size_t) e.isIntegerExp().getInteger();
431 case EXP.float64:
432 return CTFloat.hash(e.isRealExp().value);
434 case EXP.complex80:
435 auto ce = e.isComplexExp();
436 return mixHash(CTFloat.hash(ce.toReal), CTFloat.hash(ce.toImaginary));
438 case EXP.identifier:
439 return cast(size_t)cast(void*) e.isIdentifierExp().ident;
441 case EXP.null_:
442 return cast(size_t)cast(void*) e.isNullExp().type;
444 case EXP.string_:
445 return calcHash(e.isStringExp.peekData());
447 case EXP.tuple:
449 auto te = e.isTupleExp();
450 size_t hash = 0;
451 hash += te.e0 ? expressionHash(te.e0) : 0;
452 foreach (elem; *te.exps)
453 hash = mixHash(hash, expressionHash(elem));
454 return hash;
457 case EXP.arrayLiteral:
459 auto ae = e.isArrayLiteralExp();
460 size_t hash;
461 foreach (i; 0 .. ae.elements.length)
462 hash = mixHash(hash, expressionHash(ae[i]));
463 return hash;
466 case EXP.assocArrayLiteral:
468 auto ae = e.isAssocArrayLiteralExp();
469 size_t hash;
470 foreach (i; 0 .. ae.keys.length)
471 // reduction needs associative op as keys are unsorted (use XOR)
472 hash ^= mixHash(expressionHash((*ae.keys)[i]), expressionHash((*ae.values)[i]));
473 return hash;
476 case EXP.structLiteral:
478 auto se = e.isStructLiteralExp();
479 size_t hash;
480 foreach (elem; *se.elements)
481 hash = mixHash(hash, elem ? expressionHash(elem) : 0);
482 return hash;
485 case EXP.variable:
486 return cast(size_t)cast(void*) e.isVarExp().var;
488 case EXP.function_:
489 return cast(size_t)cast(void*) e.isFuncExp().fd;
491 default:
492 // no custom equals for this expression
493 assert((&e.equals).funcptr is &RootObject.equals);
494 // equals based on identity
495 return cast(size_t)cast(void*) e;
499 RootObject objectSyntaxCopy(RootObject o)
501 if (!o)
502 return null;
503 if (Type t = isType(o))
504 return t.syntaxCopy();
505 if (Expression e = isExpression(o))
506 return e.syntaxCopy();
507 return o;
510 extern (C++) final class Tuple : RootObject
512 Objects objects;
514 extern (D) this() {}
517 Params:
518 numObjects = The initial number of objects.
520 extern (D) this(size_t numObjects)
522 objects.setDim(numObjects);
525 // kludge for template.isType()
526 override DYNCAST dyncast() const
528 return DYNCAST.tuple;
531 override const(char)* toChars() const
533 return objects.toChars();
537 struct TemplatePrevious
539 TemplatePrevious* prev;
540 Scope* sc;
541 Objects* dedargs;
544 /***********************************************************
545 * [mixin] template Identifier (parameters) [Constraint]
546 * https://dlang.org/spec/template.html
547 * https://dlang.org/spec/template-mixin.html
549 extern (C++) final class TemplateDeclaration : ScopeDsymbol
551 import dmd.root.array : Array;
553 TemplateParameters* parameters; // array of TemplateParameter's
554 TemplateParameters* origParameters; // originals for Ddoc
556 Expression constraint;
558 // Hash table to look up TemplateInstance's of this TemplateDeclaration
559 TemplateInstance[TemplateInstanceBox] instances;
561 TemplateDeclaration overnext; // next overloaded TemplateDeclaration
562 TemplateDeclaration overroot; // first in overnext list
563 FuncDeclaration funcroot; // first function in unified overload list
565 Dsymbol onemember; // if !=null then one member of this template
567 bool literal; // this template declaration is a literal
568 bool ismixin; // this is a mixin template declaration
569 bool isstatic; // this is static template declaration
570 bool isTrivialAliasSeq; /// matches pattern `template AliasSeq(T...) { alias AliasSeq = T; }`
571 bool isTrivialAlias; /// matches pattern `template Alias(T) { alias Alias = qualifiers(T); }`
572 bool deprecated_; /// this template declaration is deprecated
573 Visibility visibility;
575 // threaded list of previous instantiation attempts on stack
576 TemplatePrevious* previous;
578 private Expression lastConstraint; /// the constraint after the last failed evaluation
579 private Array!Expression lastConstraintNegs; /// its negative parts
580 private Objects* lastConstraintTiargs; /// template instance arguments for `lastConstraint`
582 extern (D) this(const ref Loc loc, Identifier ident, TemplateParameters* parameters, Expression constraint, Dsymbols* decldefs, bool ismixin = false, bool literal = false)
584 super(loc, ident);
585 static if (LOG)
587 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, ident.toChars());
589 version (none)
591 if (parameters)
592 for (int i = 0; i < parameters.length; i++)
594 TemplateParameter tp = (*parameters)[i];
595 //printf("\tparameter[%d] = %p\n", i, tp);
596 TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
597 if (ttp)
599 printf("\tparameter[%d] = %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
603 this.parameters = parameters;
604 this.origParameters = parameters;
605 this.constraint = constraint;
606 this.members = decldefs;
607 this.literal = literal;
608 this.ismixin = ismixin;
609 this.isstatic = true;
610 this.visibility = Visibility(Visibility.Kind.undefined);
612 // Compute in advance for Ddoc's use
613 // https://issues.dlang.org/show_bug.cgi?id=11153: ident could be NULL if parsing fails.
614 if (!members || !ident)
615 return;
617 Dsymbol s;
618 if (!Dsymbol.oneMembers(members, &s, ident) || !s)
619 return;
621 onemember = s;
622 s.parent = this;
624 /* Set isTrivialAliasSeq if this fits the pattern:
625 * template AliasSeq(T...) { alias AliasSeq = T; }
626 * or set isTrivialAlias if this fits the pattern:
627 * template Alias(T) { alias Alias = qualifiers(T); }
629 if (!(parameters && parameters.length == 1))
630 return;
632 auto ad = s.isAliasDeclaration();
633 if (!ad || !ad.type)
634 return;
636 auto ti = ad.type.isTypeIdentifier();
638 if (!ti || ti.idents.length != 0)
639 return;
641 if (auto ttp = (*parameters)[0].isTemplateTupleParameter())
643 if (ti.ident is ttp.ident &&
644 ti.mod == 0)
646 //printf("found isTrivialAliasSeq %s %s\n", s.toChars(), ad.type.toChars());
647 isTrivialAliasSeq = true;
650 else if (auto ttp = (*parameters)[0].isTemplateTypeParameter())
652 if (ti.ident is ttp.ident)
654 //printf("found isTrivialAlias %s %s\n", s.toChars(), ad.type.toChars());
655 isTrivialAlias = true;
660 override TemplateDeclaration syntaxCopy(Dsymbol)
662 //printf("TemplateDeclaration.syntaxCopy()\n");
663 TemplateParameters* p = null;
664 if (parameters)
666 p = new TemplateParameters(parameters.length);
667 foreach (i, ref param; *p)
668 param = (*parameters)[i].syntaxCopy();
670 return new TemplateDeclaration(loc, ident, p, constraint ? constraint.syntaxCopy() : null, Dsymbol.arraySyntaxCopy(members), ismixin, literal);
673 /**********************************
674 * Overload existing TemplateDeclaration 'this' with the new one 's'.
675 * Return true if successful; i.e. no conflict.
677 override bool overloadInsert(Dsymbol s)
679 static if (LOG)
681 printf("TemplateDeclaration.overloadInsert('%s')\n", s.toChars());
683 FuncDeclaration fd = s.isFuncDeclaration();
684 if (fd)
686 if (funcroot)
687 return funcroot.overloadInsert(fd);
688 funcroot = fd;
689 return funcroot.overloadInsert(this);
692 // https://issues.dlang.org/show_bug.cgi?id=15795
693 // if candidate is an alias and its sema is not run then
694 // insertion can fail because the thing it alias is not known
695 if (AliasDeclaration ad = s.isAliasDeclaration())
697 if (s._scope)
698 aliasSemantic(ad, s._scope);
699 if (ad.aliassym && ad.aliassym is this)
700 return false;
702 TemplateDeclaration td = s.toAlias().isTemplateDeclaration();
703 if (!td)
704 return false;
706 TemplateDeclaration pthis = this;
707 TemplateDeclaration* ptd;
708 for (ptd = &pthis; *ptd; ptd = &(*ptd).overnext)
712 td.overroot = this;
713 *ptd = td;
714 static if (LOG)
716 printf("\ttrue: no conflict\n");
718 return true;
721 override bool hasStaticCtorOrDtor()
723 return false; // don't scan uninstantiated templates
726 override const(char)* kind() const
728 return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template";
731 override const(char)* toChars() const
733 return toCharsMaybeConstraints(true);
736 /****************************
737 * Similar to `toChars`, but does not print the template constraints
739 const(char)* toCharsNoConstraints() const
741 return toCharsMaybeConstraints(false);
744 const(char)* toCharsMaybeConstraints(bool includeConstraints) const
746 OutBuffer buf;
747 HdrGenState hgs;
749 buf.writestring(ident == Id.ctor ? "this" : ident.toString());
750 buf.writeByte('(');
751 foreach (i, const tp; *parameters)
753 if (i)
754 buf.writestring(", ");
755 toCBuffer(tp, buf, hgs);
757 buf.writeByte(')');
759 if (onemember)
761 const FuncDeclaration fd = onemember.isFuncDeclaration();
762 if (fd && fd.type)
764 TypeFunction tf = cast(TypeFunction)fd.type;
765 buf.writestring(parametersTypeToChars(tf.parameterList));
766 if (tf.mod)
768 buf.writeByte(' ');
769 buf.MODtoBuffer(tf.mod);
774 if (includeConstraints &&
775 constraint)
777 buf.writestring(" if (");
778 toCBuffer(constraint, buf, hgs);
779 buf.writeByte(')');
782 return buf.extractChars();
785 override Visibility visible() pure nothrow @nogc @safe
787 return visibility;
790 /****************************
791 * Check to see if constraint is satisfied.
793 extern (D) bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
795 /* Detect recursive attempts to instantiate this template declaration,
796 * https://issues.dlang.org/show_bug.cgi?id=4072
797 * void foo(T)(T x) if (is(typeof(foo(x)))) { }
798 * static assert(!is(typeof(foo(7))));
799 * Recursive attempts are regarded as a constraint failure.
801 /* There's a chicken-and-egg problem here. We don't know yet if this template
802 * instantiation will be a local one (enclosing is set), and we won't know until
803 * after selecting the correct template. Thus, function we're nesting inside
804 * is not on the sc scope chain, and this can cause errors in FuncDeclaration.getLevel().
805 * Workaround the problem by setting a flag to relax the checking on frame errors.
808 for (TemplatePrevious* p = previous; p; p = p.prev)
810 if (!arrayObjectMatch(p.dedargs, dedargs))
811 continue;
812 //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
813 /* It must be a subscope of p.sc, other scope chains are not recursive
814 * instantiations.
815 * the chain of enclosing scopes is broken by paramscope (its enclosing
816 * scope is _scope, but paramscope.callsc is the instantiating scope). So
817 * it's good enough to check the chain of callsc
819 for (Scope* scx = paramscope.callsc; scx; scx = scx.callsc)
821 // The first scx might be identical for nested eponymeous templates, e.g.
822 // template foo() { void foo()() {...} }
823 if (scx == p.sc && scx !is paramscope.callsc)
824 return false;
826 /* BUG: should also check for ref param differences
830 TemplatePrevious pr;
831 pr.prev = previous;
832 pr.sc = paramscope.callsc;
833 pr.dedargs = dedargs;
834 previous = &pr; // add this to threaded list
836 Scope* scx = paramscope.push(ti);
837 scx.parent = ti;
838 scx.tinst = null;
839 scx.minst = null;
840 // Set SCOPE.constraint before declaring function parameters for the static condition
841 // (previously, this was immediately before calling evalStaticCondition), so the
842 // semantic pass knows not to issue deprecation warnings for these throw-away decls.
843 // https://issues.dlang.org/show_bug.cgi?id=21831
844 scx.flags |= SCOPE.constraint;
846 assert(!ti.symtab);
847 if (fd)
849 /* Declare all the function parameters as variables and add them to the scope
850 * Making parameters is similar to FuncDeclaration.semantic3
852 auto tf = fd.type.isTypeFunction();
854 scx.parent = fd;
856 Parameters* fparameters = tf.parameterList.parameters;
857 const nfparams = tf.parameterList.length;
858 foreach (i, fparam; tf.parameterList)
860 fparam.storageClass &= (STC.IOR | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor);
861 fparam.storageClass |= STC.parameter;
862 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nfparams)
864 fparam.storageClass |= STC.variadic;
865 /* Don't need to set STC.scope_ because this will only
866 * be evaluated at compile time
870 foreach (fparam; *fparameters)
872 if (!fparam.ident)
873 continue;
874 // don't add it, if it has no name
875 auto v = new VarDeclaration(fparam.loc, fparam.type, fparam.ident, null);
876 fparam.storageClass |= STC.parameter;
877 v.storage_class = fparam.storageClass;
878 v.dsymbolSemantic(scx);
879 if (!ti.symtab)
880 ti.symtab = new DsymbolTable();
881 if (!scx.insert(v))
882 .error(loc, "%s `%s` parameter `%s.%s` is already defined", kind, toPrettyChars, toChars(), v.toChars());
883 else
884 v.parent = fd;
886 if (isstatic)
887 fd.storage_class |= STC.static_;
888 fd.declareThis(scx);
891 lastConstraint = constraint.syntaxCopy();
892 lastConstraintTiargs = ti.tiargs;
893 lastConstraintNegs.setDim(0);
895 import dmd.staticcond;
897 assert(ti.inst is null);
898 ti.inst = ti; // temporary instantiation to enable genIdent()
899 bool errors;
900 const bool result = evalStaticCondition(scx, constraint, lastConstraint, errors, &lastConstraintNegs);
901 if (result || errors)
903 lastConstraint = null;
904 lastConstraintTiargs = null;
905 lastConstraintNegs.setDim(0);
907 ti.inst = null;
908 ti.symtab = null;
909 scx = scx.pop();
910 previous = pr.prev; // unlink from threaded list
911 if (errors)
912 return false;
913 return result;
916 /****************************
917 * Destructively get the error message from the last constraint evaluation
918 * Params:
919 * tip = tip to show after printing all overloads
921 const(char)* getConstraintEvalError(ref const(char)* tip)
923 import dmd.staticcond;
925 // there will be a full tree view in verbose mode, and more compact list in the usual
926 const full = global.params.v.verbose;
927 uint count;
928 const msg = visualizeStaticCondition(constraint, lastConstraint, lastConstraintNegs[], full, count);
929 scope (exit)
931 lastConstraint = null;
932 lastConstraintTiargs = null;
933 lastConstraintNegs.setDim(0);
935 if (!msg)
936 return null;
938 OutBuffer buf;
940 assert(parameters && lastConstraintTiargs);
941 if (parameters.length > 0)
943 formatParamsWithTiargs(*lastConstraintTiargs, buf);
944 buf.writenl();
946 if (!full)
948 // choosing singular/plural
949 const s = (count == 1) ?
950 " must satisfy the following constraint:" :
951 " must satisfy one of the following constraints:";
952 buf.writestring(s);
953 buf.writenl();
954 // the constraints
955 buf.writeByte('`');
956 buf.writestring(msg);
957 buf.writeByte('`');
959 else
961 buf.writestring(" whose parameters have the following constraints:");
962 buf.writenl();
963 const sep = " `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`";
964 buf.writestring(sep);
965 buf.writenl();
966 // the constraints
967 buf.writeByte('`');
968 buf.writestring(msg);
969 buf.writeByte('`');
970 buf.writestring(sep);
971 tip = "not satisfied constraints are marked with `>`";
973 return buf.extractChars();
976 private void formatParamsWithTiargs(ref Objects tiargs, ref OutBuffer buf)
978 buf.writestring(" with `");
980 // write usual arguments line-by-line
981 // skips trailing default ones - they are not present in `tiargs`
982 const bool variadic = isVariadic() !is null;
983 const end = cast(int)parameters.length - (variadic ? 1 : 0);
984 uint i;
985 for (; i < tiargs.length && i < end; i++)
987 if (i > 0)
989 buf.writeByte(',');
990 buf.writenl();
991 buf.writestring(" ");
993 write(buf, (*parameters)[i]);
994 buf.writestring(" = ");
995 write(buf, tiargs[i]);
997 // write remaining variadic arguments on the last line
998 if (variadic)
1000 if (i > 0)
1002 buf.writeByte(',');
1003 buf.writenl();
1004 buf.writestring(" ");
1006 write(buf, (*parameters)[end]);
1007 buf.writestring(" = ");
1008 buf.writeByte('(');
1009 if (cast(int)tiargs.length - end > 0)
1011 write(buf, tiargs[end]);
1012 foreach (j; parameters.length .. tiargs.length)
1014 buf.writestring(", ");
1015 write(buf, tiargs[j]);
1018 buf.writeByte(')');
1020 buf.writeByte('`');
1023 /******************************
1024 * Create a scope for the parameters of the TemplateInstance
1025 * `ti` in the parent scope sc from the ScopeDsymbol paramsym.
1027 * If paramsym is null a new ScopeDsymbol is used in place of
1028 * paramsym.
1029 * Params:
1030 * ti = the TemplateInstance whose parameters to generate the scope for.
1031 * sc = the parent scope of ti
1032 * Returns:
1033 * a scope for the parameters of ti
1035 Scope* scopeForTemplateParameters(TemplateInstance ti, Scope* sc)
1037 ScopeDsymbol paramsym = new ScopeDsymbol();
1038 paramsym.parent = _scope.parent;
1039 Scope* paramscope = _scope.push(paramsym);
1040 paramscope.tinst = ti;
1041 paramscope.minst = sc.minst;
1042 paramscope.callsc = sc;
1043 paramscope.stc = 0;
1044 return paramscope;
1047 /***************************************
1048 * Given that ti is an instance of this TemplateDeclaration,
1049 * deduce the types of the parameters to this, and store
1050 * those deduced types in dedtypes[].
1051 * Input:
1052 * flag 1: don't do semantic() because of dummy types
1053 * 2: don't change types in matchArg()
1054 * Output:
1055 * dedtypes deduced arguments
1056 * Return match level.
1058 extern (D) MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, ArgumentList argumentList, int flag)
1060 enum LOGM = 0;
1061 static if (LOGM)
1063 printf("\n+TemplateDeclaration.matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti.toChars(), flag);
1065 version (none)
1067 printf("dedtypes.length = %d, parameters.length = %d\n", dedtypes.length, parameters.length);
1068 if (ti.tiargs.length)
1069 printf("ti.tiargs.length = %d, [0] = %p\n", ti.tiargs.length, (*ti.tiargs)[0]);
1071 MATCH nomatch()
1073 static if (LOGM)
1075 printf(" no match\n");
1077 return MATCH.nomatch;
1079 MATCH m;
1080 size_t dedtypes_dim = dedtypes.length;
1082 dedtypes.zero();
1084 if (errors)
1085 return MATCH.nomatch;
1087 size_t parameters_dim = parameters.length;
1088 int variadic = isVariadic() !is null;
1090 // If more arguments than parameters, no match
1091 if (ti.tiargs.length > parameters_dim && !variadic)
1093 static if (LOGM)
1095 printf(" no match: more arguments than parameters\n");
1097 return MATCH.nomatch;
1100 assert(dedtypes_dim == parameters_dim);
1101 assert(dedtypes_dim >= ti.tiargs.length || variadic);
1103 assert(_scope);
1105 // Set up scope for template parameters
1106 Scope* paramscope = scopeForTemplateParameters(ti,sc);
1108 // Attempt type deduction
1109 m = MATCH.exact;
1110 for (size_t i = 0; i < dedtypes_dim; i++)
1112 MATCH m2;
1113 TemplateParameter tp = (*parameters)[i];
1114 Declaration sparam;
1116 //printf("\targument [%d]\n", i);
1117 static if (LOGM)
1119 //printf("\targument [%d] is %s\n", i, oarg ? oarg.toChars() : "null");
1120 TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
1121 if (ttp)
1122 printf("\tparameter[%d] is %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
1125 m2 = tp.matchArg(ti.loc, paramscope, ti.tiargs, i, parameters, dedtypes, &sparam);
1126 //printf("\tm2 = %d\n", m2);
1127 if (m2 == MATCH.nomatch)
1129 version (none)
1131 printf("\tmatchArg() for parameter %i failed\n", i);
1133 return nomatch();
1136 if (m2 < m)
1137 m = m2;
1139 if (!flag)
1140 sparam.dsymbolSemantic(paramscope);
1141 if (!paramscope.insert(sparam)) // TODO: This check can make more early
1143 // in TemplateDeclaration.semantic, and
1144 // then we don't need to make sparam if flags == 0
1145 return nomatch();
1149 if (!flag)
1151 /* Any parameter left without a type gets the type of
1152 * its corresponding arg
1154 foreach (i, ref dedtype; *dedtypes)
1156 if (!dedtype)
1158 assert(i < ti.tiargs.length);
1159 dedtype = cast(Type)(*ti.tiargs)[i];
1164 if (m > MATCH.nomatch && constraint && !flag)
1166 if (ti.hasNestedArgs(ti.tiargs, this.isstatic)) // TODO: should gag error
1167 ti.parent = ti.enclosing;
1168 else
1169 ti.parent = this.parent;
1171 // Similar to doHeaderInstantiation
1172 FuncDeclaration fd = onemember ? onemember.isFuncDeclaration() : null;
1173 if (fd)
1175 TypeFunction tf = fd.type.isTypeFunction().syntaxCopy();
1176 if (argumentList.hasNames)
1177 return nomatch();
1178 Expressions* fargs = argumentList.arguments;
1179 // TODO: Expressions* fargs = tf.resolveNamedArgs(argumentList, null);
1180 // if (!fargs)
1181 // return nomatch();
1183 fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf);
1184 fd.parent = ti;
1185 fd.inferRetType = true;
1187 // Shouldn't run semantic on default arguments and return type.
1188 foreach (ref param; *tf.parameterList.parameters)
1189 param.defaultArg = null;
1191 tf.next = null;
1192 tf.incomplete = true;
1194 // Resolve parameter types and 'auto ref's.
1195 tf.fargs = fargs;
1196 uint olderrors = global.startGagging();
1197 fd.type = tf.typeSemantic(loc, paramscope);
1198 global.endGagging(olderrors);
1199 if (fd.type.ty != Tfunction)
1200 return nomatch();
1201 fd.originalType = fd.type; // for mangling
1204 // TODO: dedtypes => ti.tiargs ?
1205 if (!evaluateConstraint(ti, sc, paramscope, dedtypes, fd))
1206 return nomatch();
1209 static if (LOGM)
1211 // Print out the results
1212 printf("--------------------------\n");
1213 printf("template %s\n", toChars());
1214 printf("instance %s\n", ti.toChars());
1215 if (m > MATCH.nomatch)
1217 for (size_t i = 0; i < dedtypes_dim; i++)
1219 TemplateParameter tp = (*parameters)[i];
1220 RootObject oarg;
1221 printf(" [%d]", i);
1222 if (i < ti.tiargs.length)
1223 oarg = (*ti.tiargs)[i];
1224 else
1225 oarg = null;
1226 tp.print(oarg, (*dedtypes)[i]);
1229 else
1230 return nomatch();
1232 static if (LOGM)
1234 printf(" match = %d\n", m);
1237 paramscope.pop();
1238 static if (LOGM)
1240 printf("-TemplateDeclaration.matchWithInstance(this = %s, ti = %s) = %d\n", toChars(), ti.toChars(), m);
1242 return m;
1245 /********************************************
1246 * Determine partial specialization order of 'this' vs td2.
1247 * Returns:
1248 * match this is at least as specialized as td2
1249 * 0 td2 is more specialized than this
1251 extern (D) MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, ArgumentList argumentList)
1253 enum LOG_LEASTAS = 0;
1254 static if (LOG_LEASTAS)
1256 printf("%s.leastAsSpecialized(%s)\n", toChars(), td2.toChars());
1259 /* This works by taking the template parameters to this template
1260 * declaration and feeding them to td2 as if it were a template
1261 * instance.
1262 * If it works, then this template is at least as specialized
1263 * as td2.
1266 // Set type arguments to dummy template instance to be types
1267 // generated from the parameters to this template declaration
1268 auto tiargs = new Objects();
1269 tiargs.reserve(parameters.length);
1270 foreach (tp; *parameters)
1272 if (tp.dependent)
1273 break;
1274 RootObject p = tp.dummyArg();
1275 if (!p) //TemplateTupleParameter
1276 break;
1278 tiargs.push(p);
1280 scope TemplateInstance ti = new TemplateInstance(Loc.initial, ident, tiargs); // create dummy template instance
1282 // Temporary Array to hold deduced types
1283 Objects dedtypes = Objects(td2.parameters.length);
1285 // Attempt a type deduction
1286 MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, argumentList, 1);
1287 if (m > MATCH.nomatch)
1289 /* A non-variadic template is more specialized than a
1290 * variadic one.
1292 TemplateTupleParameter tp = isVariadic();
1293 if (tp && !tp.dependent && !td2.isVariadic())
1294 goto L1;
1296 static if (LOG_LEASTAS)
1298 printf(" matches %d, so is least as specialized\n", m);
1300 return m;
1303 static if (LOG_LEASTAS)
1305 printf(" doesn't match, so is not as specialized\n");
1307 return MATCH.nomatch;
1310 /*************************************************
1311 * Match function arguments against a specific template function.
1313 * Params:
1314 * ti = template instance. `ti.tdtypes` will be set to Expression/Type deduced template arguments
1315 * sc = instantiation scope
1316 * fd = Partially instantiated function declaration, which is set to an instantiated function declaration
1317 * tthis = 'this' argument if !NULL
1318 * argumentList = arguments to function
1320 * Returns:
1321 * match pair of initial and inferred template arguments
1323 extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, ArgumentList argumentList)
1325 version (none)
1327 printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars());
1328 for (size_t i = 0; i < (fargs ? fargs.length : 0); i++)
1330 Expression e = (*fargs)[i];
1331 printf("\tfarg[%d] is %s, type is %s\n", cast(int) i, e.toChars(), e.type.toChars());
1333 printf("fd = %s\n", fd.toChars());
1334 printf("fd.type = %s\n", fd.type.toChars());
1335 if (tthis)
1336 printf("tthis = %s\n", tthis.toChars());
1339 assert(_scope);
1341 auto dedargs = new Objects(parameters.length);
1342 dedargs.zero();
1344 Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
1345 dedtypes.setDim(parameters.length);
1346 dedtypes.zero();
1348 if (errors || fd.errors)
1349 return MATCHpair(MATCH.nomatch, MATCH.nomatch);
1351 // Set up scope for parameters
1352 Scope* paramscope = scopeForTemplateParameters(ti,sc);
1354 MATCHpair nomatch()
1356 paramscope.pop();
1357 //printf("\tnomatch\n");
1358 return MATCHpair(MATCH.nomatch, MATCH.nomatch);
1361 MATCHpair matcherror()
1363 // todo: for the future improvement
1364 paramscope.pop();
1365 //printf("\terror\n");
1366 return MATCHpair(MATCH.nomatch, MATCH.nomatch);
1368 // Mark the parameter scope as deprecated if the templated
1369 // function is deprecated (since paramscope.enclosing is the
1370 // calling scope already)
1371 paramscope.stc |= fd.storage_class & STC.deprecated_;
1373 TemplateTupleParameter tp = isVariadic();
1374 Tuple declaredTuple = null;
1376 version (none)
1378 for (size_t i = 0; i < dedargs.length; i++)
1380 printf("\tdedarg[%d] = ", i);
1381 RootObject oarg = (*dedargs)[i];
1382 if (oarg)
1383 printf("%s", oarg.toChars());
1384 printf("\n");
1388 size_t ntargs = 0; // array size of tiargs
1389 size_t inferStart = 0; // index of first parameter to infer
1390 const Loc instLoc = ti.loc;
1391 MATCH matchTiargs = MATCH.exact;
1393 if (auto tiargs = ti.tiargs)
1395 // Set initial template arguments
1396 ntargs = tiargs.length;
1397 size_t n = parameters.length;
1398 if (tp)
1399 n--;
1400 if (ntargs > n)
1402 if (!tp)
1403 return nomatch();
1405 /* The extra initial template arguments
1406 * now form the tuple argument.
1408 auto t = new Tuple(ntargs - n);
1409 assert(parameters.length);
1410 (*dedargs)[parameters.length - 1] = t;
1412 for (size_t i = 0; i < t.objects.length; i++)
1414 t.objects[i] = (*tiargs)[n + i];
1416 declareParameter(paramscope, tp, t);
1417 declaredTuple = t;
1419 else
1420 n = ntargs;
1422 memcpy(dedargs.tdata(), tiargs.tdata(), n * (*dedargs.tdata()).sizeof);
1424 for (size_t i = 0; i < n; i++)
1426 assert(i < parameters.length);
1427 Declaration sparam = null;
1428 MATCH m = (*parameters)[i].matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, &sparam);
1429 //printf("\tdeduceType m = %d\n", m);
1430 if (m == MATCH.nomatch)
1431 return nomatch();
1432 if (m < matchTiargs)
1433 matchTiargs = m;
1435 sparam.dsymbolSemantic(paramscope);
1436 if (!paramscope.insert(sparam))
1437 return nomatch();
1439 if (n < parameters.length && !declaredTuple)
1441 inferStart = n;
1443 else
1444 inferStart = parameters.length;
1445 //printf("tiargs matchTiargs = %d\n", matchTiargs);
1447 version (none)
1449 for (size_t i = 0; i < dedargs.length; i++)
1451 printf("\tdedarg[%d] = ", i);
1452 RootObject oarg = (*dedargs)[i];
1453 if (oarg)
1454 printf("%s", oarg.toChars());
1455 printf("\n");
1459 ParameterList fparameters = fd.getParameterList(); // function parameter list
1460 const nfparams = fparameters.length; // number of function parameters
1461 const nfargs = argumentList.length; // number of function arguments
1462 if (argumentList.hasNames)
1463 return matcherror(); // TODO: resolve named args
1464 Expressions* fargs = argumentList.arguments; // TODO: resolve named args
1466 /* Check for match of function arguments with variadic template
1467 * parameter, such as:
1469 * void foo(T, A...)(T t, A a);
1470 * void main() { foo(1,2,3); }
1472 size_t fptupindex = IDX_NOTFOUND;
1473 if (tp) // if variadic
1475 // TemplateTupleParameter always makes most lesser matching.
1476 matchTiargs = MATCH.convert;
1478 if (nfparams == 0 && nfargs != 0) // if no function parameters
1480 if (!declaredTuple)
1482 auto t = new Tuple();
1483 //printf("t = %p\n", t);
1484 (*dedargs)[parameters.length - 1] = t;
1485 declareParameter(paramscope, tp, t);
1486 declaredTuple = t;
1489 else
1491 /* Figure out which of the function parameters matches
1492 * the tuple template parameter. Do this by matching
1493 * type identifiers.
1494 * Set the index of this function parameter to fptupindex.
1496 for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
1498 auto fparam = (*fparameters.parameters)[fptupindex]; // fparameters[fptupindex] ?
1499 if (fparam.type.ty != Tident)
1500 continue;
1501 TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
1502 if (!tp.ident.equals(tid.ident) || tid.idents.length)
1503 continue;
1505 if (fparameters.varargs != VarArg.none) // variadic function doesn't
1506 return nomatch(); // go with variadic template
1508 goto L1;
1510 fptupindex = IDX_NOTFOUND;
1515 MATCH match = MATCH.exact;
1516 if (toParent().isModule())
1517 tthis = null;
1518 if (tthis)
1520 bool hasttp = false;
1522 // Match 'tthis' to any TemplateThisParameter's
1523 foreach (param; *parameters)
1525 if (auto ttp = param.isTemplateThisParameter())
1527 hasttp = true;
1529 Type t = new TypeIdentifier(Loc.initial, ttp.ident);
1530 MATCH m = deduceType(tthis, paramscope, t, parameters, dedtypes);
1531 if (m == MATCH.nomatch)
1532 return nomatch();
1533 if (m < match)
1534 match = m; // pick worst match
1538 // Match attributes of tthis against attributes of fd
1539 if (fd.type && !fd.isCtorDeclaration() && !(_scope.stc & STC.static_))
1541 StorageClass stc = _scope.stc | fd.storage_class2;
1542 // Propagate parent storage class, https://issues.dlang.org/show_bug.cgi?id=5504
1543 Dsymbol p = parent;
1544 while (p.isTemplateDeclaration() || p.isTemplateInstance())
1545 p = p.parent;
1546 AggregateDeclaration ad = p.isAggregateDeclaration();
1547 if (ad)
1548 stc |= ad.storage_class;
1550 ubyte mod = fd.type.mod;
1551 if (stc & STC.immutable_)
1552 mod = MODFlags.immutable_;
1553 else
1555 if (stc & (STC.shared_ | STC.synchronized_))
1556 mod |= MODFlags.shared_;
1557 if (stc & STC.const_)
1558 mod |= MODFlags.const_;
1559 if (stc & STC.wild)
1560 mod |= MODFlags.wild;
1563 ubyte thismod = tthis.mod;
1564 if (hasttp)
1565 mod = MODmerge(thismod, mod);
1566 MATCH m = MODmethodConv(thismod, mod);
1567 if (m == MATCH.nomatch)
1568 return nomatch();
1569 if (m < match)
1570 match = m;
1574 // Loop through the function parameters
1576 //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.length : 0);
1577 //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL);
1578 size_t argi = 0;
1579 size_t nfargs2 = nfargs; // nfargs + supplied defaultArgs
1580 uint inoutMatch = 0; // for debugging only
1581 for (size_t parami = 0; parami < nfparams; parami++)
1583 Parameter fparam = fparameters[parami];
1585 // Apply function parameter storage classes to parameter types
1586 Type prmtype = fparam.type.addStorageClass(fparam.storageClass);
1588 Expression farg;
1590 /* See function parameters which wound up
1591 * as part of a template tuple parameter.
1593 if (fptupindex != IDX_NOTFOUND && parami == fptupindex)
1595 assert(prmtype.ty == Tident);
1596 TypeIdentifier tid = cast(TypeIdentifier)prmtype;
1597 if (!declaredTuple)
1599 /* The types of the function arguments
1600 * now form the tuple argument.
1602 declaredTuple = new Tuple();
1603 (*dedargs)[parameters.length - 1] = declaredTuple;
1605 /* Count function parameters with no defaults following a tuple parameter.
1606 * void foo(U, T...)(int y, T, U, double, int bar = 0) {} // rem == 2 (U, double)
1608 size_t rem = 0;
1609 for (size_t j = parami + 1; j < nfparams; j++)
1611 Parameter p = fparameters[j];
1612 if (p.defaultArg)
1614 break;
1616 if (!reliesOnTemplateParameters(p.type, (*parameters)[inferStart .. parameters.length]))
1618 Type pt = p.type.syntaxCopy().typeSemantic(fd.loc, paramscope);
1619 rem += pt.ty == Ttuple ? (cast(TypeTuple)pt).arguments.length : 1;
1621 else
1623 ++rem;
1627 if (nfargs2 - argi < rem)
1628 return nomatch();
1629 declaredTuple.objects.setDim(nfargs2 - argi - rem);
1630 for (size_t i = 0; i < declaredTuple.objects.length; i++)
1632 farg = (*fargs)[argi + i];
1634 // Check invalid arguments to detect errors early.
1635 if (farg.op == EXP.error || farg.type.ty == Terror)
1636 return nomatch();
1638 if (!fparam.isLazy() && farg.type.ty == Tvoid)
1639 return nomatch();
1641 Type tt;
1642 MATCH m;
1643 if (ubyte wm = deduceWildHelper(farg.type, &tt, tid))
1645 inoutMatch |= wm;
1646 m = MATCH.constant;
1648 else
1650 m = deduceTypeHelper(farg.type, &tt, tid);
1652 if (m == MATCH.nomatch)
1653 return nomatch();
1654 if (m < match)
1655 match = m;
1657 /* Remove top const for dynamic array types and pointer types
1659 if ((tt.ty == Tarray || tt.ty == Tpointer) && !tt.isMutable() && (!(fparam.storageClass & STC.ref_) || (fparam.storageClass & STC.auto_) && !farg.isLvalue()))
1661 tt = tt.mutableOf();
1663 declaredTuple.objects[i] = tt;
1665 declareParameter(paramscope, tp, declaredTuple);
1667 else
1669 // https://issues.dlang.org/show_bug.cgi?id=6810
1670 // If declared tuple is not a type tuple,
1671 // it cannot be function parameter types.
1672 for (size_t i = 0; i < declaredTuple.objects.length; i++)
1674 if (!isType(declaredTuple.objects[i]))
1675 return nomatch();
1678 assert(declaredTuple);
1679 argi += declaredTuple.objects.length;
1680 continue;
1683 // If parameter type doesn't depend on inferred template parameters,
1684 // semantic it to get actual type.
1685 if (!reliesOnTemplateParameters(prmtype, (*parameters)[inferStart .. parameters.length]))
1687 // should copy prmtype to avoid affecting semantic result
1688 prmtype = prmtype.syntaxCopy().typeSemantic(fd.loc, paramscope);
1690 if (prmtype.ty == Ttuple)
1692 TypeTuple tt = cast(TypeTuple)prmtype;
1693 size_t tt_dim = tt.arguments.length;
1694 for (size_t j = 0; j < tt_dim; j++, ++argi)
1696 Parameter p = (*tt.arguments)[j];
1697 if (j == tt_dim - 1 && fparameters.varargs == VarArg.typesafe &&
1698 parami + 1 == nfparams && argi < nfargs)
1700 prmtype = p.type;
1701 goto Lvarargs;
1703 if (argi >= nfargs)
1705 if (p.defaultArg)
1706 continue;
1708 // https://issues.dlang.org/show_bug.cgi?id=19888
1709 if (fparam.defaultArg)
1710 break;
1712 return nomatch();
1714 farg = (*fargs)[argi];
1715 if (!farg.implicitConvTo(p.type))
1716 return nomatch();
1718 continue;
1722 if (argi >= nfargs) // if not enough arguments
1724 if (!fparam.defaultArg)
1725 goto Lvarargs;
1727 /* https://issues.dlang.org/show_bug.cgi?id=2803
1728 * Before the starting of type deduction from the function
1729 * default arguments, set the already deduced parameters into paramscope.
1730 * It's necessary to avoid breaking existing acceptable code. Cases:
1732 * 1. Already deduced template parameters can appear in fparam.defaultArg:
1733 * auto foo(A, B)(A a, B b = A.stringof);
1734 * foo(1);
1735 * // at fparam == 'B b = A.string', A is equivalent with the deduced type 'int'
1737 * 2. If prmtype depends on default-specified template parameter, the
1738 * default type should be preferred.
1739 * auto foo(N = size_t, R)(R r, N start = 0)
1740 * foo([1,2,3]);
1741 * // at fparam `N start = 0`, N should be 'size_t' before
1742 * // the deduction result from fparam.defaultArg.
1744 if (argi == nfargs)
1746 foreach (ref dedtype; *dedtypes)
1748 Type at = isType(dedtype);
1749 if (at && at.ty == Tnone)
1751 TypeDeduced xt = cast(TypeDeduced)at;
1752 dedtype = xt.tded; // 'unbox'
1755 for (size_t i = ntargs; i < dedargs.length; i++)
1757 TemplateParameter tparam = (*parameters)[i];
1759 RootObject oarg = (*dedargs)[i];
1760 RootObject oded = (*dedtypes)[i];
1761 if (oarg)
1762 continue;
1764 if (oded)
1766 if (tparam.specialization() || !tparam.isTemplateTypeParameter())
1768 /* The specialization can work as long as afterwards
1769 * the oded == oarg
1771 (*dedargs)[i] = oded;
1772 MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
1773 //printf("m2 = %d\n", m2);
1774 if (m2 == MATCH.nomatch)
1775 return nomatch();
1776 if (m2 < matchTiargs)
1777 matchTiargs = m2; // pick worst match
1778 if (!(*dedtypes)[i].equals(oded))
1779 .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, kind, toPrettyChars, tparam.ident.toChars());
1781 else
1783 if (MATCH.convert < matchTiargs)
1784 matchTiargs = MATCH.convert;
1786 (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
1788 else
1790 oded = tparam.defaultArg(instLoc, paramscope);
1791 if (oded)
1792 (*dedargs)[i] = declareParameter(paramscope, tparam, oded);
1796 nfargs2 = argi + 1;
1798 /* If prmtype does not depend on any template parameters:
1800 * auto foo(T)(T v, double x = 0);
1801 * foo("str");
1802 * // at fparam == 'double x = 0'
1804 * or, if all template parameters in the prmtype are already deduced:
1806 * auto foo(R)(R range, ElementType!R sum = 0);
1807 * foo([1,2,3]);
1808 * // at fparam == 'ElementType!R sum = 0'
1810 * Deducing prmtype from fparam.defaultArg is not necessary.
1812 if (prmtype.deco || prmtype.syntaxCopy().trySemantic(loc, paramscope))
1814 ++argi;
1815 continue;
1818 // Deduce prmtype from the defaultArg.
1819 farg = fparam.defaultArg.syntaxCopy();
1820 farg = farg.expressionSemantic(paramscope);
1821 farg = resolveProperties(paramscope, farg);
1823 else
1825 farg = (*fargs)[argi];
1828 // Check invalid arguments to detect errors early.
1829 if (farg.op == EXP.error || farg.type.ty == Terror)
1830 return nomatch();
1832 Type att = null;
1833 Lretry:
1834 version (none)
1836 printf("\tfarg.type = %s\n", farg.type.toChars());
1837 printf("\tfparam.type = %s\n", prmtype.toChars());
1839 Type argtype = farg.type;
1841 if (!fparam.isLazy() && argtype.ty == Tvoid && farg.op != EXP.function_)
1842 return nomatch();
1844 // https://issues.dlang.org/show_bug.cgi?id=12876
1845 // Optimize argument to allow CT-known length matching
1846 farg = farg.optimize(WANTvalue, fparam.isReference());
1847 //printf("farg = %s %s\n", farg.type.toChars(), farg.toChars());
1849 RootObject oarg = farg;
1850 if ((fparam.storageClass & STC.ref_) && (!(fparam.storageClass & STC.auto_) || farg.isLvalue()))
1852 /* Allow expressions that have CT-known boundaries and type [] to match with [dim]
1854 Type taai;
1855 if (argtype.ty == Tarray && (prmtype.ty == Tsarray || prmtype.ty == Taarray && (taai = (cast(TypeAArray)prmtype).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
1857 if (StringExp se = farg.isStringExp())
1859 argtype = se.type.nextOf().sarrayOf(se.len);
1861 else if (ArrayLiteralExp ae = farg.isArrayLiteralExp())
1863 argtype = ae.type.nextOf().sarrayOf(ae.elements.length);
1865 else if (SliceExp se = farg.isSliceExp())
1867 if (Type tsa = toStaticArrayType(se))
1868 argtype = tsa;
1872 oarg = argtype;
1874 else if ((fparam.storageClass & STC.out_) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && (cast(TypeIdentifier)prmtype).idents.length == 0)
1876 /* The farg passing to the prmtype always make a copy. Therefore,
1877 * we can shrink the set of the deduced type arguments for prmtype
1878 * by adjusting top-qualifier of the argtype.
1880 * prmtype argtype ta
1881 * T <- const(E)[] const(E)[]
1882 * T <- const(E[]) const(E)[]
1883 * qualifier(T) <- const(E)[] const(E[])
1884 * qualifier(T) <- const(E[]) const(E[])
1886 Type ta = argtype.castMod(prmtype.mod ? argtype.nextOf().mod : 0);
1887 if (ta != argtype)
1889 Expression ea = farg.copy();
1890 ea.type = ta;
1891 oarg = ea;
1895 if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < nfargs)
1896 goto Lvarargs;
1898 uint im = 0;
1899 MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &im, inferStart);
1900 //printf("\tL%d deduceType m = %d, im = x%x, inoutMatch = x%x\n", __LINE__, m, im, inoutMatch);
1901 inoutMatch |= im;
1903 /* If no match, see if the argument can be matched by using
1904 * implicit conversions.
1906 if (m == MATCH.nomatch && prmtype.deco)
1907 m = farg.implicitConvTo(prmtype);
1909 if (m == MATCH.nomatch)
1911 AggregateDeclaration ad = isAggregate(farg.type);
1912 if (ad && ad.aliasthis && !isRecursiveAliasThis(att, argtype))
1914 // https://issues.dlang.org/show_bug.cgi?id=12537
1915 // The isRecursiveAliasThis() call above
1917 /* If a semantic error occurs while doing alias this,
1918 * eg purity(https://issues.dlang.org/show_bug.cgi?id=7295),
1919 * just regard it as not a match.
1921 * We also save/restore sc.func.flags to avoid messing up
1922 * attribute inference in the evaluation.
1924 const oldflags = sc.func ? sc.func.flags : 0;
1925 auto e = resolveAliasThis(sc, farg, true);
1926 if (sc.func)
1927 sc.func.flags = oldflags;
1928 if (e)
1930 farg = e;
1931 goto Lretry;
1936 if (m > MATCH.nomatch && (fparam.storageClass & (STC.ref_ | STC.auto_)) == STC.ref_)
1938 if (!farg.isLvalue())
1940 if ((farg.op == EXP.string_ || farg.op == EXP.slice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
1942 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
1944 else if (global.params.rvalueRefParam == FeatureState.enabled)
1946 // Allow implicit conversion to ref
1948 else
1949 return nomatch();
1952 if (m > MATCH.nomatch && (fparam.storageClass & STC.out_))
1954 if (!farg.isLvalue())
1955 return nomatch();
1956 if (!farg.type.isMutable()) // https://issues.dlang.org/show_bug.cgi?id=11916
1957 return nomatch();
1959 if (m == MATCH.nomatch && fparam.isLazy() && prmtype.ty == Tvoid && farg.type.ty != Tvoid)
1960 m = MATCH.convert;
1961 if (m != MATCH.nomatch)
1963 if (m < match)
1964 match = m; // pick worst match
1965 argi++;
1966 continue;
1970 Lvarargs:
1971 /* The following code for variadic arguments closely
1972 * matches TypeFunction.callMatch()
1974 if (!(fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams))
1975 return nomatch();
1977 /* Check for match with function parameter T...
1979 Type tb = prmtype.toBasetype();
1980 switch (tb.ty)
1982 // 6764 fix - TypeAArray may be TypeSArray have not yet run semantic().
1983 case Tsarray:
1984 case Taarray:
1986 // Perhaps we can do better with this, see TypeFunction.callMatch()
1987 if (tb.ty == Tsarray)
1989 TypeSArray tsa = cast(TypeSArray)tb;
1990 dinteger_t sz = tsa.dim.toInteger();
1991 if (sz != nfargs - argi)
1992 return nomatch();
1994 else if (tb.ty == Taarray)
1996 TypeAArray taa = cast(TypeAArray)tb;
1997 Expression dim = new IntegerExp(instLoc, nfargs - argi, Type.tsize_t);
1999 size_t i = templateParameterLookup(taa.index, parameters);
2000 if (i == IDX_NOTFOUND)
2002 Expression e;
2003 Type t;
2004 Dsymbol s;
2005 Scope *sco;
2007 uint errors = global.startGagging();
2008 /* ref: https://issues.dlang.org/show_bug.cgi?id=11118
2009 * The parameter isn't part of the template
2010 * ones, let's try to find it in the
2011 * instantiation scope 'sc' and the one
2012 * belonging to the template itself. */
2013 sco = sc;
2014 taa.index.resolve(instLoc, sco, e, t, s);
2015 if (!e)
2017 sco = paramscope;
2018 taa.index.resolve(instLoc, sco, e, t, s);
2020 global.endGagging(errors);
2022 if (!e)
2023 return nomatch();
2025 e = e.ctfeInterpret();
2026 e = e.implicitCastTo(sco, Type.tsize_t);
2027 e = e.optimize(WANTvalue);
2028 if (!dim.equals(e))
2029 return nomatch();
2031 else
2033 // This code matches code in TypeInstance.deduceType()
2034 TemplateParameter tprm = (*parameters)[i];
2035 TemplateValueParameter tvp = tprm.isTemplateValueParameter();
2036 if (!tvp)
2037 return nomatch();
2038 Expression e = cast(Expression)(*dedtypes)[i];
2039 if (e)
2041 if (!dim.equals(e))
2042 return nomatch();
2044 else
2046 Type vt = tvp.valType.typeSemantic(Loc.initial, sc);
2047 MATCH m = dim.implicitConvTo(vt);
2048 if (m == MATCH.nomatch)
2049 return nomatch();
2050 (*dedtypes)[i] = dim;
2054 goto case Tarray;
2056 case Tarray:
2058 TypeArray ta = cast(TypeArray)tb;
2059 Type tret = fparam.isLazyArray();
2060 for (; argi < nfargs; argi++)
2062 Expression arg = (*fargs)[argi];
2063 assert(arg);
2065 MATCH m;
2066 /* If lazy array of delegates,
2067 * convert arg(s) to delegate(s)
2069 if (tret)
2071 if (ta.next.equals(arg.type))
2073 m = MATCH.exact;
2075 else
2077 m = arg.implicitConvTo(tret);
2078 if (m == MATCH.nomatch)
2080 if (tret.toBasetype().ty == Tvoid)
2081 m = MATCH.convert;
2085 else
2087 uint wm = 0;
2088 m = deduceType(arg, paramscope, ta.next, parameters, dedtypes, &wm, inferStart);
2089 inoutMatch |= wm;
2091 if (m == MATCH.nomatch)
2092 return nomatch();
2093 if (m < match)
2094 match = m;
2096 goto Lmatch;
2098 case Tclass:
2099 case Tident:
2100 goto Lmatch;
2102 default:
2103 return nomatch();
2105 assert(0);
2107 //printf(". argi = %d, nfargs = %d, nfargs2 = %d\n", argi, nfargs, nfargs2);
2108 if (argi != nfargs2 && fparameters.varargs == VarArg.none)
2109 return nomatch();
2112 Lmatch:
2113 foreach (ref dedtype; *dedtypes)
2115 Type at = isType(dedtype);
2116 if (at)
2118 if (at.ty == Tnone)
2120 TypeDeduced xt = cast(TypeDeduced)at;
2121 at = xt.tded; // 'unbox'
2123 dedtype = at.merge2();
2126 for (size_t i = ntargs; i < dedargs.length; i++)
2128 TemplateParameter tparam = (*parameters)[i];
2129 //printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
2131 /* For T:T*, the dedargs is the T*, dedtypes is the T
2132 * But for function templates, we really need them to match
2134 RootObject oarg = (*dedargs)[i];
2135 RootObject oded = (*dedtypes)[i];
2136 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
2137 //if (oarg) printf("oarg: %s\n", oarg.toChars());
2138 //if (oded) printf("oded: %s\n", oded.toChars());
2139 if (oarg)
2140 continue;
2142 if (oded)
2144 if (tparam.specialization() || !tparam.isTemplateTypeParameter())
2146 /* The specialization can work as long as afterwards
2147 * the oded == oarg
2149 (*dedargs)[i] = oded;
2150 MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
2151 //printf("m2 = %d\n", m2);
2152 if (m2 == MATCH.nomatch)
2153 return nomatch();
2154 if (m2 < matchTiargs)
2155 matchTiargs = m2; // pick worst match
2156 if (!(*dedtypes)[i].equals(oded))
2157 .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, tparam.ident.toChars());
2159 else
2161 // Discussion: https://issues.dlang.org/show_bug.cgi?id=16484
2162 if (MATCH.convert < matchTiargs)
2163 matchTiargs = MATCH.convert;
2166 else
2168 oded = tparam.defaultArg(instLoc, paramscope);
2169 if (!oded)
2171 // if tuple parameter and
2172 // tuple parameter was not in function parameter list and
2173 // we're one or more arguments short (i.e. no tuple argument)
2174 if (tparam == tp &&
2175 fptupindex == IDX_NOTFOUND &&
2176 ntargs <= dedargs.length - 1)
2178 // make tuple argument an empty tuple
2179 oded = new Tuple();
2181 else
2182 return nomatch();
2184 if (isError(oded))
2185 return matcherror();
2186 ntargs++;
2188 /* At the template parameter T, the picked default template argument
2189 * X!int should be matched to T in order to deduce dependent
2190 * template parameter A.
2191 * auto foo(T : X!A = X!int, A...)() { ... }
2192 * foo(); // T <-- X!int, A <-- (int)
2194 if (tparam.specialization())
2196 (*dedargs)[i] = oded;
2197 MATCH m2 = tparam.matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, null);
2198 //printf("m2 = %d\n", m2);
2199 if (m2 == MATCH.nomatch)
2200 return nomatch();
2201 if (m2 < matchTiargs)
2202 matchTiargs = m2; // pick worst match
2203 if (!(*dedtypes)[i].equals(oded))
2204 .error(loc, "%s `%s` specialization not allowed for deduced parameter `%s`", kind, toPrettyChars, tparam.ident.toChars());
2207 oded = declareParameter(paramscope, tparam, oded);
2208 (*dedargs)[i] = oded;
2211 /* https://issues.dlang.org/show_bug.cgi?id=7469
2212 * As same as the code for 7469 in findBestMatch,
2213 * expand a Tuple in dedargs to normalize template arguments.
2215 if (auto d = dedargs.length)
2217 if (auto va = isTuple((*dedargs)[d - 1]))
2219 dedargs.setDim(d - 1);
2220 dedargs.insert(d - 1, &va.objects);
2223 ti.tiargs = dedargs; // update to the normalized template arguments.
2225 // Partially instantiate function for constraint and fd.leastAsSpecialized()
2227 assert(paramscope.scopesym);
2228 Scope* sc2 = _scope;
2229 sc2 = sc2.push(paramscope.scopesym);
2230 sc2 = sc2.push(ti);
2231 sc2.parent = ti;
2232 sc2.tinst = ti;
2233 sc2.minst = sc.minst;
2234 sc2.stc |= fd.storage_class & STC.deprecated_;
2236 fd = doHeaderInstantiation(ti, sc2, fd, tthis, fargs);
2238 sc2 = sc2.pop();
2239 sc2 = sc2.pop();
2241 if (!fd)
2242 return nomatch();
2245 if (constraint)
2247 if (!evaluateConstraint(ti, sc, paramscope, dedargs, fd))
2248 return nomatch();
2251 version (none)
2253 for (size_t i = 0; i < dedargs.length; i++)
2255 RootObject o = (*dedargs)[i];
2256 printf("\tdedargs[%d] = %d, %s\n", i, o.dyncast(), o.toChars());
2260 paramscope.pop();
2261 //printf("\tmatch %d\n", match);
2262 return MATCHpair(matchTiargs, match);
2265 /**************************************************
2266 * Declare template parameter tp with value o, and install it in the scope sc.
2268 extern (D) RootObject declareParameter(Scope* sc, TemplateParameter tp, RootObject o)
2270 //printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o);
2271 Type ta = isType(o);
2272 Expression ea = isExpression(o);
2273 Dsymbol sa = isDsymbol(o);
2274 Tuple va = isTuple(o);
2276 Declaration d;
2277 VarDeclaration v = null;
2279 if (ea)
2281 if (ea.op == EXP.type)
2282 ta = ea.type;
2283 else if (auto se = ea.isScopeExp())
2284 sa = se.sds;
2285 else if (auto te = ea.isThisExp())
2286 sa = te.var;
2287 else if (auto se = ea.isSuperExp())
2288 sa = se.var;
2289 else if (auto fe = ea.isFuncExp())
2291 if (fe.td)
2292 sa = fe.td;
2293 else
2294 sa = fe.fd;
2298 if (ta)
2300 //printf("type %s\n", ta.toChars());
2301 auto ad = new AliasDeclaration(Loc.initial, tp.ident, ta);
2302 ad.storage_class |= STC.templateparameter;
2303 d = ad;
2305 else if (sa)
2307 //printf("Alias %s %s;\n", sa.ident.toChars(), tp.ident.toChars());
2308 auto ad = new AliasDeclaration(Loc.initial, tp.ident, sa);
2309 ad.storage_class |= STC.templateparameter;
2310 d = ad;
2312 else if (ea)
2314 // tdtypes.data[i] always matches ea here
2315 Initializer _init = new ExpInitializer(loc, ea);
2316 TemplateValueParameter tvp = tp.isTemplateValueParameter();
2317 Type t = tvp ? tvp.valType : null;
2318 v = new VarDeclaration(loc, t, tp.ident, _init);
2319 v.storage_class = STC.manifest | STC.templateparameter;
2320 d = v;
2322 else if (va)
2324 //printf("\ttuple\n");
2325 d = new TupleDeclaration(loc, tp.ident, &va.objects);
2327 else
2329 assert(0);
2331 d.storage_class |= STC.templateparameter;
2333 if (ta)
2335 Type t = ta;
2336 // consistent with Type.checkDeprecated()
2337 while (t.ty != Tenum)
2339 if (!t.nextOf())
2340 break;
2341 t = (cast(TypeNext)t).next;
2343 if (Dsymbol s = t.toDsymbol(sc))
2345 if (s.isDeprecated())
2346 d.storage_class |= STC.deprecated_;
2349 else if (sa)
2351 if (sa.isDeprecated())
2352 d.storage_class |= STC.deprecated_;
2355 if (!sc.insert(d))
2356 .error(loc, "%s `%s` declaration `%s` is already defined", kind, toPrettyChars, tp.ident.toChars());
2357 d.dsymbolSemantic(sc);
2358 /* So the caller's o gets updated with the result of semantic() being run on o
2360 if (v)
2361 o = v._init.initializerToExpression();
2362 return o;
2365 /*************************************************
2366 * Limited function template instantiation for using fd.leastAsSpecialized()
2368 extern (D) FuncDeclaration doHeaderInstantiation(TemplateInstance ti, Scope* sc2, FuncDeclaration fd, Type tthis, Expressions* fargs)
2370 assert(fd);
2371 version (none)
2373 printf("doHeaderInstantiation this = %s\n", toChars());
2376 // function body and contracts are not need
2377 if (fd.isCtorDeclaration())
2378 fd = new CtorDeclaration(fd.loc, fd.endloc, fd.storage_class, fd.type.syntaxCopy());
2379 else
2380 fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, fd.type.syntaxCopy());
2381 fd.parent = ti;
2383 assert(fd.type.ty == Tfunction);
2384 auto tf = fd.type.isTypeFunction();
2385 tf.fargs = fargs;
2387 if (tthis)
2389 // Match 'tthis' to any TemplateThisParameter's
2390 bool hasttp = false;
2391 foreach (tp; *parameters)
2393 TemplateThisParameter ttp = tp.isTemplateThisParameter();
2394 if (ttp)
2395 hasttp = true;
2397 if (hasttp)
2399 tf = cast(TypeFunction)tf.addSTC(ModToStc(tthis.mod));
2400 assert(!tf.deco);
2404 Scope* scx = sc2.push();
2406 // Shouldn't run semantic on default arguments and return type.
2407 foreach (ref params; *tf.parameterList.parameters)
2408 params.defaultArg = null;
2409 tf.incomplete = true;
2411 if (fd.isCtorDeclaration())
2413 // For constructors, emitting return type is necessary for
2414 // isReturnIsolated() in functionResolve.
2415 tf.isctor = true;
2417 Dsymbol parent = toParentDecl();
2418 Type tret;
2419 AggregateDeclaration ad = parent.isAggregateDeclaration();
2420 if (!ad || parent.isUnionDeclaration())
2422 tret = Type.tvoid;
2424 else
2426 tret = ad.handleType();
2427 assert(tret);
2428 tret = tret.addStorageClass(fd.storage_class | scx.stc);
2429 tret = tret.addMod(tf.mod);
2431 tf.next = tret;
2432 if (ad && ad.isStructDeclaration())
2433 tf.isref = 1;
2434 //printf("tf = %s\n", tf.toChars());
2436 else
2437 tf.next = null;
2438 fd.type = tf;
2439 fd.type = fd.type.addSTC(scx.stc);
2440 fd.type = fd.type.typeSemantic(fd.loc, scx);
2441 scx = scx.pop();
2443 if (fd.type.ty != Tfunction)
2444 return null;
2446 fd.originalType = fd.type; // for mangling
2447 //printf("\t[%s] fd.type = %s, mod = %x, ", loc.toChars(), fd.type.toChars(), fd.type.mod);
2448 //printf("fd.needThis() = %d\n", fd.needThis());
2450 return fd;
2453 debug (FindExistingInstance)
2455 __gshared uint nFound, nNotFound, nAdded, nRemoved;
2457 shared static ~this()
2459 printf("debug (FindExistingInstance) nFound %u, nNotFound: %u, nAdded: %u, nRemoved: %u\n",
2460 nFound, nNotFound, nAdded, nRemoved);
2464 /****************************************************
2465 * Given a new instance tithis of this TemplateDeclaration,
2466 * see if there already exists an instance.
2467 * If so, return that existing instance.
2469 extern (D) TemplateInstance findExistingInstance(TemplateInstance tithis, Expressions* fargs)
2471 //printf("findExistingInstance() %s\n", tithis.toChars());
2472 tithis.fargs = fargs;
2473 auto tibox = TemplateInstanceBox(tithis);
2474 auto p = tibox in instances;
2475 debug (FindExistingInstance) ++(p ? nFound : nNotFound);
2476 //if (p) printf("\tfound %p\n", *p); else printf("\tnot found\n");
2477 return p ? *p : null;
2480 /********************************************
2481 * Add instance ti to TemplateDeclaration's table of instances.
2482 * Return a handle we can use to later remove it if it fails instantiation.
2484 extern (D) TemplateInstance addInstance(TemplateInstance ti)
2486 //printf("addInstance() %p %s\n", instances, ti.toChars());
2487 auto tibox = TemplateInstanceBox(ti);
2488 instances[tibox] = ti;
2489 debug (FindExistingInstance) ++nAdded;
2490 return ti;
2493 /*******************************************
2494 * Remove TemplateInstance from table of instances.
2495 * Input:
2496 * handle returned by addInstance()
2498 extern (D) void removeInstance(TemplateInstance ti)
2500 //printf("removeInstance() %s\n", ti.toChars());
2501 auto tibox = TemplateInstanceBox(ti);
2502 debug (FindExistingInstance) ++nRemoved;
2503 instances.remove(tibox);
2506 override inout(TemplateDeclaration) isTemplateDeclaration() inout
2508 return this;
2512 * Check if the last template parameter is a tuple one,
2513 * and returns it if so, else returns `null`.
2515 * Returns:
2516 * The last template parameter if it's a `TemplateTupleParameter`
2518 extern (D) TemplateTupleParameter isVariadic()
2520 size_t dim = parameters.length;
2521 if (dim == 0)
2522 return null;
2523 return (*parameters)[dim - 1].isTemplateTupleParameter();
2526 extern(C++) override bool isDeprecated() const
2528 return this.deprecated_;
2531 /***********************************
2532 * We can overload templates.
2534 override bool isOverloadable() const
2536 return true;
2539 override void accept(Visitor v)
2541 v.visit(this);
2545 extern (C++) final class TypeDeduced : Type
2547 Type tded;
2548 Expressions argexps; // corresponding expressions
2549 Types tparams; // tparams[i].mod
2551 extern (D) this(Type tt, Expression e, Type tparam)
2553 super(Tnone);
2554 tded = tt;
2555 argexps.push(e);
2556 tparams.push(tparam);
2559 void update(Expression e, Type tparam)
2561 argexps.push(e);
2562 tparams.push(tparam);
2565 void update(Type tt, Expression e, Type tparam)
2567 tded = tt;
2568 argexps.push(e);
2569 tparams.push(tparam);
2572 MATCH matchAll(Type tt)
2574 MATCH match = MATCH.exact;
2575 foreach (j, e; argexps)
2577 assert(e);
2578 if (e == emptyArrayElement)
2579 continue;
2581 Type t = tt.addMod(tparams[j].mod).substWildTo(MODFlags.const_);
2583 MATCH m = e.implicitConvTo(t);
2584 if (match > m)
2585 match = m;
2586 if (match == MATCH.nomatch)
2587 break;
2589 return match;
2594 /*************************************************
2595 * Given function arguments, figure out which template function
2596 * to expand, and return matching result.
2597 * Params:
2598 * m = matching result
2599 * dstart = the root of overloaded function templates
2600 * loc = instantiation location
2601 * sc = instantiation scope
2602 * tiargs = initial list of template arguments
2603 * tthis = if !NULL, the 'this' pointer argument
2604 * argumentList= arguments to function
2605 * pMessage = address to store error message, or null
2607 void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs,
2608 Type tthis, ArgumentList argumentList, const(char)** pMessage = null)
2610 version (none)
2612 printf("functionResolve() dstart = %s\n", dstart.toChars());
2613 printf(" tiargs:\n");
2614 if (tiargs)
2616 for (size_t i = 0; i < tiargs.length; i++)
2618 RootObject arg = (*tiargs)[i];
2619 printf("\t%s\n", arg.toChars());
2622 printf(" fargs:\n");
2623 for (size_t i = 0; i < (fargs ? fargs.length : 0); i++)
2625 Expression arg = (*fargs)[i];
2626 printf("\t%s %s\n", arg.type.toChars(), arg.toChars());
2627 //printf("\tty = %d\n", arg.type.ty);
2629 //printf("stc = %llx\n", dstart._scope.stc);
2630 //printf("match:t/f = %d/%d\n", ta_last, m.last);
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;
2643 int applyFunction(FuncDeclaration fd)
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.length > 0)
2650 return 0;
2652 // constructors need a valid scope in order to detect semantic errors
2653 if (!fd.isCtorDeclaration &&
2654 fd.semanticRun < PASS.semanticdone)
2656 Ungag ungag = fd.ungagSpeculative();
2657 fd.dsymbolSemantic(null);
2659 if (fd.semanticRun < PASS.semanticdone)
2661 .error(loc, "forward reference to template `%s`", fd.toChars());
2662 return 1;
2664 //printf("fd = %s %s, fargs = %s\n", fd.toChars(), fd.type.toChars(), fargs.toChars());
2665 auto tf = cast(TypeFunction)fd.type;
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");
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.
2677 Type tthis_fd = fd.needThis() ? tthis : null;
2678 bool isCtorCall = tthis_fd && fd.isCtorDeclaration();
2679 if (isCtorCall)
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())
2687 /* && tf.isShared() == tthis_fd.isShared()*/
2688 // Uniquely constructed object can ignore shared qualifier.
2689 // TODO: Is this appropriate?
2690 tthis_fd = null;
2692 else
2693 return 0; // MATCH.nomatch
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.
2703 if (auto dt = fd.isDtorDeclaration())
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;
2714 MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, pMessage, sc);
2715 //printf("test1: mfa = %d\n", mfa);
2716 if (mfa == MATCH.nomatch)
2717 return 0;
2719 int firstIsBetter()
2721 td_best = null;
2722 ti_best = null;
2723 ta_last = MATCH.exact;
2724 m.last = mfa;
2725 m.lastf = fd;
2726 tthis_best = tthis_fd;
2727 ov_index = 0;
2728 m.count = 1;
2729 return 0;
2732 if (mfa > m.last) return firstIsBetter();
2733 if (mfa < m.last) return 0;
2735 /* See if one of the matches overrides the other.
2737 assert(m.lastf);
2738 if (m.lastf.overrides(fd)) return 0;
2739 if (fd.overrides(m.lastf)) return firstIsBetter();
2741 /* Try to disambiguate using template-style partial ordering rules.
2742 * In essence, if f() and g() are ambiguous, if f() can call g(),
2743 * but g() cannot call f(), then pick f().
2744 * This is because f() is "more specialized."
2747 MATCH c1 = fd.leastAsSpecialized(m.lastf, argumentList.names);
2748 MATCH c2 = m.lastf.leastAsSpecialized(fd, argumentList.names);
2749 //printf("c1 = %d, c2 = %d\n", c1, c2);
2750 if (c1 > c2) return firstIsBetter();
2751 if (c1 < c2) return 0;
2754 /* The 'overrides' check above does covariant checking only
2755 * for virtual member functions. It should do it for all functions,
2756 * but in order to not risk breaking code we put it after
2757 * the 'leastAsSpecialized' check.
2758 * In the future try moving it before.
2759 * I.e. a not-the-same-but-covariant match is preferred,
2760 * as it is more restrictive.
2762 if (!m.lastf.type.equals(fd.type))
2764 //printf("cov: %d %d\n", m.lastf.type.covariant(fd.type), fd.type.covariant(m.lastf.type));
2765 const lastCovariant = m.lastf.type.covariant(fd.type);
2766 const firstCovariant = fd.type.covariant(m.lastf.type);
2768 if (lastCovariant == Covariant.yes || lastCovariant == Covariant.no)
2770 if (firstCovariant != Covariant.yes && firstCovariant != Covariant.no)
2772 return 0;
2775 else if (firstCovariant == Covariant.yes || firstCovariant == Covariant.no)
2777 return firstIsBetter();
2781 /* If the two functions are the same function, like:
2782 * int foo(int);
2783 * int foo(int x) { ... }
2784 * then pick the one with the body.
2786 * If none has a body then don't care because the same
2787 * real function would be linked to the decl (e.g from object file)
2789 if (tf.equals(m.lastf.type) &&
2790 fd.storage_class == m.lastf.storage_class &&
2791 fd.parent == m.lastf.parent &&
2792 fd.visibility == m.lastf.visibility &&
2793 fd._linkage == m.lastf._linkage)
2795 if (fd.fbody && !m.lastf.fbody)
2796 return firstIsBetter();
2797 if (!fd.fbody)
2798 return 0;
2801 // https://issues.dlang.org/show_bug.cgi?id=14450
2802 // Prefer exact qualified constructor for the creating object type
2803 if (isCtorCall && tf.mod != m.lastf.type.mod)
2805 if (tthis.mod == tf.mod) return firstIsBetter();
2806 if (tthis.mod == m.lastf.type.mod) return 0;
2809 m.nextf = fd;
2810 m.count++;
2811 return 0;
2814 int applyTemplate(TemplateDeclaration td)
2816 //printf("applyTemplate(): td = %s\n", td.toChars());
2817 if (td == td_best) // skip duplicates
2818 return 0;
2820 if (!sc)
2821 sc = td._scope; // workaround for Type.aliasthisOf
2823 if (td.semanticRun == PASS.initial && td._scope)
2825 // Try to fix forward reference. Ungag errors while doing so.
2826 Ungag ungag = td.ungagSpeculative();
2827 td.dsymbolSemantic(td._scope);
2829 if (td.semanticRun == PASS.initial)
2831 .error(loc, "forward reference to template `%s`", td.toChars());
2832 Lerror:
2833 m.lastf = null;
2834 m.count = 0;
2835 m.last = MATCH.nomatch;
2836 return 1;
2838 //printf("td = %s\n", td.toChars());
2840 if (argumentList.hasNames)
2842 .error(loc, "named arguments with Implicit Function Template Instantiation are not supported yet");
2843 goto Lerror;
2845 auto f = td.onemember ? td.onemember.isFuncDeclaration() : null;
2846 if (!f)
2848 if (!tiargs)
2849 tiargs = new Objects();
2850 auto ti = new TemplateInstance(loc, td, tiargs);
2851 Objects dedtypes = Objects(td.parameters.length);
2852 assert(td.semanticRun != PASS.initial);
2853 MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, argumentList, 0);
2854 //printf("matchWithInstance = %d\n", mta);
2855 if (mta == MATCH.nomatch || mta < ta_last) // no match or less match
2856 return 0;
2858 ti.templateInstanceSemantic(sc, argumentList);
2859 if (!ti.inst) // if template failed to expand
2860 return 0;
2862 Dsymbol s = ti.inst.toAlias();
2863 FuncDeclaration fd;
2864 if (auto tdx = s.isTemplateDeclaration())
2866 Objects dedtypesX; // empty tiargs
2868 // https://issues.dlang.org/show_bug.cgi?id=11553
2869 // Check for recursive instantiation of tdx.
2870 for (TemplatePrevious* p = tdx.previous; p; p = p.prev)
2872 if (arrayObjectMatch(p.dedargs, &dedtypesX))
2874 //printf("recursive, no match p.sc=%p %p %s\n", p.sc, this, this.toChars());
2875 /* It must be a subscope of p.sc, other scope chains are not recursive
2876 * instantiations.
2878 for (Scope* scx = sc; scx; scx = scx.enclosing)
2880 if (scx == p.sc)
2882 error(loc, "recursive template expansion while looking for `%s.%s`", ti.toChars(), tdx.toChars());
2883 goto Lerror;
2887 /* BUG: should also check for ref param differences
2891 TemplatePrevious pr;
2892 pr.prev = tdx.previous;
2893 pr.sc = sc;
2894 pr.dedargs = &dedtypesX;
2895 tdx.previous = &pr; // add this to threaded list
2897 fd = resolveFuncCall(loc, sc, s, null, tthis, argumentList, FuncResolveFlag.quiet);
2899 tdx.previous = pr.prev; // unlink from threaded list
2901 else if (s.isFuncDeclaration())
2903 fd = resolveFuncCall(loc, sc, s, null, tthis, argumentList, FuncResolveFlag.quiet);
2905 else
2906 goto Lerror;
2908 if (!fd)
2909 return 0;
2911 if (fd.type.ty != Tfunction)
2913 m.lastf = fd; // to propagate "error match"
2914 m.count = 1;
2915 m.last = MATCH.nomatch;
2916 return 1;
2919 Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null;
2921 auto tf = cast(TypeFunction)fd.type;
2922 MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, null, sc);
2923 if (mfa < m.last)
2924 return 0;
2926 if (mta < ta_last) goto Ltd_best2;
2927 if (mta > ta_last) goto Ltd2;
2929 if (mfa < m.last) goto Ltd_best2;
2930 if (mfa > m.last) goto Ltd2;
2932 // td_best and td are ambiguous
2933 //printf("Lambig2\n");
2934 m.nextf = fd;
2935 m.count++;
2936 return 0;
2938 Ltd_best2:
2939 return 0;
2941 Ltd2:
2942 // td is the new best match
2943 assert(td._scope);
2944 td_best = td;
2945 ti_best = null;
2946 property = 0; // (backward compatibility)
2947 ta_last = mta;
2948 m.last = mfa;
2949 m.lastf = fd;
2950 tthis_best = tthis_fd;
2951 ov_index = 0;
2952 m.nextf = null;
2953 m.count = 1;
2954 return 0;
2957 //printf("td = %s\n", td.toChars());
2958 for (size_t ovi = 0; f; f = f.overnext0, ovi++)
2960 if (f.type.ty != Tfunction || f.errors)
2961 goto Lerror;
2963 /* This is a 'dummy' instance to evaluate constraint properly.
2965 auto ti = new TemplateInstance(loc, td, tiargs);
2966 ti.parent = td.parent; // Maybe calculating valid 'enclosing' is unnecessary.
2968 auto fd = f;
2969 MATCHpair x = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, argumentList);
2970 MATCH mta = x.mta;
2971 MATCH mfa = x.mfa;
2972 //printf("match:t/f = %d/%d\n", mta, mfa);
2973 if (!fd || mfa == MATCH.nomatch)
2974 continue;
2976 Type tthis_fd = fd.needThis() ? tthis : null;
2978 bool isCtorCall = tthis_fd && fd.isCtorDeclaration();
2979 if (isCtorCall)
2981 // Constructor call requires additional check.
2982 auto tf = cast(TypeFunction)fd.type;
2983 assert(tf.next);
2984 if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
2985 tf.isWild() && tf.isShared() == tthis_fd.isShared() ||
2986 fd.isReturnIsolated())
2988 tthis_fd = null;
2990 else
2991 continue; // MATCH.nomatch
2993 // need to check here whether the constructor is the member of a struct
2994 // declaration that defines a copy constructor. This is already checked
2995 // in the semantic of CtorDeclaration, however, when matching functions,
2996 // the template instance is not expanded.
2997 // https://issues.dlang.org/show_bug.cgi?id=21613
2998 auto ad = fd.isThis();
2999 auto sd = ad.isStructDeclaration();
3000 if (checkHasBothRvalueAndCpCtor(sd, fd.isCtorDeclaration(), ti))
3001 continue;
3004 if (mta < ta_last) goto Ltd_best;
3005 if (mta > ta_last) goto Ltd;
3007 if (mfa < m.last) goto Ltd_best;
3008 if (mfa > m.last) goto Ltd;
3010 if (td_best)
3012 // Disambiguate by picking the most specialized TemplateDeclaration
3013 MATCH c1 = td.leastAsSpecialized(sc, td_best, argumentList);
3014 MATCH c2 = td_best.leastAsSpecialized(sc, td, argumentList);
3015 //printf("1: c1 = %d, c2 = %d\n", c1, c2);
3016 if (c1 > c2) goto Ltd;
3017 if (c1 < c2) goto Ltd_best;
3019 assert(fd && m.lastf);
3021 // Disambiguate by tf.callMatch
3022 auto tf1 = fd.type.isTypeFunction();
3023 auto tf2 = m.lastf.type.isTypeFunction();
3024 MATCH c1 = tf1.callMatch(tthis_fd, argumentList, 0, null, sc);
3025 MATCH c2 = tf2.callMatch(tthis_best, argumentList, 0, null, sc);
3026 //printf("2: c1 = %d, c2 = %d\n", c1, c2);
3027 if (c1 > c2) goto Ltd;
3028 if (c1 < c2) goto Ltd_best;
3031 // Disambiguate by picking the most specialized FunctionDeclaration
3032 MATCH c1 = fd.leastAsSpecialized(m.lastf, argumentList.names);
3033 MATCH c2 = m.lastf.leastAsSpecialized(fd, argumentList.names);
3034 //printf("3: c1 = %d, c2 = %d\n", c1, c2);
3035 if (c1 > c2) goto Ltd;
3036 if (c1 < c2) goto Ltd_best;
3039 // https://issues.dlang.org/show_bug.cgi?id=14450
3040 // Prefer exact qualified constructor for the creating object type
3041 if (isCtorCall && fd.type.mod != m.lastf.type.mod)
3043 if (tthis.mod == fd.type.mod) goto Ltd;
3044 if (tthis.mod == m.lastf.type.mod) goto Ltd_best;
3047 m.nextf = fd;
3048 m.count++;
3049 continue;
3051 Ltd_best: // td_best is the best match so far
3052 //printf("Ltd_best\n");
3053 continue;
3055 Ltd: // td is the new best match
3056 //printf("Ltd\n");
3057 assert(td._scope);
3058 td_best = td;
3059 ti_best = ti;
3060 property = 0; // (backward compatibility)
3061 ta_last = mta;
3062 m.last = mfa;
3063 m.lastf = fd;
3064 tthis_best = tthis_fd;
3065 ov_index = ovi;
3066 m.nextf = null;
3067 m.count = 1;
3068 continue;
3070 return 0;
3073 auto td = dstart.isTemplateDeclaration();
3074 if (td && td.funcroot)
3075 dstart = td.funcroot;
3076 overloadApply(dstart, (Dsymbol s)
3078 if (s.errors)
3079 return 0;
3080 if (auto fd = s.isFuncDeclaration())
3081 return applyFunction(fd);
3082 if (auto td = s.isTemplateDeclaration())
3083 return applyTemplate(td);
3084 return 0;
3085 }, sc);
3087 //printf("td_best = %p, m.lastf = %p\n", td_best, m.lastf);
3088 if (td_best && ti_best && m.count == 1)
3090 // Matches to template function
3091 assert(td_best.onemember && td_best.onemember.isFuncDeclaration());
3092 /* The best match is td_best with arguments tdargs.
3093 * Now instantiate the template.
3095 assert(td_best._scope);
3096 if (!sc)
3097 sc = td_best._scope; // workaround for Type.aliasthisOf
3099 auto ti = new TemplateInstance(loc, td_best, ti_best.tiargs);
3100 ti.templateInstanceSemantic(sc, argumentList);
3102 m.lastf = ti.toAlias().isFuncDeclaration();
3103 if (!m.lastf)
3104 goto Lnomatch;
3105 if (ti.errors)
3107 Lerror:
3108 m.count = 1;
3109 assert(m.lastf);
3110 m.last = MATCH.nomatch;
3111 return;
3114 // look forward instantiated overload function
3115 // Dsymbol.oneMembers is alredy called in TemplateInstance.semantic.
3116 // it has filled overnext0d
3117 while (ov_index--)
3119 m.lastf = m.lastf.overnext0;
3120 assert(m.lastf);
3123 tthis_best = m.lastf.needThis() && !m.lastf.isCtorDeclaration() ? tthis : null;
3125 if (m.lastf.type.ty == Terror)
3126 goto Lerror;
3127 auto tf = m.lastf.type.isTypeFunction();
3128 if (!tf.callMatch(tthis_best, argumentList, 0, null, sc))
3129 goto Lnomatch;
3131 /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows,
3132 * a template instance can be matched while instantiating
3133 * that same template. Thus, the function type can be incomplete. Complete it.
3135 * https://issues.dlang.org/show_bug.cgi?id=9208
3136 * For auto function, completion should be deferred to the end of
3137 * its semantic3. Should not complete it in here.
3139 if (tf.next && !m.lastf.inferRetType)
3141 m.lastf.type = tf.typeSemantic(loc, sc);
3144 else if (m.lastf)
3146 // Matches to non template function,
3147 // or found matches were ambiguous.
3148 assert(m.count >= 1);
3150 else
3152 Lnomatch:
3153 m.count = 0;
3154 m.lastf = null;
3155 m.last = MATCH.nomatch;
3159 /* ======================== Type ============================================ */
3161 /****
3162 * Given an identifier, figure out which TemplateParameter it is.
3163 * Return IDX_NOTFOUND if not found.
3165 private size_t templateIdentifierLookup(Identifier id, TemplateParameters* parameters)
3167 for (size_t i = 0; i < parameters.length; i++)
3169 TemplateParameter tp = (*parameters)[i];
3170 if (tp.ident.equals(id))
3171 return i;
3173 return IDX_NOTFOUND;
3176 private size_t templateParameterLookup(Type tparam, TemplateParameters* parameters)
3178 if (tparam.ty == Tident)
3180 TypeIdentifier tident = cast(TypeIdentifier)tparam;
3181 //printf("\ttident = '%s'\n", tident.toChars());
3182 return templateIdentifierLookup(tident.ident, parameters);
3184 return IDX_NOTFOUND;
3187 private ubyte deduceWildHelper(Type t, Type* at, Type tparam)
3189 if ((tparam.mod & MODFlags.wild) == 0)
3190 return 0;
3192 *at = null;
3194 auto X(T, U)(T U, U T)
3196 return (U << 4) | T;
3199 switch (X(tparam.mod, t.mod))
3201 case X(MODFlags.wild, 0):
3202 case X(MODFlags.wild, MODFlags.const_):
3203 case X(MODFlags.wild, MODFlags.shared_):
3204 case X(MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3205 case X(MODFlags.wild, MODFlags.immutable_):
3206 case X(MODFlags.wildconst, 0):
3207 case X(MODFlags.wildconst, MODFlags.const_):
3208 case X(MODFlags.wildconst, MODFlags.shared_):
3209 case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3210 case X(MODFlags.wildconst, MODFlags.immutable_):
3211 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_):
3212 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3213 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.immutable_):
3214 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_):
3215 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3216 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.immutable_):
3218 ubyte wm = (t.mod & ~MODFlags.shared_);
3219 if (wm == 0)
3220 wm = MODFlags.mutable;
3221 ubyte m = (t.mod & (MODFlags.const_ | MODFlags.immutable_)) | (tparam.mod & t.mod & MODFlags.shared_);
3222 *at = t.unqualify(m);
3223 return wm;
3225 case X(MODFlags.wild, MODFlags.wild):
3226 case X(MODFlags.wild, MODFlags.wildconst):
3227 case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3228 case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3229 case X(MODFlags.wildconst, MODFlags.wild):
3230 case X(MODFlags.wildconst, MODFlags.wildconst):
3231 case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3232 case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3233 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3234 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3235 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3236 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3238 *at = t.unqualify(tparam.mod & t.mod);
3239 return MODFlags.wild;
3241 default:
3242 return 0;
3247 * Returns the common type of the 2 types.
3249 private Type rawTypeMerge(Type t1, Type t2)
3251 if (t1.equals(t2))
3252 return t1;
3253 if (t1.equivalent(t2))
3254 return t1.castMod(MODmerge(t1.mod, t2.mod));
3256 auto t1b = t1.toBasetype();
3257 auto t2b = t2.toBasetype();
3258 if (t1b.equals(t2b))
3259 return t1b;
3260 if (t1b.equivalent(t2b))
3261 return t1b.castMod(MODmerge(t1b.mod, t2b.mod));
3263 auto ty = implicitConvCommonTy(t1b.ty, t2b.ty);
3264 if (ty != Terror)
3265 return Type.basic[ty];
3267 return null;
3270 private MATCH deduceTypeHelper(Type t, Type* at, Type tparam)
3272 // 9*9 == 81 cases
3274 auto X(T, U)(T U, U T)
3276 return (U << 4) | T;
3279 switch (X(tparam.mod, t.mod))
3281 case X(0, 0):
3282 case X(0, MODFlags.const_):
3283 case X(0, MODFlags.wild):
3284 case X(0, MODFlags.wildconst):
3285 case X(0, MODFlags.shared_):
3286 case X(0, MODFlags.shared_ | MODFlags.const_):
3287 case X(0, MODFlags.shared_ | MODFlags.wild):
3288 case X(0, MODFlags.shared_ | MODFlags.wildconst):
3289 case X(0, MODFlags.immutable_):
3290 // foo(U) T => T
3291 // foo(U) const(T) => const(T)
3292 // foo(U) inout(T) => inout(T)
3293 // foo(U) inout(const(T)) => inout(const(T))
3294 // foo(U) shared(T) => shared(T)
3295 // foo(U) shared(const(T)) => shared(const(T))
3296 // foo(U) shared(inout(T)) => shared(inout(T))
3297 // foo(U) shared(inout(const(T))) => shared(inout(const(T)))
3298 // foo(U) immutable(T) => immutable(T)
3300 *at = t;
3301 return MATCH.exact;
3303 case X(MODFlags.const_, MODFlags.const_):
3304 case X(MODFlags.wild, MODFlags.wild):
3305 case X(MODFlags.wildconst, MODFlags.wildconst):
3306 case X(MODFlags.shared_, MODFlags.shared_):
3307 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.const_):
3308 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3309 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3310 case X(MODFlags.immutable_, MODFlags.immutable_):
3311 // foo(const(U)) const(T) => T
3312 // foo(inout(U)) inout(T) => T
3313 // foo(inout(const(U))) inout(const(T)) => T
3314 // foo(shared(U)) shared(T) => T
3315 // foo(shared(const(U))) shared(const(T)) => T
3316 // foo(shared(inout(U))) shared(inout(T)) => T
3317 // foo(shared(inout(const(U)))) shared(inout(const(T))) => T
3318 // foo(immutable(U)) immutable(T) => T
3320 *at = t.mutableOf().unSharedOf();
3321 return MATCH.exact;
3323 case X(MODFlags.const_, MODFlags.shared_ | MODFlags.const_):
3324 case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wild):
3325 case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst):
3326 // foo(const(U)) shared(const(T)) => shared(T)
3327 // foo(inout(U)) shared(inout(T)) => shared(T)
3328 // foo(inout(const(U))) shared(inout(const(T))) => shared(T)
3330 *at = t.mutableOf();
3331 return MATCH.exact;
3333 case X(MODFlags.const_, 0):
3334 case X(MODFlags.const_, MODFlags.wild):
3335 case X(MODFlags.const_, MODFlags.wildconst):
3336 case X(MODFlags.const_, MODFlags.shared_ | MODFlags.wild):
3337 case X(MODFlags.const_, MODFlags.shared_ | MODFlags.wildconst):
3338 case X(MODFlags.const_, MODFlags.immutable_):
3339 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.immutable_):
3340 // foo(const(U)) T => T
3341 // foo(const(U)) inout(T) => T
3342 // foo(const(U)) inout(const(T)) => T
3343 // foo(const(U)) shared(inout(T)) => shared(T)
3344 // foo(const(U)) shared(inout(const(T))) => shared(T)
3345 // foo(const(U)) immutable(T) => T
3346 // foo(shared(const(U))) immutable(T) => T
3348 *at = t.mutableOf();
3349 return MATCH.constant;
3351 case X(MODFlags.const_, MODFlags.shared_):
3352 // foo(const(U)) shared(T) => shared(T)
3354 *at = t;
3355 return MATCH.constant;
3357 case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.const_):
3358 case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wild):
3359 case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wildconst):
3360 // foo(shared(U)) shared(const(T)) => const(T)
3361 // foo(shared(U)) shared(inout(T)) => inout(T)
3362 // foo(shared(U)) shared(inout(const(T))) => inout(const(T))
3364 *at = t.unSharedOf();
3365 return MATCH.exact;
3367 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_):
3368 // foo(shared(const(U))) shared(T) => T
3370 *at = t.unSharedOf();
3371 return MATCH.constant;
3373 case X(MODFlags.wildconst, MODFlags.immutable_):
3374 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.wildconst):
3375 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.immutable_):
3376 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3377 // foo(inout(const(U))) immutable(T) => T
3378 // foo(shared(const(U))) shared(inout(const(T))) => T
3379 // foo(shared(inout(const(U)))) immutable(T) => T
3380 // foo(shared(inout(const(U)))) shared(inout(T)) => T
3382 *at = t.unSharedOf().mutableOf();
3383 return MATCH.constant;
3385 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_ | MODFlags.wild):
3386 // foo(shared(const(U))) shared(inout(T)) => T
3388 *at = t.unSharedOf().mutableOf();
3389 return MATCH.constant;
3391 case X(MODFlags.wild, 0):
3392 case X(MODFlags.wild, MODFlags.const_):
3393 case X(MODFlags.wild, MODFlags.wildconst):
3394 case X(MODFlags.wild, MODFlags.immutable_):
3395 case X(MODFlags.wild, MODFlags.shared_):
3396 case X(MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3397 case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3398 case X(MODFlags.wildconst, 0):
3399 case X(MODFlags.wildconst, MODFlags.const_):
3400 case X(MODFlags.wildconst, MODFlags.wild):
3401 case X(MODFlags.wildconst, MODFlags.shared_):
3402 case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3403 case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wild):
3404 case X(MODFlags.shared_, 0):
3405 case X(MODFlags.shared_, MODFlags.const_):
3406 case X(MODFlags.shared_, MODFlags.wild):
3407 case X(MODFlags.shared_, MODFlags.wildconst):
3408 case X(MODFlags.shared_, MODFlags.immutable_):
3409 case X(MODFlags.shared_ | MODFlags.const_, 0):
3410 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.const_):
3411 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.wild):
3412 case X(MODFlags.shared_ | MODFlags.const_, MODFlags.wildconst):
3413 case X(MODFlags.shared_ | MODFlags.wild, 0):
3414 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.const_):
3415 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.wild):
3416 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.wildconst):
3417 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.immutable_):
3418 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_):
3419 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.const_):
3420 case X(MODFlags.shared_ | MODFlags.wild, MODFlags.shared_ | MODFlags.wildconst):
3421 case X(MODFlags.shared_ | MODFlags.wildconst, 0):
3422 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.const_):
3423 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.wild):
3424 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.wildconst):
3425 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_):
3426 case X(MODFlags.shared_ | MODFlags.wildconst, MODFlags.shared_ | MODFlags.const_):
3427 case X(MODFlags.immutable_, 0):
3428 case X(MODFlags.immutable_, MODFlags.const_):
3429 case X(MODFlags.immutable_, MODFlags.wild):
3430 case X(MODFlags.immutable_, MODFlags.wildconst):
3431 case X(MODFlags.immutable_, MODFlags.shared_):
3432 case X(MODFlags.immutable_, MODFlags.shared_ | MODFlags.const_):
3433 case X(MODFlags.immutable_, MODFlags.shared_ | MODFlags.wild):
3434 case X(MODFlags.immutable_, MODFlags.shared_ | MODFlags.wildconst):
3435 // foo(inout(U)) T => nomatch
3436 // foo(inout(U)) const(T) => nomatch
3437 // foo(inout(U)) inout(const(T)) => nomatch
3438 // foo(inout(U)) immutable(T) => nomatch
3439 // foo(inout(U)) shared(T) => nomatch
3440 // foo(inout(U)) shared(const(T)) => nomatch
3441 // foo(inout(U)) shared(inout(const(T))) => nomatch
3442 // foo(inout(const(U))) T => nomatch
3443 // foo(inout(const(U))) const(T) => nomatch
3444 // foo(inout(const(U))) inout(T) => nomatch
3445 // foo(inout(const(U))) shared(T) => nomatch
3446 // foo(inout(const(U))) shared(const(T)) => nomatch
3447 // foo(inout(const(U))) shared(inout(T)) => nomatch
3448 // foo(shared(U)) T => nomatch
3449 // foo(shared(U)) const(T) => nomatch
3450 // foo(shared(U)) inout(T) => nomatch
3451 // foo(shared(U)) inout(const(T)) => nomatch
3452 // foo(shared(U)) immutable(T) => nomatch
3453 // foo(shared(const(U))) T => nomatch
3454 // foo(shared(const(U))) const(T) => nomatch
3455 // foo(shared(const(U))) inout(T) => nomatch
3456 // foo(shared(const(U))) inout(const(T)) => nomatch
3457 // foo(shared(inout(U))) T => nomatch
3458 // foo(shared(inout(U))) const(T) => nomatch
3459 // foo(shared(inout(U))) inout(T) => nomatch
3460 // foo(shared(inout(U))) inout(const(T)) => nomatch
3461 // foo(shared(inout(U))) immutable(T) => nomatch
3462 // foo(shared(inout(U))) shared(T) => nomatch
3463 // foo(shared(inout(U))) shared(const(T)) => nomatch
3464 // foo(shared(inout(U))) shared(inout(const(T))) => nomatch
3465 // foo(shared(inout(const(U)))) T => nomatch
3466 // foo(shared(inout(const(U)))) const(T) => nomatch
3467 // foo(shared(inout(const(U)))) inout(T) => nomatch
3468 // foo(shared(inout(const(U)))) inout(const(T)) => nomatch
3469 // foo(shared(inout(const(U)))) shared(T) => nomatch
3470 // foo(shared(inout(const(U)))) shared(const(T)) => nomatch
3471 // foo(immutable(U)) T => nomatch
3472 // foo(immutable(U)) const(T) => nomatch
3473 // foo(immutable(U)) inout(T) => nomatch
3474 // foo(immutable(U)) inout(const(T)) => nomatch
3475 // foo(immutable(U)) shared(T) => nomatch
3476 // foo(immutable(U)) shared(const(T)) => nomatch
3477 // foo(immutable(U)) shared(inout(T)) => nomatch
3478 // foo(immutable(U)) shared(inout(const(T))) => nomatch
3479 return MATCH.nomatch;
3481 default:
3482 assert(0);
3486 __gshared Expression emptyArrayElement = null;
3488 /* These form the heart of template argument deduction.
3489 * Given 'this' being the type argument to the template instance,
3490 * it is matched against the template declaration parameter specialization
3491 * 'tparam' to determine the type to be used for the parameter.
3492 * Example:
3493 * template Foo(T:T*) // template declaration
3494 * Foo!(int*) // template instantiation
3495 * Input:
3496 * this = int*
3497 * tparam = T*
3498 * parameters = [ T:T* ] // Array of TemplateParameter's
3499 * Output:
3500 * dedtypes = [ int ] // Array of Expression/Type's
3502 MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm = null, size_t inferStart = 0, bool ignoreAliasThis = false)
3504 extern (C++) final class DeduceType : Visitor
3506 alias visit = Visitor.visit;
3507 public:
3508 Scope* sc;
3509 Type tparam;
3510 TemplateParameters* parameters;
3511 Objects* dedtypes;
3512 uint* wm;
3513 size_t inferStart;
3514 bool ignoreAliasThis;
3515 MATCH result;
3517 extern (D) this(Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, uint* wm, size_t inferStart, bool ignoreAliasThis) @safe
3519 this.sc = sc;
3520 this.tparam = tparam;
3521 this.parameters = parameters;
3522 this.dedtypes = dedtypes;
3523 this.wm = wm;
3524 this.inferStart = inferStart;
3525 this.ignoreAliasThis = ignoreAliasThis;
3526 result = MATCH.nomatch;
3529 override void visit(Type t)
3531 if (!tparam)
3532 goto Lnomatch;
3534 if (t == tparam)
3535 goto Lexact;
3537 if (tparam.ty == Tident)
3539 // Determine which parameter tparam is
3540 size_t i = templateParameterLookup(tparam, parameters);
3541 if (i == IDX_NOTFOUND)
3543 if (!sc)
3544 goto Lnomatch;
3546 /* Need a loc to go with the semantic routine.
3548 Loc loc;
3549 if (parameters.length)
3551 TemplateParameter tp = (*parameters)[0];
3552 loc = tp.loc;
3555 /* BUG: what if tparam is a template instance, that
3556 * has as an argument another Tident?
3558 tparam = tparam.typeSemantic(loc, sc);
3559 assert(tparam.ty != Tident);
3560 result = deduceType(t, sc, tparam, parameters, dedtypes, wm);
3561 return;
3564 TemplateParameter tp = (*parameters)[i];
3566 TypeIdentifier tident = cast(TypeIdentifier)tparam;
3567 if (tident.idents.length > 0)
3569 //printf("matching %s to %s\n", tparam.toChars(), t.toChars());
3570 Dsymbol s = t.toDsymbol(sc);
3571 for (size_t j = tident.idents.length; j-- > 0;)
3573 RootObject id = tident.idents[j];
3574 if (id.dyncast() == DYNCAST.identifier)
3576 if (!s || !s.parent)
3577 goto Lnomatch;
3578 Dsymbol s2 = s.parent.search(Loc.initial, cast(Identifier)id);
3579 if (!s2)
3580 goto Lnomatch;
3581 s2 = s2.toAlias();
3582 //printf("[%d] s = %s %s, s2 = %s %s\n", j, s.kind(), s.toChars(), s2.kind(), s2.toChars());
3583 if (s != s2)
3585 if (Type tx = s2.getType())
3587 if (s != tx.toDsymbol(sc))
3588 goto Lnomatch;
3590 else
3591 goto Lnomatch;
3593 s = s.parent;
3595 else
3596 goto Lnomatch;
3598 //printf("[e] s = %s\n", s?s.toChars():"(null)");
3599 if (tp.isTemplateTypeParameter())
3601 Type tt = s.getType();
3602 if (!tt)
3603 goto Lnomatch;
3604 Type at = cast(Type)(*dedtypes)[i];
3605 if (at && at.ty == Tnone)
3606 at = (cast(TypeDeduced)at).tded;
3607 if (!at || tt.equals(at))
3609 (*dedtypes)[i] = tt;
3610 goto Lexact;
3613 if (tp.isTemplateAliasParameter())
3615 Dsymbol s2 = cast(Dsymbol)(*dedtypes)[i];
3616 if (!s2 || s == s2)
3618 (*dedtypes)[i] = s;
3619 goto Lexact;
3622 goto Lnomatch;
3625 // Found the corresponding parameter tp
3627 https://issues.dlang.org/show_bug.cgi?id=23578
3628 To pattern match:
3629 static if (is(S!int == S!av, alias av))
3631 We eventually need to deduce `int` (Tint32 [0]) and `av` (Tident).
3632 Previously this would not get pattern matched at all, but now we check if the
3633 template parameter `av` came from.
3635 This note has been left to serve as a hint for further explorers into
3636 how IsExp matching works.
3638 if (auto ta = tp.isTemplateAliasParameter())
3640 (*dedtypes)[i] = t;
3641 goto Lexact;
3643 // (23578) - ensure previous behaviour for non-alias template params
3644 if (!tp.isTemplateTypeParameter())
3646 goto Lnomatch;
3649 Type at = cast(Type)(*dedtypes)[i];
3650 Type tt;
3651 if (ubyte wx = wm ? deduceWildHelper(t, &tt, tparam) : 0)
3653 // type vs (none)
3654 if (!at)
3656 (*dedtypes)[i] = tt;
3657 *wm |= wx;
3658 result = MATCH.constant;
3659 return;
3662 // type vs expressions
3663 if (at.ty == Tnone)
3665 TypeDeduced xt = cast(TypeDeduced)at;
3666 result = xt.matchAll(tt);
3667 if (result > MATCH.nomatch)
3669 (*dedtypes)[i] = tt;
3670 if (result > MATCH.constant)
3671 result = MATCH.constant; // limit level for inout matches
3673 return;
3676 // type vs type
3677 if (tt.equals(at))
3679 (*dedtypes)[i] = tt; // Prefer current type match
3680 goto Lconst;
3682 if (tt.implicitConvTo(at.constOf()))
3684 (*dedtypes)[i] = at.constOf().mutableOf();
3685 *wm |= MODFlags.const_;
3686 goto Lconst;
3688 if (at.implicitConvTo(tt.constOf()))
3690 (*dedtypes)[i] = tt.constOf().mutableOf();
3691 *wm |= MODFlags.const_;
3692 goto Lconst;
3694 goto Lnomatch;
3696 else if (MATCH m = deduceTypeHelper(t, &tt, tparam))
3698 // type vs (none)
3699 if (!at)
3701 (*dedtypes)[i] = tt;
3702 result = m;
3703 return;
3706 // type vs expressions
3707 if (at.ty == Tnone)
3709 TypeDeduced xt = cast(TypeDeduced)at;
3710 result = xt.matchAll(tt);
3711 if (result > MATCH.nomatch)
3713 (*dedtypes)[i] = tt;
3715 return;
3718 // type vs type
3719 if (tt.equals(at))
3721 goto Lexact;
3723 if (tt.ty == Tclass && at.ty == Tclass)
3725 result = tt.implicitConvTo(at);
3726 return;
3728 if (tt.ty == Tsarray && at.ty == Tarray && tt.nextOf().implicitConvTo(at.nextOf()) >= MATCH.constant)
3730 goto Lexact;
3733 goto Lnomatch;
3736 if (tparam.ty == Ttypeof)
3738 /* Need a loc to go with the semantic routine.
3740 Loc loc;
3741 if (parameters.length)
3743 TemplateParameter tp = (*parameters)[0];
3744 loc = tp.loc;
3747 tparam = tparam.typeSemantic(loc, sc);
3749 if (t.ty != tparam.ty)
3751 if (Dsymbol sym = t.toDsymbol(sc))
3753 if (sym.isforwardRef() && !tparam.deco)
3754 goto Lnomatch;
3757 MATCH m = t.implicitConvTo(tparam);
3758 if (m == MATCH.nomatch && !ignoreAliasThis)
3760 if (t.ty == Tclass)
3762 TypeClass tc = cast(TypeClass)t;
3763 if (tc.sym.aliasthis && !(tc.att & AliasThisRec.tracingDT))
3765 if (auto ato = t.aliasthisOf())
3767 tc.att = cast(AliasThisRec)(tc.att | AliasThisRec.tracingDT);
3768 m = deduceType(ato, sc, tparam, parameters, dedtypes, wm);
3769 tc.att = cast(AliasThisRec)(tc.att & ~AliasThisRec.tracingDT);
3773 else if (t.ty == Tstruct)
3775 TypeStruct ts = cast(TypeStruct)t;
3776 if (ts.sym.aliasthis && !(ts.att & AliasThisRec.tracingDT))
3778 if (auto ato = t.aliasthisOf())
3780 ts.att = cast(AliasThisRec)(ts.att | AliasThisRec.tracingDT);
3781 m = deduceType(ato, sc, tparam, parameters, dedtypes, wm);
3782 ts.att = cast(AliasThisRec)(ts.att & ~AliasThisRec.tracingDT);
3787 result = m;
3788 return;
3791 if (t.nextOf())
3793 if (tparam.deco && !tparam.hasWild())
3795 result = t.implicitConvTo(tparam);
3796 return;
3799 Type tpn = tparam.nextOf();
3800 if (wm && t.ty == Taarray && tparam.isWild())
3802 // https://issues.dlang.org/show_bug.cgi?id=12403
3803 // In IFTI, stop inout matching on transitive part of AA types.
3804 tpn = tpn.substWildTo(MODFlags.mutable);
3807 result = deduceType(t.nextOf(), sc, tpn, parameters, dedtypes, wm);
3808 return;
3811 Lexact:
3812 result = MATCH.exact;
3813 return;
3815 Lnomatch:
3816 result = MATCH.nomatch;
3817 return;
3819 Lconst:
3820 result = MATCH.constant;
3823 override void visit(TypeVector t)
3825 if (tparam.ty == Tvector)
3827 TypeVector tp = cast(TypeVector)tparam;
3828 result = deduceType(t.basetype, sc, tp.basetype, parameters, dedtypes, wm);
3829 return;
3831 visit(cast(Type)t);
3834 override void visit(TypeDArray t)
3836 visit(cast(Type)t);
3839 override void visit(TypeSArray t)
3841 // Extra check that array dimensions must match
3842 if (tparam)
3844 if (tparam.ty == Tarray)
3846 MATCH m = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
3847 result = (m >= MATCH.constant) ? MATCH.convert : MATCH.nomatch;
3848 return;
3851 TemplateParameter tp = null;
3852 Expression edim = null;
3853 size_t i;
3854 if (tparam.ty == Tsarray)
3856 TypeSArray tsa = cast(TypeSArray)tparam;
3857 if (tsa.dim.isVarExp() && tsa.dim.isVarExp().var.storage_class & STC.templateparameter)
3859 Identifier id = tsa.dim.isVarExp().var.ident;
3860 i = templateIdentifierLookup(id, parameters);
3861 assert(i != IDX_NOTFOUND);
3862 tp = (*parameters)[i];
3864 else
3865 edim = tsa.dim;
3867 else if (tparam.ty == Taarray)
3869 TypeAArray taa = cast(TypeAArray)tparam;
3870 i = templateParameterLookup(taa.index, parameters);
3871 if (i != IDX_NOTFOUND)
3872 tp = (*parameters)[i];
3873 else
3875 Loc loc;
3876 // The "type" (it hasn't been resolved yet) of the function parameter
3877 // does not have a location but the parameter it is related to does,
3878 // so we use that for the resolution (better error message).
3879 if (inferStart < parameters.length)
3881 TemplateParameter loctp = (*parameters)[inferStart];
3882 loc = loctp.loc;
3885 Expression e;
3886 Type tx;
3887 Dsymbol s;
3888 taa.index.resolve(loc, sc, e, tx, s);
3889 edim = s ? getValue(s) : getValue(e);
3892 if (tp && tp.matchArg(sc, t.dim, i, parameters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger())
3894 result = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm);
3895 return;
3898 visit(cast(Type)t);
3901 override void visit(TypeAArray t)
3903 // Extra check that index type must match
3904 if (tparam && tparam.ty == Taarray)
3906 TypeAArray tp = cast(TypeAArray)tparam;
3907 if (!deduceType(t.index, sc, tp.index, parameters, dedtypes))
3909 result = MATCH.nomatch;
3910 return;
3913 visit(cast(Type)t);
3916 override void visit(TypeFunction t)
3918 // Extra check that function characteristics must match
3919 if (!tparam)
3920 return visit(cast(Type)t);
3922 if (auto tp = tparam.isTypeFunction())
3924 if (t.parameterList.varargs != tp.parameterList.varargs || t.linkage != tp.linkage)
3926 result = MATCH.nomatch;
3927 return;
3930 foreach (fparam; *tp.parameterList.parameters)
3932 // https://issues.dlang.org/show_bug.cgi?id=2579
3933 // Apply function parameter storage classes to parameter types
3934 fparam.type = fparam.type.addStorageClass(fparam.storageClass);
3935 fparam.storageClass &= ~STC.TYPECTOR;
3937 // https://issues.dlang.org/show_bug.cgi?id=15243
3938 // Resolve parameter type if it's not related with template parameters
3939 if (!reliesOnTemplateParameters(fparam.type, (*parameters)[inferStart .. parameters.length]))
3941 auto tx = fparam.type.typeSemantic(Loc.initial, sc);
3942 if (tx.ty == Terror)
3944 result = MATCH.nomatch;
3945 return;
3947 fparam.type = tx;
3951 size_t nfargs = t.parameterList.length;
3952 size_t nfparams = tp.parameterList.length;
3954 /* See if tuple match
3956 if (nfparams > 0 && nfargs >= nfparams - 1)
3958 /* See if 'A' of the template parameter matches 'A'
3959 * of the type of the last function parameter.
3961 Parameter fparam = tp.parameterList[nfparams - 1];
3962 assert(fparam);
3963 assert(fparam.type);
3964 if (fparam.type.ty != Tident)
3965 goto L1;
3966 TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
3967 if (tid.idents.length)
3968 goto L1;
3970 /* Look through parameters to find tuple matching tid.ident
3972 size_t tupi = 0;
3973 for (; 1; tupi++)
3975 if (tupi == parameters.length)
3976 goto L1;
3977 TemplateParameter tx = (*parameters)[tupi];
3978 TemplateTupleParameter tup = tx.isTemplateTupleParameter();
3979 if (tup && tup.ident.equals(tid.ident))
3980 break;
3983 /* The types of the function arguments [nfparams - 1 .. nfargs]
3984 * now form the tuple argument.
3986 size_t tuple_dim = nfargs - (nfparams - 1);
3988 /* See if existing tuple, and whether it matches or not
3990 RootObject o = (*dedtypes)[tupi];
3991 if (o)
3993 // Existing deduced argument must be a tuple, and must match
3994 Tuple tup = isTuple(o);
3995 if (!tup || tup.objects.length != tuple_dim)
3997 result = MATCH.nomatch;
3998 return;
4000 for (size_t i = 0; i < tuple_dim; i++)
4002 Parameter arg = t.parameterList[nfparams - 1 + i];
4003 if (!arg.type.equals(tup.objects[i]))
4005 result = MATCH.nomatch;
4006 return;
4010 else
4012 // Create new tuple
4013 auto tup = new Tuple(tuple_dim);
4014 for (size_t i = 0; i < tuple_dim; i++)
4016 Parameter arg = t.parameterList[nfparams - 1 + i];
4017 tup.objects[i] = arg.type;
4019 (*dedtypes)[tupi] = tup;
4021 nfparams--; // don't consider the last parameter for type deduction
4022 goto L2;
4026 if (nfargs != nfparams)
4028 result = MATCH.nomatch;
4029 return;
4032 assert(nfparams <= tp.parameterList.length);
4033 foreach (i, ap; tp.parameterList)
4035 if (i == nfparams)
4036 break;
4038 Parameter a = t.parameterList[i];
4040 if (!a.isCovariant(t.isref, ap) ||
4041 !deduceType(a.type, sc, ap.type, parameters, dedtypes))
4043 result = MATCH.nomatch;
4044 return;
4048 visit(cast(Type)t);
4051 override void visit(TypeIdentifier t)
4053 // Extra check
4054 if (tparam && tparam.ty == Tident)
4056 TypeIdentifier tp = cast(TypeIdentifier)tparam;
4057 for (size_t i = 0; i < t.idents.length; i++)
4059 RootObject id1 = t.idents[i];
4060 RootObject id2 = tp.idents[i];
4061 if (!id1.equals(id2))
4063 result = MATCH.nomatch;
4064 return;
4068 visit(cast(Type)t);
4071 override void visit(TypeInstance t)
4073 // Extra check
4074 if (tparam && tparam.ty == Tinstance && t.tempinst.tempdecl)
4076 TemplateDeclaration tempdecl = t.tempinst.tempdecl.isTemplateDeclaration();
4077 assert(tempdecl);
4079 TypeInstance tp = cast(TypeInstance)tparam;
4081 //printf("tempinst.tempdecl = %p\n", tempdecl);
4082 //printf("tp.tempinst.tempdecl = %p\n", tp.tempinst.tempdecl);
4083 if (!tp.tempinst.tempdecl)
4085 //printf("tp.tempinst.name = '%s'\n", tp.tempinst.name.toChars());
4087 /* Handle case of:
4088 * template Foo(T : sa!(T), alias sa)
4090 size_t i = templateIdentifierLookup(tp.tempinst.name, parameters);
4091 if (i == IDX_NOTFOUND)
4093 /* Didn't find it as a parameter identifier. Try looking
4094 * it up and seeing if is an alias.
4095 * https://issues.dlang.org/show_bug.cgi?id=1454
4097 auto tid = new TypeIdentifier(tp.loc, tp.tempinst.name);
4098 Type tx;
4099 Expression e;
4100 Dsymbol s;
4101 tid.resolve(tp.loc, sc, e, tx, s);
4102 if (tx)
4104 s = tx.toDsymbol(sc);
4105 if (TemplateInstance ti = s ? s.parent.isTemplateInstance() : null)
4107 // https://issues.dlang.org/show_bug.cgi?id=14290
4108 // Try to match with ti.tempecl,
4109 // only when ti is an enclosing instance.
4110 Dsymbol p = sc.parent;
4111 while (p && p != ti)
4112 p = p.parent;
4113 if (p)
4114 s = ti.tempdecl;
4117 if (s)
4119 s = s.toAlias();
4120 TemplateDeclaration td = s.isTemplateDeclaration();
4121 if (td)
4123 if (td.overroot)
4124 td = td.overroot;
4125 for (; td; td = td.overnext)
4127 if (td == tempdecl)
4128 goto L2;
4132 goto Lnomatch;
4135 TemplateParameter tpx = (*parameters)[i];
4136 if (!tpx.matchArg(sc, tempdecl, i, parameters, dedtypes, null))
4137 goto Lnomatch;
4139 else if (tempdecl != tp.tempinst.tempdecl)
4140 goto Lnomatch;
4143 if (!resolveTemplateInstantiation(t.tempinst.tiargs, &t.tempinst.tdtypes, tempdecl, tp, dedtypes))
4144 goto Lnomatch;
4146 visit(cast(Type)t);
4147 return;
4149 Lnomatch:
4150 //printf("no match\n");
4151 result = MATCH.nomatch;
4154 /********************
4155 * Match template `parameters` to the target template instance.
4156 * Example:
4157 * struct Temp(U, int Z) {}
4158 * void foo(T)(Temp!(T, 3));
4159 * foo(Temp!(int, 3)());
4160 * Input:
4161 * this.parameters = template params of foo -> [T]
4162 * tiargs = <Temp!(int, 3)>.tiargs -> [int, 3]
4163 * tdtypes = <Temp!(int, 3)>.tdtypes -> [int, 3]
4164 * tempdecl = <struct Temp!(T, int Z)> -> [T, Z]
4165 * tp = <Temp!(T, 3)>
4166 * Output:
4167 * dedtypes = deduced params of `foo(Temp!(int, 3)())` -> [int]
4169 private bool resolveTemplateInstantiation(Objects* tiargs, Objects* tdtypes, TemplateDeclaration tempdecl, TypeInstance tp, Objects* dedtypes)
4171 for (size_t i = 0; 1; i++)
4173 //printf("\ttest: tempinst.tiargs[%zu]\n", i);
4174 RootObject o1 = null;
4175 if (i < tiargs.length)
4176 o1 = (*tiargs)[i];
4177 else if (i < tdtypes.length && i < tp.tempinst.tiargs.length)
4179 // Pick up default arg
4180 o1 = (*tdtypes)[i];
4182 else if (i >= tp.tempinst.tiargs.length)
4183 break;
4184 //printf("\ttest: o1 = %s\n", o1.toChars());
4185 if (i >= tp.tempinst.tiargs.length)
4187 size_t dim = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
4188 while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
4190 i++;
4192 if (i >= dim)
4193 break; // match if all remained parameters are dependent
4194 return false;
4197 RootObject o2 = (*tp.tempinst.tiargs)[i];
4198 Type t2 = isType(o2);
4199 //printf("\ttest: o2 = %s\n", o2.toChars());
4200 size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.length - 1)
4201 ? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
4202 if (j != IDX_NOTFOUND && j == parameters.length - 1 &&
4203 (*parameters)[j].isTemplateTupleParameter())
4205 /* Given:
4206 * struct A(B...) {}
4207 * alias A!(int, float) X;
4208 * static if (is(X Y == A!(Z), Z...)) {}
4209 * deduce that Z is a tuple(int, float)
4212 /* Create tuple from remaining args
4214 size_t vtdim = (tempdecl.isVariadic() ? tiargs.length : tdtypes.length) - i;
4215 auto vt = new Tuple(vtdim);
4216 for (size_t k = 0; k < vtdim; k++)
4218 RootObject o;
4219 if (k < tiargs.length)
4220 o = (*tiargs)[i + k];
4221 else // Pick up default arg
4222 o = (*tdtypes)[i + k];
4223 vt.objects[k] = o;
4226 Tuple v = cast(Tuple)(*dedtypes)[j];
4227 if (v)
4229 if (!match(v, vt))
4230 return false;
4232 else
4233 (*dedtypes)[j] = vt;
4234 break;
4236 else if (!o1)
4237 break;
4239 Type t1 = isType(o1);
4240 Dsymbol s1 = isDsymbol(o1);
4241 Dsymbol s2 = isDsymbol(o2);
4242 Expression e1 = s1 ? getValue(s1) : getValue(isExpression(o1));
4243 Expression e2 = isExpression(o2);
4244 version (none)
4246 Tuple v1 = isTuple(o1);
4247 Tuple v2 = isTuple(o2);
4248 if (t1)
4249 printf("t1 = %s\n", t1.toChars());
4250 if (t2)
4251 printf("t2 = %s\n", t2.toChars());
4252 if (e1)
4253 printf("e1 = %s\n", e1.toChars());
4254 if (e2)
4255 printf("e2 = %s\n", e2.toChars());
4256 if (s1)
4257 printf("s1 = %s\n", s1.toChars());
4258 if (s2)
4259 printf("s2 = %s\n", s2.toChars());
4260 if (v1)
4261 printf("v1 = %s\n", v1.toChars());
4262 if (v2)
4263 printf("v2 = %s\n", v2.toChars());
4266 if (t1 && t2)
4268 if (!deduceType(t1, sc, t2, parameters, dedtypes))
4269 return false;
4271 else if (e1 && e2)
4274 e1 = e1.ctfeInterpret();
4276 /* If it is one of the template parameters for this template,
4277 * we should not attempt to interpret it. It already has a value.
4279 if (e2.op == EXP.variable && (e2.isVarExp().var.storage_class & STC.templateparameter))
4282 * (T:Number!(e2), int e2)
4284 j = templateIdentifierLookup(e2.isVarExp().var.ident, parameters);
4285 if (j != IDX_NOTFOUND)
4286 goto L1;
4287 // The template parameter was not from this template
4288 // (it may be from a parent template, for example)
4291 e2 = e2.expressionSemantic(sc); // https://issues.dlang.org/show_bug.cgi?id=13417
4292 e2 = e2.ctfeInterpret();
4294 //printf("e1 = %s, type = %s %d\n", e1.toChars(), e1.type.toChars(), e1.type.ty);
4295 //printf("e2 = %s, type = %s %d\n", e2.toChars(), e2.type.toChars(), e2.type.ty);
4296 if (!e1.equals(e2))
4298 if (!e2.implicitConvTo(e1.type))
4299 return false;
4301 e2 = e2.implicitCastTo(sc, e1.type);
4302 e2 = e2.ctfeInterpret();
4303 if (!e1.equals(e2))
4304 return false;
4307 else if (e1 && t2 && t2.ty == Tident)
4309 j = templateParameterLookup(t2, parameters);
4311 if (j == IDX_NOTFOUND)
4313 t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
4314 if (e2)
4315 goto Le;
4316 return false;
4318 if (!(*parameters)[j].matchArg(sc, e1, j, parameters, dedtypes, null))
4319 return false;
4321 else if (s1 && s2)
4324 if (!s1.equals(s2))
4325 return false;
4327 else if (s1 && t2 && t2.ty == Tident)
4329 j = templateParameterLookup(t2, parameters);
4330 if (j == IDX_NOTFOUND)
4332 t2.resolve((cast(TypeIdentifier)t2).loc, sc, e2, t2, s2);
4333 if (s2)
4334 goto Ls;
4335 return false;
4337 if (!(*parameters)[j].matchArg(sc, s1, j, parameters, dedtypes, null))
4338 return false;
4340 else
4341 return false;
4343 return true;
4346 override void visit(TypeStruct t)
4348 /* If this struct is a template struct, and we're matching
4349 * it against a template instance, convert the struct type
4350 * to a template instance, too, and try again.
4352 TemplateInstance ti = t.sym.parent.isTemplateInstance();
4354 if (tparam && tparam.ty == Tinstance)
4356 if (ti && ti.toAlias() == t.sym)
4358 auto tx = new TypeInstance(Loc.initial, ti);
4359 auto m = deduceType(tx, sc, tparam, parameters, dedtypes, wm);
4360 // if we have a no match we still need to check alias this
4361 if (m != MATCH.nomatch)
4363 result = m;
4364 return;
4368 /* Match things like:
4369 * S!(T).foo
4371 TypeInstance tpi = cast(TypeInstance)tparam;
4372 if (tpi.idents.length)
4374 RootObject id = tpi.idents[tpi.idents.length - 1];
4375 if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id))
4377 Type tparent = t.sym.parent.getType();
4378 if (tparent)
4380 /* Slice off the .foo in S!(T).foo
4382 tpi.idents.length--;
4383 result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
4384 tpi.idents.length++;
4385 return;
4391 // Extra check
4392 if (tparam && tparam.ty == Tstruct)
4394 TypeStruct tp = cast(TypeStruct)tparam;
4396 //printf("\t%d\n", cast(MATCH) t.implicitConvTo(tp));
4397 if (wm && t.deduceWild(tparam, false))
4399 result = MATCH.constant;
4400 return;
4402 result = t.implicitConvTo(tp);
4403 return;
4405 visit(cast(Type)t);
4408 override void visit(TypeEnum t)
4410 // Extra check
4411 if (tparam && tparam.ty == Tenum)
4413 TypeEnum tp = cast(TypeEnum)tparam;
4414 if (t.sym == tp.sym)
4415 visit(cast(Type)t);
4416 else
4417 result = MATCH.nomatch;
4418 return;
4420 Type tb = t.toBasetype();
4421 if (tb.ty == tparam.ty || tb.ty == Tsarray && tparam.ty == Taarray)
4423 result = deduceType(tb, sc, tparam, parameters, dedtypes, wm);
4424 if (result == MATCH.exact)
4425 result = MATCH.convert;
4426 return;
4428 visit(cast(Type)t);
4431 /* Helper for TypeClass.deduceType().
4432 * Classes can match with implicit conversion to a base class or interface.
4433 * This is complicated, because there may be more than one base class which
4434 * matches. In such cases, one or more parameters remain ambiguous.
4435 * For example,
4437 * interface I(X, Y) {}
4438 * class C : I(uint, double), I(char, double) {}
4439 * C x;
4440 * foo(T, U)( I!(T, U) x)
4442 * deduces that U is double, but T remains ambiguous (could be char or uint).
4444 * Given a baseclass b, and initial deduced types 'dedtypes', this function
4445 * tries to match tparam with b, and also tries all base interfaces of b.
4446 * If a match occurs, numBaseClassMatches is incremented, and the new deduced
4447 * types are ANDed with the current 'best' estimate for dedtypes.
4449 static void deduceBaseClassParameters(ref BaseClass b, Scope* sc, Type tparam, TemplateParameters* parameters, Objects* dedtypes, Objects* best, ref int numBaseClassMatches)
4451 TemplateInstance parti = b.sym ? b.sym.parent.isTemplateInstance() : null;
4452 if (parti)
4454 // Make a temporary copy of dedtypes so we don't destroy it
4455 auto tmpdedtypes = new Objects(dedtypes.length);
4456 memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.length * (void*).sizeof);
4458 auto t = new TypeInstance(Loc.initial, parti);
4459 MATCH m = deduceType(t, sc, tparam, parameters, tmpdedtypes);
4460 if (m > MATCH.nomatch)
4462 // If this is the first ever match, it becomes our best estimate
4463 if (numBaseClassMatches == 0)
4464 memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.length * (void*).sizeof);
4465 else
4466 for (size_t k = 0; k < tmpdedtypes.length; ++k)
4468 // If we've found more than one possible type for a parameter,
4469 // mark it as unknown.
4470 if ((*tmpdedtypes)[k] != (*best)[k])
4471 (*best)[k] = (*dedtypes)[k];
4473 ++numBaseClassMatches;
4477 // Now recursively test the inherited interfaces
4478 foreach (ref bi; b.baseInterfaces)
4480 deduceBaseClassParameters(bi, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4484 override void visit(TypeClass t)
4486 //printf("TypeClass.deduceType(this = %s)\n", t.toChars());
4488 /* If this class is a template class, and we're matching
4489 * it against a template instance, convert the class type
4490 * to a template instance, too, and try again.
4492 TemplateInstance ti = t.sym.parent.isTemplateInstance();
4494 if (tparam && tparam.ty == Tinstance)
4496 if (ti && ti.toAlias() == t.sym)
4498 auto tx = new TypeInstance(Loc.initial, ti);
4499 MATCH m = deduceType(tx, sc, tparam, parameters, dedtypes, wm);
4500 // Even if the match fails, there is still a chance it could match
4501 // a base class.
4502 if (m != MATCH.nomatch)
4504 result = m;
4505 return;
4509 /* Match things like:
4510 * S!(T).foo
4512 TypeInstance tpi = cast(TypeInstance)tparam;
4513 if (tpi.idents.length)
4515 RootObject id = tpi.idents[tpi.idents.length - 1];
4516 if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id))
4518 Type tparent = t.sym.parent.getType();
4519 if (tparent)
4521 /* Slice off the .foo in S!(T).foo
4523 tpi.idents.length--;
4524 result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
4525 tpi.idents.length++;
4526 return;
4531 // If it matches exactly or via implicit conversion, we're done
4532 visit(cast(Type)t);
4533 if (result != MATCH.nomatch)
4534 return;
4536 /* There is still a chance to match via implicit conversion to
4537 * a base class or interface. Because there could be more than one such
4538 * match, we need to check them all.
4541 int numBaseClassMatches = 0; // Have we found an interface match?
4543 // Our best guess at dedtypes
4544 auto best = new Objects(dedtypes.length);
4546 ClassDeclaration s = t.sym;
4547 while (s && s.baseclasses.length > 0)
4549 // Test the base class
4550 deduceBaseClassParameters(*(*s.baseclasses)[0], sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4552 // Test the interfaces inherited by the base class
4553 foreach (b; s.interfaces)
4555 deduceBaseClassParameters(*b, sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
4557 s = (*s.baseclasses)[0].sym;
4560 if (numBaseClassMatches == 0)
4562 result = MATCH.nomatch;
4563 return;
4566 // If we got at least one match, copy the known types into dedtypes
4567 memcpy(dedtypes.tdata(), best.tdata(), best.length * (void*).sizeof);
4568 result = MATCH.convert;
4569 return;
4572 // Extra check
4573 if (tparam && tparam.ty == Tclass)
4575 TypeClass tp = cast(TypeClass)tparam;
4577 //printf("\t%d\n", cast(MATCH) t.implicitConvTo(tp));
4578 if (wm && t.deduceWild(tparam, false))
4580 result = MATCH.constant;
4581 return;
4583 result = t.implicitConvTo(tp);
4584 return;
4586 visit(cast(Type)t);
4589 override void visit(Expression e)
4591 //printf("Expression.deduceType(e = %s)\n", e.toChars());
4592 size_t i = templateParameterLookup(tparam, parameters);
4593 if (i == IDX_NOTFOUND || (cast(TypeIdentifier)tparam).idents.length > 0)
4595 if (e == emptyArrayElement && tparam.ty == Tarray)
4597 Type tn = (cast(TypeNext)tparam).next;
4598 result = deduceType(emptyArrayElement, sc, tn, parameters, dedtypes, wm);
4599 return;
4601 e.type.accept(this);
4602 return;
4605 TemplateTypeParameter tp = (*parameters)[i].isTemplateTypeParameter();
4606 if (!tp)
4607 return; // nomatch
4609 if (e == emptyArrayElement)
4611 if ((*dedtypes)[i])
4613 result = MATCH.exact;
4614 return;
4616 if (tp.defaultType)
4618 tp.defaultType.accept(this);
4619 return;
4623 /* Returns `true` if `t` is a reference type, or an array of reference types
4625 bool isTopRef(Type t)
4627 auto tb = t.baseElemOf();
4628 return tb.ty == Tclass ||
4629 tb.ty == Taarray ||
4630 tb.ty == Tstruct && tb.hasPointers();
4633 Type at = cast(Type)(*dedtypes)[i];
4634 Type tt;
4635 if (ubyte wx = deduceWildHelper(e.type, &tt, tparam))
4637 *wm |= wx;
4638 result = MATCH.constant;
4640 else if (MATCH m = deduceTypeHelper(e.type, &tt, tparam))
4642 result = m;
4644 else if (!isTopRef(e.type))
4646 /* https://issues.dlang.org/show_bug.cgi?id=15653
4647 * In IFTI, recognize top-qualifier conversions
4648 * through the value copy, e.g.
4649 * int --> immutable(int)
4650 * immutable(string[]) --> immutable(string)[]
4652 tt = e.type.mutableOf();
4653 result = MATCH.convert;
4655 else
4656 return; // nomatch
4658 // expression vs (none)
4659 if (!at)
4661 (*dedtypes)[i] = new TypeDeduced(tt, e, tparam);
4662 return;
4665 TypeDeduced xt = null;
4666 if (at.ty == Tnone)
4668 xt = cast(TypeDeduced)at;
4669 at = xt.tded;
4672 // From previous matched expressions to current deduced type
4673 MATCH match1 = xt ? xt.matchAll(tt) : MATCH.nomatch;
4675 // From current expressions to previous deduced type
4676 Type pt = at.addMod(tparam.mod);
4677 if (*wm)
4678 pt = pt.substWildTo(*wm);
4679 MATCH match2 = e.implicitConvTo(pt);
4681 if (match1 > MATCH.nomatch && match2 > MATCH.nomatch)
4683 if (at.implicitConvTo(tt) == MATCH.nomatch)
4684 match1 = MATCH.nomatch; // Prefer at
4685 else if (tt.implicitConvTo(at) == MATCH.nomatch)
4686 match2 = MATCH.nomatch; // Prefer tt
4687 else if (tt.isTypeBasic() && tt.ty == at.ty && tt.mod != at.mod)
4689 if (!tt.isMutable() && !at.isMutable())
4690 tt = tt.mutableOf().addMod(MODmerge(tt.mod, at.mod));
4691 else if (tt.isMutable())
4693 if (at.mod == 0) // Prefer unshared
4694 match1 = MATCH.nomatch;
4695 else
4696 match2 = MATCH.nomatch;
4698 else if (at.isMutable())
4700 if (tt.mod == 0) // Prefer unshared
4701 match2 = MATCH.nomatch;
4702 else
4703 match1 = MATCH.nomatch;
4705 //printf("tt = %s, at = %s\n", tt.toChars(), at.toChars());
4707 else
4709 match1 = MATCH.nomatch;
4710 match2 = MATCH.nomatch;
4713 if (match1 > MATCH.nomatch)
4715 // Prefer current match: tt
4716 if (xt)
4717 xt.update(tt, e, tparam);
4718 else
4719 (*dedtypes)[i] = tt;
4720 result = match1;
4721 return;
4723 if (match2 > MATCH.nomatch)
4725 // Prefer previous match: (*dedtypes)[i]
4726 if (xt)
4727 xt.update(e, tparam);
4728 result = match2;
4729 return;
4732 /* Deduce common type
4734 if (Type t = rawTypeMerge(at, tt))
4736 if (xt)
4737 xt.update(t, e, tparam);
4738 else
4739 (*dedtypes)[i] = t;
4741 pt = tt.addMod(tparam.mod);
4742 if (*wm)
4743 pt = pt.substWildTo(*wm);
4744 result = e.implicitConvTo(pt);
4745 return;
4748 result = MATCH.nomatch;
4751 MATCH deduceEmptyArrayElement()
4753 if (!emptyArrayElement)
4755 emptyArrayElement = new IdentifierExp(Loc.initial, Id.p); // dummy
4756 emptyArrayElement.type = Type.tvoid;
4758 assert(tparam.ty == Tarray);
4760 Type tn = (cast(TypeNext)tparam).next;
4761 return deduceType(emptyArrayElement, sc, tn, parameters, dedtypes, wm);
4764 override void visit(NullExp e)
4766 if (tparam.ty == Tarray && e.type.ty == Tnull)
4768 // tparam:T[] <- e:null (void[])
4769 result = deduceEmptyArrayElement();
4770 return;
4772 visit(cast(Expression)e);
4775 override void visit(StringExp e)
4777 Type taai;
4778 if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
4780 // Consider compile-time known boundaries
4781 e.type.nextOf().sarrayOf(e.len).accept(this);
4782 return;
4784 visit(cast(Expression)e);
4787 override void visit(ArrayLiteralExp e)
4789 // https://issues.dlang.org/show_bug.cgi?id=20092
4790 if (e.elements && e.elements.length && e.type.toBasetype().nextOf().ty == Tvoid)
4792 result = deduceEmptyArrayElement();
4793 return;
4795 if ((!e.elements || !e.elements.length) && e.type.toBasetype().nextOf().ty == Tvoid && tparam.ty == Tarray)
4797 // tparam:T[] <- e:[] (void[])
4798 result = deduceEmptyArrayElement();
4799 return;
4802 if (tparam.ty == Tarray && e.elements && e.elements.length)
4804 Type tn = (cast(TypeDArray)tparam).next;
4805 result = MATCH.exact;
4806 if (e.basis)
4808 MATCH m = deduceType(e.basis, sc, tn, parameters, dedtypes, wm);
4809 if (m < result)
4810 result = m;
4812 foreach (el; *e.elements)
4814 if (result == MATCH.nomatch)
4815 break;
4816 if (!el)
4817 continue;
4818 MATCH m = deduceType(el, sc, tn, parameters, dedtypes, wm);
4819 if (m < result)
4820 result = m;
4822 return;
4825 Type taai;
4826 if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
4828 // Consider compile-time known boundaries
4829 e.type.nextOf().sarrayOf(e.elements.length).accept(this);
4830 return;
4832 visit(cast(Expression)e);
4835 override void visit(AssocArrayLiteralExp e)
4837 if (tparam.ty == Taarray && e.keys && e.keys.length)
4839 TypeAArray taa = cast(TypeAArray)tparam;
4840 result = MATCH.exact;
4841 foreach (i, key; *e.keys)
4843 MATCH m1 = deduceType(key, sc, taa.index, parameters, dedtypes, wm);
4844 if (m1 < result)
4845 result = m1;
4846 if (result == MATCH.nomatch)
4847 break;
4848 MATCH m2 = deduceType((*e.values)[i], sc, taa.next, parameters, dedtypes, wm);
4849 if (m2 < result)
4850 result = m2;
4851 if (result == MATCH.nomatch)
4852 break;
4854 return;
4856 visit(cast(Expression)e);
4859 override void visit(FuncExp e)
4861 //printf("e.type = %s, tparam = %s\n", e.type.toChars(), tparam.toChars());
4862 if (e.td)
4864 Type to = tparam;
4865 if (!to.nextOf())
4866 return;
4867 auto tof = to.nextOf().isTypeFunction();
4868 if (!tof)
4869 return;
4871 // Parameter types inference from 'tof'
4872 assert(e.td._scope);
4873 TypeFunction tf = cast(TypeFunction)e.fd.type;
4874 //printf("\ttof = %s\n", tof.toChars());
4875 //printf("\ttf = %s\n", tf.toChars());
4876 const dim = tf.parameterList.length;
4878 if (tof.parameterList.length != dim || tof.parameterList.varargs != tf.parameterList.varargs)
4879 return;
4881 auto tiargs = new Objects();
4882 tiargs.reserve(e.td.parameters.length);
4884 foreach (tp; *e.td.parameters)
4886 size_t u = 0;
4887 foreach (i, p; tf.parameterList)
4889 if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4890 break;
4891 ++u;
4893 assert(u < dim);
4894 Parameter pto = tof.parameterList[u];
4895 if (!pto)
4896 break;
4897 Type t = pto.type.syntaxCopy(); // https://issues.dlang.org/show_bug.cgi?id=11774
4898 if (reliesOnTemplateParameters(t, (*parameters)[inferStart .. parameters.length]))
4899 return;
4900 t = t.typeSemantic(e.loc, sc);
4901 if (t.ty == Terror)
4902 return;
4903 tiargs.push(t);
4906 // Set target of return type inference
4907 if (!tf.next && tof.next)
4908 e.fd.treq = tparam;
4910 auto ti = new TemplateInstance(e.loc, e.td, tiargs);
4911 Expression ex = (new ScopeExp(e.loc, ti)).expressionSemantic(e.td._scope);
4913 // Reset inference target for the later re-semantic
4914 e.fd.treq = null;
4916 if (ex.op == EXP.error)
4917 return;
4918 if (ex.op != EXP.function_)
4919 return;
4920 visit(ex.type);
4921 return;
4924 Type t = e.type;
4926 if (t.ty == Tdelegate && tparam.ty == Tpointer)
4927 return;
4929 // Allow conversion from implicit function pointer to delegate
4930 if (e.tok == TOK.reserved && t.ty == Tpointer && tparam.ty == Tdelegate)
4932 TypeFunction tf = cast(TypeFunction)t.nextOf();
4933 t = (new TypeDelegate(tf)).merge();
4935 //printf("tparam = %s <= e.type = %s, t = %s\n", tparam.toChars(), e.type.toChars(), t.toChars());
4936 visit(t);
4939 override void visit(SliceExp e)
4941 Type taai;
4942 if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
4944 // Consider compile-time known boundaries
4945 if (Type tsa = toStaticArrayType(e))
4947 tsa.accept(this);
4948 if (result > MATCH.convert)
4949 result = MATCH.convert; // match with implicit conversion at most
4950 return;
4953 visit(cast(Expression)e);
4956 override void visit(CommaExp e)
4958 e.e2.accept(this);
4962 scope DeduceType v = new DeduceType(sc, tparam, parameters, dedtypes, wm, inferStart, ignoreAliasThis);
4963 if (Type t = isType(o))
4964 t.accept(v);
4965 else if (Expression e = isExpression(o))
4967 assert(wm);
4968 e.accept(v);
4970 else
4971 assert(0);
4972 return v.result;
4975 /***********************************************************
4976 * Check whether the type t representation relies on one or more the template parameters.
4977 * Params:
4978 * t = Tested type, if null, returns false.
4979 * tparams = Template parameters.
4980 * iStart = Start index of tparams to limit the tested parameters. If it's
4981 * nonzero, tparams[0..iStart] will be excluded from the test target.
4983 bool reliesOnTident(Type t, TemplateParameters* tparams, size_t iStart = 0)
4985 return reliesOnTemplateParameters(t, (*tparams)[0 .. tparams.length]);
4988 /***********************************************************
4989 * Check whether the type t representation relies on one or more the template parameters.
4990 * Params:
4991 * t = Tested type, if null, returns false.
4992 * tparams = Template parameters.
4994 private bool reliesOnTemplateParameters(Type t, TemplateParameter[] tparams)
4996 bool visitVector(TypeVector t)
4998 return t.basetype.reliesOnTemplateParameters(tparams);
5001 bool visitAArray(TypeAArray t)
5003 return t.next.reliesOnTemplateParameters(tparams) ||
5004 t.index.reliesOnTemplateParameters(tparams);
5007 bool visitFunction(TypeFunction t)
5009 foreach (i, fparam; t.parameterList)
5011 if (fparam.type.reliesOnTemplateParameters(tparams))
5012 return true;
5014 return t.next.reliesOnTemplateParameters(tparams);
5017 bool visitIdentifier(TypeIdentifier t)
5019 foreach (tp; tparams)
5021 if (tp.ident.equals(t.ident))
5022 return true;
5024 return false;
5027 bool visitInstance(TypeInstance t)
5029 foreach (tp; tparams)
5031 if (t.tempinst.name == tp.ident)
5032 return true;
5035 if (t.tempinst.tiargs)
5036 foreach (arg; *t.tempinst.tiargs)
5038 if (Type ta = isType(arg))
5040 if (ta.reliesOnTemplateParameters(tparams))
5041 return true;
5045 return false;
5048 bool visitTypeof(TypeTypeof t)
5050 //printf("TypeTypeof.reliesOnTemplateParameters('%s')\n", t.toChars());
5051 return t.exp.reliesOnTemplateParameters(tparams);
5054 bool visitTuple(TypeTuple t)
5056 if (t.arguments)
5057 foreach (arg; *t.arguments)
5059 if (arg.type.reliesOnTemplateParameters(tparams))
5060 return true;
5063 return false;
5066 if (!t)
5067 return false;
5069 Type tb = t.toBasetype();
5070 switch (tb.ty)
5072 case Tvector: return visitVector(tb.isTypeVector());
5073 case Taarray: return visitAArray(tb.isTypeAArray());
5074 case Tfunction: return visitFunction(tb.isTypeFunction());
5075 case Tident: return visitIdentifier(tb.isTypeIdentifier());
5076 case Tinstance: return visitInstance(tb.isTypeInstance());
5077 case Ttypeof: return visitTypeof(tb.isTypeTypeof());
5078 case Ttuple: return visitTuple(tb.isTypeTuple());
5079 case Tenum: return false;
5080 default: return tb.nextOf().reliesOnTemplateParameters(tparams);
5084 /***********************************************************
5085 * Check whether the expression representation relies on one or more the template parameters.
5086 * Params:
5087 * e = expression to test
5088 * tparams = Template parameters.
5089 * Returns:
5090 * true if it does
5092 private bool reliesOnTemplateParameters(Expression e, TemplateParameter[] tparams)
5094 extern (C++) final class ReliesOnTemplateParameters : Visitor
5096 alias visit = Visitor.visit;
5097 public:
5098 TemplateParameter[] tparams;
5099 bool result;
5101 extern (D) this(TemplateParameter[] tparams) @safe
5103 this.tparams = tparams;
5106 override void visit(Expression e)
5108 //printf("Expression.reliesOnTemplateParameters('%s')\n", e.toChars());
5111 override void visit(IdentifierExp e)
5113 //printf("IdentifierExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5114 foreach (tp; tparams)
5116 if (e.ident == tp.ident)
5118 result = true;
5119 return;
5124 override void visit(TupleExp e)
5126 //printf("TupleExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5127 if (e.exps)
5129 foreach (ea; *e.exps)
5131 ea.accept(this);
5132 if (result)
5133 return;
5138 override void visit(ArrayLiteralExp e)
5140 //printf("ArrayLiteralExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5141 if (e.elements)
5143 foreach (el; *e.elements)
5145 el.accept(this);
5146 if (result)
5147 return;
5152 override void visit(AssocArrayLiteralExp e)
5154 //printf("AssocArrayLiteralExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5155 foreach (ek; *e.keys)
5157 ek.accept(this);
5158 if (result)
5159 return;
5161 foreach (ev; *e.values)
5163 ev.accept(this);
5164 if (result)
5165 return;
5169 override void visit(StructLiteralExp e)
5171 //printf("StructLiteralExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5172 if (e.elements)
5174 foreach (ea; *e.elements)
5176 ea.accept(this);
5177 if (result)
5178 return;
5183 override void visit(TypeExp e)
5185 //printf("TypeExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5186 result = e.type.reliesOnTemplateParameters(tparams);
5189 override void visit(NewExp e)
5191 //printf("NewExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5192 if (e.thisexp)
5193 e.thisexp.accept(this);
5194 result = e.newtype.reliesOnTemplateParameters(tparams);
5195 if (!result && e.arguments)
5197 foreach (ea; *e.arguments)
5199 ea.accept(this);
5200 if (result)
5201 return;
5206 override void visit(NewAnonClassExp e)
5208 //printf("NewAnonClassExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5209 result = true;
5212 override void visit(FuncExp e)
5214 //printf("FuncExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5215 result = true;
5218 override void visit(TypeidExp e)
5220 //printf("TypeidExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5221 if (auto ea = isExpression(e.obj))
5222 ea.accept(this);
5223 else if (auto ta = isType(e.obj))
5224 result = ta.reliesOnTemplateParameters(tparams);
5227 override void visit(TraitsExp e)
5229 //printf("TraitsExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5230 if (e.args)
5232 foreach (oa; *e.args)
5234 if (auto ea = isExpression(oa))
5235 ea.accept(this);
5236 else if (auto ta = isType(oa))
5237 result = ta.reliesOnTemplateParameters(tparams);
5238 if (result)
5239 return;
5244 override void visit(IsExp e)
5246 //printf("IsExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5247 result = e.targ.reliesOnTemplateParameters(tparams);
5250 override void visit(UnaExp e)
5252 //printf("UnaExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5253 e.e1.accept(this);
5256 override void visit(DotTemplateInstanceExp e)
5258 //printf("DotTemplateInstanceExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5259 visit(e.isUnaExp());
5260 if (!result && e.ti.tiargs)
5262 foreach (oa; *e.ti.tiargs)
5264 if (auto ea = isExpression(oa))
5265 ea.accept(this);
5266 else if (auto ta = isType(oa))
5267 result = ta.reliesOnTemplateParameters(tparams);
5268 if (result)
5269 return;
5274 override void visit(CallExp e)
5276 //printf("CallExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5277 visit(e.isUnaExp());
5278 if (!result && e.arguments)
5280 foreach (ea; *e.arguments)
5282 ea.accept(this);
5283 if (result)
5284 return;
5289 override void visit(CastExp e)
5291 //printf("CallExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5292 visit(e.isUnaExp());
5293 // e.to can be null for cast() with no type
5294 if (!result && e.to)
5295 result = e.to.reliesOnTemplateParameters(tparams);
5298 override void visit(SliceExp e)
5300 //printf("SliceExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5301 visit(e.isUnaExp());
5302 if (!result && e.lwr)
5303 e.lwr.accept(this);
5304 if (!result && e.upr)
5305 e.upr.accept(this);
5308 override void visit(IntervalExp e)
5310 //printf("IntervalExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5311 e.lwr.accept(this);
5312 if (!result)
5313 e.upr.accept(this);
5316 override void visit(ArrayExp e)
5318 //printf("ArrayExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5319 visit(e.isUnaExp());
5320 if (!result && e.arguments)
5322 foreach (ea; *e.arguments)
5323 ea.accept(this);
5327 override void visit(BinExp e)
5329 //printf("BinExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5330 e.e1.accept(this);
5331 if (!result)
5332 e.e2.accept(this);
5335 override void visit(CondExp e)
5337 //printf("BinExp.reliesOnTemplateParameters('%s')\n", e.toChars());
5338 e.econd.accept(this);
5339 if (!result)
5340 visit(e.isBinExp());
5344 scope ReliesOnTemplateParameters v = new ReliesOnTemplateParameters(tparams);
5345 e.accept(v);
5346 return v.result;
5349 /***********************************************************
5350 * https://dlang.org/spec/template.html#TemplateParameter
5352 extern (C++) class TemplateParameter : ASTNode
5354 Loc loc;
5355 Identifier ident;
5357 /* True if this is a part of precedent parameter specialization pattern.
5359 * template A(T : X!TL, alias X, TL...) {}
5360 * // X and TL are dependent template parameter
5362 * A dependent template parameter should return MATCH.exact in matchArg()
5363 * to respect the match level of the corresponding precedent parameter.
5365 bool dependent;
5367 /* ======================== TemplateParameter =============================== */
5368 extern (D) this(const ref Loc loc, Identifier ident) @safe
5370 this.loc = loc;
5371 this.ident = ident;
5374 TemplateTypeParameter isTemplateTypeParameter()
5376 return null;
5379 TemplateValueParameter isTemplateValueParameter()
5381 return null;
5384 TemplateAliasParameter isTemplateAliasParameter()
5386 return null;
5389 TemplateThisParameter isTemplateThisParameter()
5391 return null;
5394 TemplateTupleParameter isTemplateTupleParameter()
5396 return null;
5399 abstract TemplateParameter syntaxCopy();
5401 abstract bool declareParameter(Scope* sc);
5403 abstract void print(RootObject oarg, RootObject oded);
5405 abstract RootObject specialization();
5407 abstract RootObject defaultArg(const ref Loc instLoc, Scope* sc);
5409 abstract bool hasDefaultArg();
5411 override const(char)* toChars() const
5413 return this.ident.toChars();
5416 override DYNCAST dyncast() const
5418 return DYNCAST.templateparameter;
5421 /* Create dummy argument based on parameter.
5423 abstract RootObject dummyArg();
5425 override void accept(Visitor v)
5427 v.visit(this);
5431 /***********************************************************
5432 * https://dlang.org/spec/template.html#TemplateTypeParameter
5433 * Syntax:
5434 * ident : specType = defaultType
5436 extern (C++) class TemplateTypeParameter : TemplateParameter
5438 Type specType; // if !=null, this is the type specialization
5439 Type defaultType;
5441 extern (D) __gshared Type tdummy = null;
5443 extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType) @safe
5445 super(loc, ident);
5446 this.specType = specType;
5447 this.defaultType = defaultType;
5450 override final TemplateTypeParameter isTemplateTypeParameter()
5452 return this;
5455 override TemplateTypeParameter syntaxCopy()
5457 return new TemplateTypeParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5460 override final bool declareParameter(Scope* sc)
5462 //printf("TemplateTypeParameter.declareParameter('%s')\n", ident.toChars());
5463 auto ti = new TypeIdentifier(loc, ident);
5464 Declaration ad = new AliasDeclaration(loc, ident, ti);
5465 return sc.insert(ad) !is null;
5468 override final void print(RootObject oarg, RootObject oded)
5470 printf(" %s\n", ident.toChars());
5472 Type t = isType(oarg);
5473 Type ta = isType(oded);
5474 assert(ta);
5476 if (specType)
5477 printf("\tSpecialization: %s\n", specType.toChars());
5478 if (defaultType)
5479 printf("\tDefault: %s\n", defaultType.toChars());
5480 printf("\tParameter: %s\n", t ? t.toChars() : "NULL");
5481 printf("\tDeduced Type: %s\n", ta.toChars());
5484 override final RootObject specialization()
5486 return specType;
5489 override final RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5491 Type t = defaultType;
5492 if (t)
5494 t = t.syntaxCopy();
5495 t = t.typeSemantic(loc, sc); // use the parameter loc
5497 return t;
5500 override final bool hasDefaultArg()
5502 return defaultType !is null;
5505 override final RootObject dummyArg()
5507 Type t = specType;
5508 if (!t)
5510 // Use this for alias-parameter's too (?)
5511 if (!tdummy)
5512 tdummy = new TypeIdentifier(loc, ident);
5513 t = tdummy;
5515 return t;
5518 override void accept(Visitor v)
5520 v.visit(this);
5524 /***********************************************************
5525 * https://dlang.org/spec/template.html#TemplateThisParameter
5526 * Syntax:
5527 * this ident : specType = defaultType
5529 extern (C++) final class TemplateThisParameter : TemplateTypeParameter
5531 extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType) @safe
5533 super(loc, ident, specType, defaultType);
5536 override TemplateThisParameter isTemplateThisParameter()
5538 return this;
5541 override TemplateThisParameter syntaxCopy()
5543 return new TemplateThisParameter(loc, ident, specType ? specType.syntaxCopy() : null, defaultType ? defaultType.syntaxCopy() : null);
5546 override void accept(Visitor v)
5548 v.visit(this);
5552 /***********************************************************
5553 * https://dlang.org/spec/template.html#TemplateValueParameter
5554 * Syntax:
5555 * valType ident : specValue = defaultValue
5557 extern (C++) final class TemplateValueParameter : TemplateParameter
5559 Type valType;
5560 Expression specValue;
5561 Expression defaultValue;
5563 extern (D) __gshared Expression[void*] edummies;
5565 extern (D) this(const ref Loc loc, Identifier ident, Type valType,
5566 Expression specValue, Expression defaultValue) @safe
5568 super(loc, ident);
5569 this.valType = valType;
5570 this.specValue = specValue;
5571 this.defaultValue = defaultValue;
5574 override TemplateValueParameter isTemplateValueParameter()
5576 return this;
5579 override TemplateValueParameter syntaxCopy()
5581 return new TemplateValueParameter(loc, ident,
5582 valType.syntaxCopy(),
5583 specValue ? specValue.syntaxCopy() : null,
5584 defaultValue ? defaultValue.syntaxCopy() : null);
5587 override bool declareParameter(Scope* sc)
5590 Do type semantic earlier.
5592 This means for certain erroneous value parameters
5593 their "type" can be known earlier and thus a better
5594 error message given.
5596 For example:
5597 `template test(x* x) {}`
5598 now yields "undefined identifier" rather than the opaque
5599 "variable `x` is used as a type".
5601 if (valType)
5602 valType = valType.typeSemantic(loc, sc);
5603 auto v = new VarDeclaration(loc, valType, ident, null);
5604 v.storage_class = STC.templateparameter;
5605 return sc.insert(v) !is null;
5608 override void print(RootObject oarg, RootObject oded)
5610 printf(" %s\n", ident.toChars());
5611 Expression ea = isExpression(oded);
5612 if (specValue)
5613 printf("\tSpecialization: %s\n", specValue.toChars());
5614 printf("\tParameter Value: %s\n", ea ? ea.toChars() : "NULL");
5617 override RootObject specialization()
5619 return specValue;
5622 override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5624 Expression e = defaultValue;
5625 if (e)
5627 e = e.syntaxCopy();
5628 if ((e = e.expressionSemantic(sc)) is null)
5629 return null;
5630 if (auto te = e.isTemplateExp())
5632 assert(sc && sc.tinst);
5633 if (te.td == sc.tinst.tempdecl)
5635 // defaultValue is a reference to its template declaration
5636 // i.e: `template T(int arg = T)`
5637 // Raise error now before calling resolveProperties otherwise we'll
5638 // start looping on the expansion of the template instance.
5639 auto td = sc.tinst.tempdecl;
5640 .error(td.loc, "%s `%s` recursive template expansion", td.kind, td.toPrettyChars);
5641 return ErrorExp.get();
5644 if ((e = resolveProperties(sc, e)) is null)
5645 return null;
5646 e = e.resolveLoc(instLoc, sc); // use the instantiated loc
5647 e = e.optimize(WANTvalue);
5649 return e;
5652 override bool hasDefaultArg()
5654 return defaultValue !is null;
5657 override RootObject dummyArg()
5659 Expression e = specValue;
5660 if (!e)
5662 // Create a dummy value
5663 auto pe = cast(void*)valType in edummies;
5664 if (!pe)
5666 e = valType.defaultInit(Loc.initial);
5667 edummies[cast(void*)valType] = e;
5669 else
5670 e = *pe;
5672 return e;
5675 override void accept(Visitor v)
5677 v.visit(this);
5681 /***********************************************************
5682 * https://dlang.org/spec/template.html#TemplateAliasParameter
5683 * Syntax:
5684 * specType ident : specAlias = defaultAlias
5686 extern (C++) final class TemplateAliasParameter : TemplateParameter
5688 Type specType;
5689 RootObject specAlias;
5690 RootObject defaultAlias;
5692 extern (D) __gshared Dsymbol sdummy = null;
5694 extern (D) this(const ref Loc loc, Identifier ident, Type specType, RootObject specAlias, RootObject defaultAlias) @safe
5696 super(loc, ident);
5697 this.specType = specType;
5698 this.specAlias = specAlias;
5699 this.defaultAlias = defaultAlias;
5702 override TemplateAliasParameter isTemplateAliasParameter()
5704 return this;
5707 override TemplateAliasParameter syntaxCopy()
5709 return new TemplateAliasParameter(loc, ident, specType ? specType.syntaxCopy() : null, objectSyntaxCopy(specAlias), objectSyntaxCopy(defaultAlias));
5712 override bool declareParameter(Scope* sc)
5714 auto ti = new TypeIdentifier(loc, ident);
5715 Declaration ad = new AliasDeclaration(loc, ident, ti);
5716 return sc.insert(ad) !is null;
5719 override void print(RootObject oarg, RootObject oded)
5721 printf(" %s\n", ident.toChars());
5722 Dsymbol sa = isDsymbol(oded);
5723 assert(sa);
5724 printf("\tParameter alias: %s\n", sa.toChars());
5727 override RootObject specialization()
5729 return specAlias;
5732 override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5734 RootObject da = defaultAlias;
5735 if (auto ta = isType(defaultAlias))
5737 switch (ta.ty)
5739 // If the default arg is a template, instantiate for each type
5740 case Tinstance :
5741 // same if the default arg is a mixin, traits, typeof
5742 // since the content might rely on a previous parameter
5743 // (https://issues.dlang.org/show_bug.cgi?id=23686)
5744 case Tmixin, Ttypeof, Ttraits :
5745 da = ta.syntaxCopy();
5746 break;
5747 default:
5751 RootObject o = aliasParameterSemantic(loc, sc, da, null); // use the parameter loc
5752 return o;
5755 override bool hasDefaultArg()
5757 return defaultAlias !is null;
5760 override RootObject dummyArg()
5762 RootObject s = specAlias;
5763 if (!s)
5765 if (!sdummy)
5766 sdummy = new Dsymbol();
5767 s = sdummy;
5769 return s;
5772 override void accept(Visitor v)
5774 v.visit(this);
5778 /***********************************************************
5779 * https://dlang.org/spec/template.html#TemplateSequenceParameter
5780 * Syntax:
5781 * ident ...
5783 extern (C++) final class TemplateTupleParameter : TemplateParameter
5785 extern (D) this(const ref Loc loc, Identifier ident) @safe
5787 super(loc, ident);
5790 override TemplateTupleParameter isTemplateTupleParameter()
5792 return this;
5795 override TemplateTupleParameter syntaxCopy()
5797 return new TemplateTupleParameter(loc, ident);
5800 override bool declareParameter(Scope* sc)
5802 auto ti = new TypeIdentifier(loc, ident);
5803 Declaration ad = new AliasDeclaration(loc, ident, ti);
5804 return sc.insert(ad) !is null;
5807 override void print(RootObject oarg, RootObject oded)
5809 printf(" %s... [", ident.toChars());
5810 Tuple v = isTuple(oded);
5811 assert(v);
5813 //printf("|%d| ", v.objects.length);
5814 foreach (i, o; v.objects)
5816 if (i)
5817 printf(", ");
5819 Dsymbol sa = isDsymbol(o);
5820 if (sa)
5821 printf("alias: %s", sa.toChars());
5822 Type ta = isType(o);
5823 if (ta)
5824 printf("type: %s", ta.toChars());
5825 Expression ea = isExpression(o);
5826 if (ea)
5827 printf("exp: %s", ea.toChars());
5829 assert(!isTuple(o)); // no nested Tuple arguments
5831 printf("]\n");
5834 override RootObject specialization()
5836 return null;
5839 override RootObject defaultArg(const ref Loc instLoc, Scope* sc)
5841 return null;
5844 override bool hasDefaultArg()
5846 return false;
5849 override RootObject dummyArg()
5851 return null;
5854 override void accept(Visitor v)
5856 v.visit(this);
5860 /***********************************************************
5861 * https://dlang.org/spec/template.html#explicit_tmp_instantiation
5862 * Given:
5863 * foo!(args) =>
5864 * name = foo
5865 * tiargs = args
5867 extern (C++) class TemplateInstance : ScopeDsymbol
5869 Identifier name;
5871 // Array of Types/Expressions of template
5872 // instance arguments [int*, char, 10*10]
5873 Objects* tiargs;
5875 // Array of Types/Expressions corresponding
5876 // to TemplateDeclaration.parameters
5877 // [int, char, 100]
5878 Objects tdtypes;
5880 // Modules imported by this template instance
5881 Modules importedModules;
5883 Dsymbol tempdecl; // referenced by foo.bar.abc
5884 Dsymbol enclosing; // if referencing local symbols, this is the context
5885 Dsymbol aliasdecl; // !=null if instance is an alias for its sole member
5886 TemplateInstance inst; // refer to existing instance
5887 ScopeDsymbol argsym; // argument symbol table
5888 size_t hash; // cached result of toHash()
5889 Expressions* fargs; // for function template, these are the function arguments
5891 TemplateInstances* deferred;
5893 Module memberOf; // if !null, then this TemplateInstance appears in memberOf.members[]
5895 // Used to determine the instance needs code generation.
5896 // Note that these are inaccurate until semantic analysis phase completed.
5897 TemplateInstance tinst; // enclosing template instance
5898 TemplateInstance tnext; // non-first instantiated instances
5899 Module minst; // the top module that instantiated this instance
5901 private ushort _nest; // for recursive pretty printing detection, 3 MSBs reserved for flags (below)
5902 ubyte inuse; // for recursive expansion detection
5904 private enum Flag : uint
5906 semantictiargsdone = 1u << (_nest.sizeof * 8 - 1), // MSB of _nest
5907 havetempdecl = semantictiargsdone >> 1,
5908 gagged = semantictiargsdone >> 2,
5909 available = gagged - 1 // always last flag minus one, 1s for all available bits
5912 extern(D) final @safe @property pure nothrow @nogc
5914 ushort nest() const { return _nest & Flag.available; }
5915 void nestUp() { assert(nest() < Flag.available); ++_nest; }
5916 void nestDown() { assert(nest() > 0); --_nest; }
5917 /// has semanticTiargs() been done?
5918 bool semantictiargsdone() const { return (_nest & Flag.semantictiargsdone) != 0; }
5919 void semantictiargsdone(bool x)
5921 if (x) _nest |= Flag.semantictiargsdone;
5922 else _nest &= ~Flag.semantictiargsdone;
5924 /// if used second constructor
5925 bool havetempdecl() const { return (_nest & Flag.havetempdecl) != 0; }
5926 void havetempdecl(bool x)
5928 if (x) _nest |= Flag.havetempdecl;
5929 else _nest &= ~Flag.havetempdecl;
5931 /// if the instantiation is done with error gagging
5932 bool gagged() const { return (_nest & Flag.gagged) != 0; }
5933 void gagged(bool x)
5935 if (x) _nest |= Flag.gagged;
5936 else _nest &= ~Flag.gagged;
5940 extern (D) this(const ref Loc loc, Identifier ident, Objects* tiargs) scope
5942 super(loc, null);
5943 static if (LOG)
5945 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident.toChars() : "null");
5947 this.name = ident;
5948 this.tiargs = tiargs;
5951 /*****************
5952 * This constructor is only called when we figured out which function
5953 * template to instantiate.
5955 extern (D) this(const ref Loc loc, TemplateDeclaration td, Objects* tiargs) scope
5957 super(loc, null);
5958 static if (LOG)
5960 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td.toChars());
5962 this.name = td.ident;
5963 this.tiargs = tiargs;
5964 this.tempdecl = td;
5965 this.semantictiargsdone = true;
5966 this.havetempdecl = true;
5967 assert(tempdecl._scope);
5970 extern (D) static Objects* arraySyntaxCopy(Objects* objs)
5972 Objects* a = null;
5973 if (objs)
5975 a = new Objects(objs.length);
5976 foreach (i, o; *objs)
5977 (*a)[i] = objectSyntaxCopy(o);
5979 return a;
5982 override TemplateInstance syntaxCopy(Dsymbol s)
5984 TemplateInstance ti = s ? cast(TemplateInstance)s : new TemplateInstance(loc, name, null);
5985 ti.tiargs = arraySyntaxCopy(tiargs);
5986 TemplateDeclaration td;
5987 if (inst && tempdecl && (td = tempdecl.isTemplateDeclaration()) !is null)
5988 td.ScopeDsymbol.syntaxCopy(ti);
5989 else
5990 ScopeDsymbol.syntaxCopy(ti);
5991 return ti;
5994 // resolve real symbol
5995 override final Dsymbol toAlias()
5997 static if (LOG)
5999 printf("TemplateInstance.toAlias()\n");
6001 if (!inst)
6003 // Maybe we can resolve it
6004 if (_scope)
6006 dsymbolSemantic(this, _scope);
6008 if (!inst)
6010 .error(loc, "%s `%s` cannot resolve forward reference", kind, toPrettyChars);
6011 errors = true;
6012 return this;
6016 if (inst != this)
6017 return inst.toAlias();
6019 if (aliasdecl)
6021 return aliasdecl.toAlias();
6024 return inst;
6027 override const(char)* kind() const
6029 return "template instance";
6032 override bool oneMember(Dsymbol* ps, Identifier ident)
6034 *ps = null;
6035 return true;
6038 override const(char)* toChars() const
6040 OutBuffer buf;
6041 toCBufferInstance(this, buf);
6042 return buf.extractChars();
6045 override final const(char)* toPrettyCharsHelper()
6047 OutBuffer buf;
6048 toCBufferInstance(this, buf, true);
6049 return buf.extractChars();
6052 /**************************************
6053 * Given an error instantiating the TemplateInstance,
6054 * give the nested TemplateInstance instantiations that got
6055 * us here. Those are a list threaded into the nested scopes.
6056 * Params:
6057 * cl = classification of this trace as printing either errors or deprecations
6058 * max_shown = maximum number of trace elements printed (controlled with -v/-verror-limit)
6060 extern(D) final void printInstantiationTrace(Classification cl = Classification.error,
6061 const(uint) max_shown = global.params.v.errorSupplementCount())
6063 if (global.gag)
6064 return;
6066 // Print full trace for verbose mode, otherwise only short traces
6067 const(char)* format = "instantiated from here: `%s`";
6069 // This returns a function pointer
6070 scope printFn = () {
6071 final switch (cl)
6073 case Classification.error:
6074 return &errorSupplemental;
6075 case Classification.deprecation:
6076 return &deprecationSupplemental;
6077 case Classification.gagged, Classification.tip, Classification.warning:
6078 assert(0);
6080 }();
6082 // determine instantiation depth and number of recursive instantiations
6083 int n_instantiations = 1;
6084 int n_totalrecursions = 0;
6085 for (TemplateInstance cur = this; cur; cur = cur.tinst)
6087 ++n_instantiations;
6088 // Set error here as we don't want it to depend on the number of
6089 // entries that are being printed.
6090 if (cl == Classification.error ||
6091 (cl == Classification.warning && global.params.warnings == DiagnosticReporting.error) ||
6092 (cl == Classification.deprecation && global.params.useDeprecated == DiagnosticReporting.error))
6093 cur.errors = true;
6095 // If two instantiations use the same declaration, they are recursive.
6096 // (this works even if they are instantiated from different places in the
6097 // same template).
6098 // In principle, we could also check for multiple-template recursion, but it's
6099 // probably not worthwhile.
6100 if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
6101 ++n_totalrecursions;
6104 if (n_instantiations <= max_shown)
6106 for (TemplateInstance cur = this; cur; cur = cur.tinst)
6107 printFn(cur.loc, format, cur.toChars());
6109 else if (n_instantiations - n_totalrecursions <= max_shown)
6111 // By collapsing recursive instantiations into a single line,
6112 // we can stay under the limit.
6113 int recursionDepth = 0;
6114 for (TemplateInstance cur = this; cur; cur = cur.tinst)
6116 if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc))
6118 ++recursionDepth;
6120 else
6122 if (recursionDepth)
6123 printFn(cur.loc, "%d recursive instantiations from here: `%s`", recursionDepth + 2, cur.toChars());
6124 else
6125 printFn(cur.loc, format, cur.toChars());
6126 recursionDepth = 0;
6130 else
6132 // Even after collapsing the recursions, the depth is too deep.
6133 // Just display the first few and last few instantiations.
6134 uint i = 0;
6135 for (TemplateInstance cur = this; cur; cur = cur.tinst)
6137 if (i == max_shown / 2)
6138 printFn(cur.loc, "... (%d instantiations, -v to show) ...", n_instantiations - max_shown);
6140 if (i < max_shown / 2 || i >= n_instantiations - max_shown + max_shown / 2)
6141 printFn(cur.loc, format, cur.toChars());
6142 ++i;
6147 /*************************************
6148 * Lazily generate identifier for template instance.
6149 * This is because 75% of the ident's are never needed.
6151 override final Identifier getIdent()
6153 if (!ident && inst && !errors)
6154 ident = genIdent(tiargs); // need an identifier for name mangling purposes.
6155 return ident;
6158 /*************************************
6159 * Compare proposed template instantiation with existing template instantiation.
6160 * Note that this is not commutative because of the auto ref check.
6161 * Params:
6162 * ti = existing template instantiation
6163 * Returns:
6164 * true for match
6166 final bool equalsx(TemplateInstance ti)
6168 //printf("this = %p, ti = %p\n", this, ti);
6169 assert(tdtypes.length == ti.tdtypes.length);
6171 // Nesting must match
6172 if (enclosing != ti.enclosing)
6174 //printf("test2 enclosing %s ti.enclosing %s\n", enclosing ? enclosing.toChars() : "", ti.enclosing ? ti.enclosing.toChars() : "");
6175 goto Lnotequals;
6177 //printf("parent = %s, ti.parent = %s\n", parent.toPrettyChars(), ti.parent.toPrettyChars());
6179 if (!arrayObjectMatch(&tdtypes, &ti.tdtypes))
6180 goto Lnotequals;
6182 /* Template functions may have different instantiations based on
6183 * "auto ref" parameters.
6185 if (auto fd = ti.toAlias().isFuncDeclaration())
6187 if (!fd.errors)
6189 auto fparameters = fd.getParameterList();
6190 size_t nfparams = fparameters.length; // Num function parameters
6191 for (size_t j = 0; j < nfparams; j++)
6193 Parameter fparam = fparameters[j];
6194 if (fparam.storageClass & STC.autoref) // if "auto ref"
6196 Expression farg = fargs && j < fargs.length ? (*fargs)[j] : fparam.defaultArg;
6197 if (!farg)
6198 goto Lnotequals;
6199 if (farg.isLvalue())
6201 if (!(fparam.storageClass & STC.ref_))
6202 goto Lnotequals; // auto ref's don't match
6204 else
6206 if (fparam.storageClass & STC.ref_)
6207 goto Lnotequals; // auto ref's don't match
6213 return true;
6215 Lnotequals:
6216 return false;
6219 extern (D) final size_t toHash()
6221 if (!hash)
6223 hash = cast(size_t)cast(void*)enclosing;
6224 hash += arrayObjectHash(&tdtypes);
6225 hash += hash == 0;
6227 return hash;
6231 Returns: true if the instances' innards are discardable.
6233 The idea of this function is to see if the template instantiation
6234 can be 100% replaced with its eponymous member. All other members
6235 can be discarded, even in the compiler to free memory (for example,
6236 the template could be expanded in a region allocator, deemed trivial,
6237 the end result copied back out independently and the entire region freed),
6238 and can be elided entirely from the binary.
6240 The current implementation affects code that generally looks like:
6243 template foo(args...) {
6244 some_basic_type_or_string helper() { .... }
6245 enum foo = helper();
6249 since it was the easiest starting point of implementation but it can and
6250 should be expanded more later.
6252 final bool isDiscardable()
6254 if (aliasdecl is null)
6255 return false;
6257 auto v = aliasdecl.isVarDeclaration();
6258 if (v is null)
6259 return false;
6261 if (!(v.storage_class & STC.manifest))
6262 return false;
6264 // Currently only doing basic types here because it is the easiest proof-of-concept
6265 // implementation with minimal risk of side effects, but it could likely be
6266 // expanded to any type that already exists outside this particular instance.
6267 if (!(v.type.equals(Type.tstring) || (v.type.isTypeBasic() !is null)))
6268 return false;
6270 // Static ctors and dtors, even in an eponymous enum template, are still run,
6271 // so if any of them are in here, we'd better not assume it is trivial lest
6272 // we break useful code
6273 foreach(member; *members)
6275 if(member.hasStaticCtorOrDtor())
6276 return false;
6277 if(member.isStaticDtorDeclaration())
6278 return false;
6279 if(member.isStaticCtorDeclaration())
6280 return false;
6283 // but if it passes through this gauntlet... it should be fine. D code will
6284 // see only the eponymous member, outside stuff can never access it, even through
6285 // reflection; the outside world ought to be none the wiser. Even dmd should be
6286 // able to simply free the memory of everything except the final result.
6288 return true;
6292 /***********************************************
6293 * Returns true if this is not instantiated in non-root module, and
6294 * is a part of non-speculative instantiatiation.
6296 * Note: minst does not stabilize until semantic analysis is completed,
6297 * so don't call this function during semantic analysis to return precise result.
6299 final bool needsCodegen()
6301 //printf("needsCodegen() %s\n", toChars());
6303 // minst is finalized after the 1st invocation.
6304 // tnext is only needed for the 1st invocation and
6305 // cleared for further invocations.
6306 TemplateInstance tnext = this.tnext;
6307 TemplateInstance tinst = this.tinst;
6308 this.tnext = null;
6310 // Don't do codegen if the instance has errors,
6311 // is a dummy instance (see evaluateConstraint),
6312 // or is determined to be discardable.
6313 if (errors || inst is null || inst.isDiscardable())
6315 minst = null; // mark as speculative
6316 return false;
6319 // This should only be called on the primary instantiation.
6320 assert(this is inst);
6322 if (global.params.allInst)
6324 // Do codegen if there is an instantiation from a root module, to maximize link-ability.
6325 static ThreeState needsCodegenAllInst(TemplateInstance tithis, TemplateInstance tinst)
6327 // Do codegen if `this` is instantiated from a root module.
6328 if (tithis.minst && tithis.minst.isRoot())
6329 return ThreeState.yes;
6331 // Do codegen if the ancestor needs it.
6332 if (tinst && tinst.inst && tinst.inst.needsCodegen())
6334 tithis.minst = tinst.inst.minst; // cache result
6335 assert(tithis.minst);
6336 assert(tithis.minst.isRoot());
6337 return ThreeState.yes;
6339 return ThreeState.none;
6342 if (const needsCodegen = needsCodegenAllInst(this, tinst))
6343 return needsCodegen == ThreeState.yes ? true : false;
6345 // Do codegen if a sibling needs it.
6346 for (; tnext; tnext = tnext.tnext)
6348 const needsCodegen = needsCodegenAllInst(tnext, tnext.tinst);
6349 if (needsCodegen == ThreeState.yes)
6351 minst = tnext.minst; // cache result
6352 assert(minst);
6353 assert(minst.isRoot());
6354 return true;
6356 else if (!minst && tnext.minst)
6358 minst = tnext.minst; // cache result from non-speculative sibling
6359 // continue searching
6361 else if (needsCodegen != ThreeState.none)
6362 break;
6365 // Elide codegen because there's no instantiation from any root modules.
6366 return false;
6368 else
6370 // Prefer instantiations from non-root modules, to minimize object code size.
6372 /* If a TemplateInstance is ever instantiated from a non-root module,
6373 * we do not have to generate code for it,
6374 * because it will be generated when the non-root module is compiled.
6376 * But, if the non-root 'minst' imports any root modules, it might still need codegen.
6378 * The problem is if A imports B, and B imports A, and both A
6379 * and B instantiate the same template, does the compilation of A
6380 * or the compilation of B do the actual instantiation?
6382 * See https://issues.dlang.org/show_bug.cgi?id=2500.
6384 * => Elide codegen if there is at least one instantiation from a non-root module
6385 * which doesn't import any root modules.
6387 static ThreeState needsCodegenRootOnly(TemplateInstance tithis, TemplateInstance tinst)
6389 // If the ancestor isn't speculative,
6390 // 1. do codegen if the ancestor needs it
6391 // 2. elide codegen if the ancestor doesn't need it (non-root instantiation of ancestor incl. subtree)
6392 if (tinst && tinst.inst)
6394 tinst = tinst.inst;
6395 const needsCodegen = tinst.needsCodegen(); // sets tinst.minst
6396 if (tinst.minst) // not speculative
6398 tithis.minst = tinst.minst; // cache result
6399 return needsCodegen ? ThreeState.yes : ThreeState.no;
6403 // Elide codegen if `this` doesn't need it.
6404 if (tithis.minst && !tithis.minst.isRoot() && !tithis.minst.rootImports())
6405 return ThreeState.no;
6407 return ThreeState.none;
6410 if (const needsCodegen = needsCodegenRootOnly(this, tinst))
6411 return needsCodegen == ThreeState.yes ? true : false;
6413 // Elide codegen if a (non-speculative) sibling doesn't need it.
6414 for (; tnext; tnext = tnext.tnext)
6416 const needsCodegen = needsCodegenRootOnly(tnext, tnext.tinst); // sets tnext.minst
6417 if (tnext.minst) // not speculative
6419 if (needsCodegen == ThreeState.no)
6421 minst = tnext.minst; // cache result
6422 assert(!minst.isRoot() && !minst.rootImports());
6423 return false;
6425 else if (!minst)
6427 minst = tnext.minst; // cache result from non-speculative sibling
6428 // continue searching
6430 else if (needsCodegen != ThreeState.none)
6431 break;
6435 // Unless `this` is still speculative (=> all further siblings speculative too),
6436 // do codegen because we found no guaranteed-codegen'd non-root instantiation.
6437 return minst !is null;
6441 /**********************************************
6442 * Find template declaration corresponding to template instance.
6444 * Returns:
6445 * false if finding fails.
6446 * Note:
6447 * This function is reentrant against error occurrence. If returns false,
6448 * any members of this object won't be modified, and repetition call will
6449 * reproduce same error.
6451 extern (D) final bool findTempDecl(Scope* sc, WithScopeSymbol* pwithsym)
6453 if (pwithsym)
6454 *pwithsym = null;
6456 if (havetempdecl)
6457 return true;
6459 //printf("TemplateInstance.findTempDecl() %s\n", toChars());
6460 if (!tempdecl)
6462 /* Given:
6463 * foo!( ... )
6464 * figure out which TemplateDeclaration foo refers to.
6466 Identifier id = name;
6467 Dsymbol scopesym;
6468 Dsymbol s = sc.search(loc, id, scopesym);
6469 if (!s)
6471 s = sc.search_correct(id);
6472 if (s)
6473 .error(loc, "%s `%s` template `%s` is not defined, did you mean %s?", kind, toPrettyChars, id.toChars(), s.toChars());
6474 else
6475 .error(loc, "%s `%s` template `%s` is not defined", kind, toPrettyChars, id.toChars());
6476 return false;
6478 static if (LOG)
6480 printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind());
6481 if (s.parent)
6482 printf("s.parent = '%s'\n", s.parent.toChars());
6484 if (pwithsym)
6485 *pwithsym = scopesym.isWithScopeSymbol();
6487 /* We might have found an alias within a template when
6488 * we really want the template.
6490 TemplateInstance ti;
6491 if (s.parent && (ti = s.parent.isTemplateInstance()) !is null)
6493 if (ti.tempdecl && ti.tempdecl.ident == id)
6495 /* This is so that one can refer to the enclosing
6496 * template, even if it has the same name as a member
6497 * of the template, if it has a !(arguments)
6499 TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
6500 assert(td);
6501 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
6502 td = td.overroot; // then get the start
6503 s = td;
6507 // The template might originate from a selective import which implies that
6508 // s is a lowered AliasDeclaration of the actual TemplateDeclaration.
6509 // This is the last place where we see the deprecated alias because it is
6510 // stripped below, so check if the selective import was deprecated.
6511 // See https://issues.dlang.org/show_bug.cgi?id=20840.
6512 if (s.isAliasDeclaration())
6513 s.checkDeprecated(this.loc, sc);
6515 if (!updateTempDecl(sc, s))
6517 return false;
6520 assert(tempdecl);
6522 // Look for forward references
6523 auto tovers = tempdecl.isOverloadSet();
6524 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
6526 Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
6527 int r = overloadApply(dstart, (Dsymbol s)
6529 auto td = s.isTemplateDeclaration();
6530 if (!td)
6531 return 0;
6533 if (td.semanticRun == PASS.initial)
6535 if (td._scope)
6537 // Try to fix forward reference. Ungag errors while doing so.
6538 Ungag ungag = td.ungagSpeculative();
6539 td.dsymbolSemantic(td._scope);
6541 if (td.semanticRun == PASS.initial)
6543 .error(loc, "%s `%s` `%s` forward references template declaration `%s`", kind, toPrettyChars,
6544 toChars(), td.toChars());
6545 return 1;
6548 return 0;
6550 if (r)
6551 return false;
6553 return true;
6556 /**********************************************
6557 * Confirm s is a valid template, then store it.
6558 * Input:
6559 * sc
6560 * s candidate symbol of template. It may be:
6561 * TemplateDeclaration
6562 * FuncDeclaration with findTemplateDeclRoot() != NULL
6563 * OverloadSet which contains candidates
6564 * Returns:
6565 * true if updating succeeds.
6567 extern (D) final bool updateTempDecl(Scope* sc, Dsymbol s)
6569 if (!s)
6570 return tempdecl !is null;
6572 Identifier id = name;
6573 s = s.toAlias();
6575 /* If an OverloadSet, look for a unique member that is a template declaration
6577 if (OverloadSet os = s.isOverloadSet())
6579 s = null;
6580 foreach (s2; os.a)
6582 if (FuncDeclaration f = s2.isFuncDeclaration())
6583 s2 = f.findTemplateDeclRoot();
6584 else
6585 s2 = s2.isTemplateDeclaration();
6586 if (s2)
6588 if (s)
6590 tempdecl = os;
6591 return true;
6593 s = s2;
6596 if (!s)
6598 .error(loc, "%s `%s` template `%s` is not defined", kind, toPrettyChars, id.toChars());
6599 return false;
6603 if (OverDeclaration od = s.isOverDeclaration())
6605 tempdecl = od; // TODO: more strict check
6606 return true;
6609 /* It should be a TemplateDeclaration, not some other symbol
6611 if (FuncDeclaration f = s.isFuncDeclaration())
6612 tempdecl = f.findTemplateDeclRoot();
6613 else
6614 tempdecl = s.isTemplateDeclaration();
6616 // We're done
6617 if (tempdecl)
6618 return true;
6620 // Error already issued, just return `false`
6621 if (!s.parent && global.errors)
6622 return false;
6624 if (!s.parent && s.getType())
6626 Dsymbol s2 = s.getType().toDsymbol(sc);
6627 if (!s2)
6629 .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());
6630 return false;
6632 // because s can be the alias created for a TemplateParameter
6633 const AliasDeclaration ad = s.isAliasDeclaration();
6634 version (none)
6636 if (ad && ad.isAliasedTemplateParameter())
6637 printf("`%s` is an alias created from a template parameter\n", s.toChars());
6639 if (!ad || !ad.isAliasedTemplateParameter())
6640 s = s2;
6643 TemplateInstance ti = s.parent ? s.parent.isTemplateInstance() : null;
6645 /* This avoids the VarDeclaration.toAlias() which runs semantic() too soon
6647 static bool matchId(TemplateInstance ti, Identifier id)
6649 if (ti.aliasdecl && ti.aliasdecl.isVarDeclaration())
6650 return ti.aliasdecl.isVarDeclaration().ident == id;
6651 return ti.toAlias().ident == id;
6654 if (ti && (ti.name == s.ident || matchId(ti, s.ident)) && ti.tempdecl)
6656 /* This is so that one can refer to the enclosing
6657 * template, even if it has the same name as a member
6658 * of the template, if it has a !(arguments)
6660 TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
6661 assert(td);
6662 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
6663 td = td.overroot; // then get the start
6664 tempdecl = td;
6665 return true;
6667 else
6669 .error(loc, "%s `%s` `%s` is not a template declaration, it is a %s", kind, toPrettyChars, id.toChars(), s.kind());
6670 return false;
6674 /**********************************
6675 * Run semantic of tiargs as arguments of template.
6676 * Input:
6677 * loc
6678 * sc
6679 * tiargs array of template arguments
6680 * flags 1: replace const variables with their initializers
6681 * 2: don't devolve Parameter to Type
6682 * atd tuple being optimized. If found, it's not expanded here
6683 * but in AliasAssign semantic.
6684 * Returns:
6685 * false if one or more arguments have errors.
6687 extern (D) static bool semanticTiargs(const ref Loc loc, Scope* sc, Objects* tiargs, int flags, TupleDeclaration atd = null)
6689 // Run semantic on each argument, place results in tiargs[]
6690 //printf("+TemplateInstance.semanticTiargs()\n");
6691 if (!tiargs)
6692 return true;
6693 bool err = false;
6694 for (size_t j = 0; j < tiargs.length; j++)
6696 RootObject o = (*tiargs)[j];
6697 Type ta = isType(o);
6698 Expression ea = isExpression(o);
6699 Dsymbol sa = isDsymbol(o);
6701 //printf("1: (*tiargs)[%d] = %p, s=%p, v=%p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
6702 if (ta)
6704 //printf("type %s\n", ta.toChars());
6706 // It might really be an Expression or an Alias
6707 ta.resolve(loc, sc, ea, ta, sa, (flags & 1) != 0);
6708 if (ea)
6709 goto Lexpr;
6710 if (sa)
6711 goto Ldsym;
6712 if (ta is null)
6714 assert(global.errors);
6715 ta = Type.terror;
6718 Ltype:
6719 if (ta.ty == Ttuple)
6721 // Expand tuple
6722 TypeTuple tt = cast(TypeTuple)ta;
6723 size_t dim = tt.arguments.length;
6724 tiargs.remove(j);
6725 if (dim)
6727 tiargs.reserve(dim);
6728 foreach (i, arg; *tt.arguments)
6730 if (flags & 2 && (arg.storageClass & STC.parameter))
6731 tiargs.insert(j + i, arg);
6732 else
6733 tiargs.insert(j + i, arg.type);
6736 j--;
6737 continue;
6739 if (ta.ty == Terror)
6741 err = true;
6742 continue;
6744 (*tiargs)[j] = ta.merge2();
6746 else if (ea)
6748 Lexpr:
6749 //printf("+[%d] ea = %s %s\n", j, EXPtoString(ea.op).ptr, ea.toChars());
6750 if (flags & 1) // only used by __traits
6752 ea = ea.expressionSemantic(sc);
6754 // must not interpret the args, excepting template parameters
6755 if (!ea.isVarExp() || (ea.isVarExp().var.storage_class & STC.templateparameter))
6757 ea = ea.optimize(WANTvalue);
6760 else
6762 sc = sc.startCTFE();
6763 ea = ea.expressionSemantic(sc);
6764 sc = sc.endCTFE();
6766 if (auto varExp = ea.isVarExp())
6768 /* If the parameter is a function that is not called
6769 * explicitly, i.e. `foo!func` as opposed to `foo!func()`,
6770 * then it is a dsymbol, not the return value of `func()`
6772 Declaration vd = varExp.var;
6773 if (auto fd = vd.isFuncDeclaration())
6775 sa = fd;
6776 goto Ldsym;
6778 /* Otherwise skip substituting a const var with
6779 * its initializer. The problem is the initializer won't
6780 * match with an 'alias' parameter. Instead, do the
6781 * const substitution in TemplateValueParameter.matchArg().
6784 else if (definitelyValueParameter(ea))
6786 if (ea.checkValue()) // check void expression
6787 ea = ErrorExp.get();
6788 uint olderrs = global.errors;
6789 ea = ea.ctfeInterpret();
6790 if (global.errors != olderrs)
6791 ea = ErrorExp.get();
6794 //printf("-[%d] ea = %s %s\n", j, EXPtoString(ea.op).ptr, ea.toChars());
6795 if (TupleExp te = ea.isTupleExp())
6797 // Expand tuple
6798 size_t dim = te.exps.length;
6799 tiargs.remove(j);
6800 if (dim)
6802 tiargs.reserve(dim);
6803 foreach (i, exp; *te.exps)
6804 tiargs.insert(j + i, exp);
6806 j--;
6807 continue;
6809 if (ea.op == EXP.error)
6811 err = true;
6812 continue;
6814 (*tiargs)[j] = ea;
6816 if (ea.op == EXP.type)
6818 ta = ea.type;
6819 goto Ltype;
6821 if (ea.op == EXP.scope_)
6823 sa = ea.isScopeExp().sds;
6824 goto Ldsym;
6826 if (FuncExp fe = ea.isFuncExp())
6828 /* A function literal, that is passed to template and
6829 * already semanticed as function pointer, never requires
6830 * outer frame. So convert it to global function is valid.
6832 if (fe.fd.tok == TOK.reserved && fe.type.ty == Tpointer)
6834 // change to non-nested
6835 fe.fd.tok = TOK.function_;
6836 fe.fd.vthis = null;
6838 else if (fe.td)
6840 /* If template argument is a template lambda,
6841 * get template declaration itself. */
6842 //sa = fe.td;
6843 //goto Ldsym;
6846 if (ea.op == EXP.dotVariable && !(flags & 1))
6848 // translate expression to dsymbol.
6849 sa = ea.isDotVarExp().var;
6850 goto Ldsym;
6852 if (auto te = ea.isTemplateExp())
6854 sa = te.td;
6855 goto Ldsym;
6857 if (ea.op == EXP.dotTemplateDeclaration && !(flags & 1))
6859 // translate expression to dsymbol.
6860 sa = ea.isDotTemplateExp().td;
6861 goto Ldsym;
6863 if (auto de = ea.isDotExp())
6865 if (auto se = de.e2.isScopeExp())
6867 sa = se.sds;
6868 goto Ldsym;
6872 else if (sa)
6874 Ldsym:
6875 //printf("dsym %s %s\n", sa.kind(), sa.toChars());
6876 if (sa.errors)
6878 err = true;
6879 continue;
6882 TupleDeclaration d = sa.toAlias().isTupleDeclaration();
6883 if (d)
6885 if (d is atd)
6887 (*tiargs)[j] = d;
6888 continue;
6890 // Expand tuple
6891 tiargs.remove(j);
6892 tiargs.insert(j, d.objects);
6893 j--;
6894 continue;
6896 if (FuncAliasDeclaration fa = sa.isFuncAliasDeclaration())
6898 FuncDeclaration f = fa.toAliasFunc();
6899 if (!fa.hasOverloads && f.isUnique())
6901 // Strip FuncAlias only when the aliased function
6902 // does not have any overloads.
6903 sa = f;
6906 (*tiargs)[j] = sa;
6908 TemplateDeclaration td = sa.isTemplateDeclaration();
6909 if (td && td.semanticRun == PASS.initial && td.literal)
6911 td.dsymbolSemantic(sc);
6913 FuncDeclaration fd = sa.isFuncDeclaration();
6914 if (fd)
6915 fd.functionSemantic();
6917 else if (isParameter(o))
6920 else
6922 assert(0);
6924 //printf("1: (*tiargs)[%d] = %p\n", j, (*tiargs)[j]);
6926 version (none)
6928 printf("-TemplateInstance.semanticTiargs()\n");
6929 for (size_t j = 0; j < tiargs.length; j++)
6931 RootObject o = (*tiargs)[j];
6932 Type ta = isType(o);
6933 Expression ea = isExpression(o);
6934 Dsymbol sa = isDsymbol(o);
6935 Tuple va = isTuple(o);
6936 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
6939 return !err;
6942 /**********************************
6943 * Run semantic on the elements of tiargs.
6944 * Input:
6945 * sc
6946 * Returns:
6947 * false if one or more arguments have errors.
6948 * Note:
6949 * This function is reentrant against error occurrence. If returns false,
6950 * all elements of tiargs won't be modified.
6952 extern (D) final bool semanticTiargs(Scope* sc)
6954 //printf("+TemplateInstance.semanticTiargs() %s\n", toChars());
6955 if (semantictiargsdone)
6956 return true;
6957 if (semanticTiargs(loc, sc, tiargs, 0))
6959 // cache the result iff semantic analysis succeeded entirely
6960 semantictiargsdone = 1;
6961 return true;
6963 return false;
6966 /**********************************
6967 * Find the TemplateDeclaration that matches this TemplateInstance best.
6969 * Params:
6970 * sc = the scope this TemplateInstance resides in
6971 * argumentList = function arguments in case of a template function
6973 * Returns:
6974 * `true` if a match was found, `false` otherwise
6976 extern (D) final bool findBestMatch(Scope* sc, ArgumentList argumentList)
6978 if (havetempdecl)
6980 TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
6981 assert(tempdecl);
6982 assert(tempdecl._scope);
6983 // Deduce tdtypes
6984 tdtypes.setDim(tempdecl.parameters.length);
6985 if (!tempdecl.matchWithInstance(sc, this, &tdtypes, argumentList, 2))
6987 .error(loc, "%s `%s` incompatible arguments for template instantiation", kind, toPrettyChars);
6988 return false;
6990 // TODO: Normalizing tiargs for https://issues.dlang.org/show_bug.cgi?id=7469 is necessary?
6991 return true;
6994 static if (LOG)
6996 printf("TemplateInstance.findBestMatch()\n");
6999 uint errs = global.errors;
7000 TemplateDeclaration td_last = null;
7001 Objects dedtypes;
7003 /* Since there can be multiple TemplateDeclaration's with the same
7004 * name, look for the best match.
7006 auto tovers = tempdecl.isOverloadSet();
7007 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
7009 TemplateDeclaration td_best;
7010 TemplateDeclaration td_ambig;
7011 MATCH m_best = MATCH.nomatch;
7013 Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7014 overloadApply(dstart, (Dsymbol s)
7016 auto td = s.isTemplateDeclaration();
7017 if (!td)
7018 return 0;
7019 if (td == td_best) // skip duplicates
7020 return 0;
7022 //printf("td = %s\n", td.toPrettyChars());
7023 // If more arguments than parameters,
7024 // then this is no match.
7025 if (td.parameters.length < tiargs.length)
7027 if (!td.isVariadic())
7028 return 0;
7031 dedtypes.setDim(td.parameters.length);
7032 dedtypes.zero();
7033 assert(td.semanticRun != PASS.initial);
7035 MATCH m = td.matchWithInstance(sc, this, &dedtypes, argumentList, 0);
7036 //printf("matchWithInstance = %d\n", m);
7037 if (m == MATCH.nomatch) // no match at all
7038 return 0;
7039 if (m < m_best) goto Ltd_best;
7040 if (m > m_best) goto Ltd;
7042 // Disambiguate by picking the most specialized TemplateDeclaration
7044 MATCH c1 = td.leastAsSpecialized(sc, td_best, argumentList);
7045 MATCH c2 = td_best.leastAsSpecialized(sc, td, argumentList);
7046 //printf("c1 = %d, c2 = %d\n", c1, c2);
7047 if (c1 > c2) goto Ltd;
7048 if (c1 < c2) goto Ltd_best;
7051 td_ambig = td;
7052 return 0;
7054 Ltd_best:
7055 // td_best is the best match so far
7056 td_ambig = null;
7057 return 0;
7059 Ltd:
7060 // td is the new best match
7061 td_ambig = null;
7062 td_best = td;
7063 m_best = m;
7064 tdtypes.setDim(dedtypes.length);
7065 memcpy(tdtypes.tdata(), dedtypes.tdata(), tdtypes.length * (void*).sizeof);
7066 return 0;
7069 if (td_ambig)
7071 .error(loc, "%s `%s.%s` matches more than one template declaration:",
7072 td_best.kind(), td_best.parent.toPrettyChars(), td_best.ident.toChars());
7073 .errorSupplemental(td_best.loc, "`%s`\nand:", td_best.toChars());
7074 .errorSupplemental(td_ambig.loc, "`%s`", td_ambig.toChars());
7075 return false;
7077 if (td_best)
7079 if (!td_last)
7080 td_last = td_best;
7081 else if (td_last != td_best)
7083 ScopeDsymbol.multiplyDefined(loc, td_last, td_best);
7084 return false;
7089 if (td_last)
7091 /* https://issues.dlang.org/show_bug.cgi?id=7469
7092 * Normalize tiargs by using corresponding deduced
7093 * template value parameters and tuples for the correct mangling.
7095 * By doing this before hasNestedArgs, CTFEable local variable will be
7096 * accepted as a value parameter. For example:
7098 * void foo() {
7099 * struct S(int n) {} // non-global template
7100 * const int num = 1; // CTFEable local variable
7101 * S!num s; // S!1 is instantiated, not S!num
7104 size_t dim = td_last.parameters.length - (td_last.isVariadic() ? 1 : 0);
7105 for (size_t i = 0; i < dim; i++)
7107 if (tiargs.length <= i)
7108 tiargs.push(tdtypes[i]);
7109 assert(i < tiargs.length);
7111 auto tvp = (*td_last.parameters)[i].isTemplateValueParameter();
7112 if (!tvp)
7113 continue;
7114 assert(tdtypes[i]);
7115 // tdtypes[i] is already normalized to the required type in matchArg
7117 (*tiargs)[i] = tdtypes[i];
7119 if (td_last.isVariadic() && tiargs.length == dim && tdtypes[dim])
7121 Tuple va = isTuple(tdtypes[dim]);
7122 assert(va);
7123 tiargs.pushSlice(va.objects[]);
7126 else if (errors && inst)
7128 // instantiation was failed with error reporting
7129 assert(global.errors);
7130 return false;
7132 else
7134 auto tdecl = tempdecl.isTemplateDeclaration();
7136 if (errs != global.errors)
7137 errorSupplemental(loc, "while looking for match for `%s`", toChars());
7138 else if (tdecl && !tdecl.overnext)
7140 // Only one template, so we can give better error message
7141 const(char)* msg = "does not match template declaration";
7142 const(char)* tip;
7143 const tmsg = tdecl.toCharsNoConstraints();
7144 const cmsg = tdecl.getConstraintEvalError(tip);
7145 if (cmsg)
7147 .error(loc, "%s `%s` %s `%s`\n%s", kind, toPrettyChars, msg, tmsg, cmsg);
7148 if (tip)
7149 .tip(tip);
7151 else
7153 .error(loc, "%s `%s` %s `%s`", kind, toPrettyChars, msg, tmsg);
7155 if (tdecl.parameters.length == tiargs.length)
7157 // https://issues.dlang.org/show_bug.cgi?id=7352
7158 // print additional information, e.g. `foo` is not a type
7159 foreach (i, param; *tdecl.parameters)
7161 MATCH match = param.matchArg(loc, sc, tiargs, i, tdecl.parameters, &dedtypes, null);
7162 auto arg = (*tiargs)[i];
7163 auto sym = arg.isDsymbol;
7164 auto exp = arg.isExpression;
7166 if (exp)
7167 exp = exp.optimize(WANTvalue);
7169 if (match == MATCH.nomatch &&
7170 ((sym && sym.isFuncDeclaration) ||
7171 (exp && exp.isVarExp)))
7173 if (param.isTemplateTypeParameter)
7174 errorSupplemental(loc, "`%s` is not a type", arg.toChars);
7175 else if (auto tvp = param.isTemplateValueParameter)
7176 errorSupplemental(loc, "`%s` is not of a value of type `%s`",
7177 arg.toChars, tvp.valType.toChars);
7184 else
7186 .error(loc, "%s `%s` does not match any template declaration", kind(), toPrettyChars());
7187 bool found;
7188 overloadApply(tempdecl, (s){
7189 if (!found)
7190 errorSupplemental(loc, "Candidates are:");
7191 found = true;
7192 errorSupplemental(s.loc, "%s", s.toChars());
7193 return 0;
7196 return false;
7199 /* The best match is td_last
7201 tempdecl = td_last;
7203 static if (LOG)
7205 printf("\tIt's a match with template declaration '%s'\n", tempdecl.toChars());
7207 return (errs == global.errors);
7210 /*****************************************************
7211 * Determine if template instance is really a template function,
7212 * and that template function needs to infer types from the function
7213 * arguments.
7215 * Like findBestMatch, iterate possible template candidates,
7216 * but just looks only the necessity of type inference.
7218 extern (D) final bool needsTypeInference(Scope* sc, int flag = 0)
7220 //printf("TemplateInstance.needsTypeInference() %s\n", toChars());
7221 if (semanticRun != PASS.initial)
7222 return false;
7224 uint olderrs = global.errors;
7225 Objects dedtypes;
7226 size_t count = 0;
7228 auto tovers = tempdecl.isOverloadSet();
7229 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
7231 Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7232 int r = overloadApply(dstart, (Dsymbol s)
7234 auto td = s.isTemplateDeclaration();
7235 if (!td)
7236 return 0;
7238 /* If any of the overloaded template declarations need inference,
7239 * then return true
7241 if (!td.onemember)
7242 return 0;
7243 if (auto td2 = td.onemember.isTemplateDeclaration())
7245 if (!td2.onemember || !td2.onemember.isFuncDeclaration())
7246 return 0;
7247 if (tiargs.length >= td.parameters.length - (td.isVariadic() ? 1 : 0))
7248 return 0;
7249 return 1;
7251 auto fd = td.onemember.isFuncDeclaration();
7252 if (!fd || fd.type.ty != Tfunction)
7253 return 0;
7255 foreach (tp; *td.parameters)
7257 if (tp.isTemplateThisParameter())
7258 return 1;
7261 /* Determine if the instance arguments, tiargs, are all that is necessary
7262 * to instantiate the template.
7264 //printf("tp = %p, td.parameters.length = %d, tiargs.length = %d\n", tp, td.parameters.length, tiargs.length);
7265 auto tf = cast(TypeFunction)fd.type;
7266 if (tf.parameterList.length)
7268 auto tp = td.isVariadic();
7269 if (tp && td.parameters.length > 1)
7270 return 1;
7272 if (!tp && tiargs.length < td.parameters.length)
7274 // Can remain tiargs be filled by default arguments?
7275 foreach (size_t i; tiargs.length .. td.parameters.length)
7277 if (!(*td.parameters)[i].hasDefaultArg())
7278 return 1;
7282 foreach (i, fparam; tf.parameterList)
7284 // 'auto ref' needs inference.
7285 if (fparam.storageClass & STC.auto_)
7286 return 1;
7290 if (!flag)
7292 /* Calculate the need for overload resolution.
7293 * When only one template can match with tiargs, inference is not necessary.
7295 dedtypes.setDim(td.parameters.length);
7296 dedtypes.zero();
7297 if (td.semanticRun == PASS.initial)
7299 if (td._scope)
7301 // Try to fix forward reference. Ungag errors while doing so.
7302 Ungag ungag = td.ungagSpeculative();
7303 td.dsymbolSemantic(td._scope);
7305 if (td.semanticRun == PASS.initial)
7307 .error(loc, "%s `%s` `%s` forward references template declaration `%s`", kind, toPrettyChars, toChars(), td.toChars());
7308 return 1;
7311 MATCH m = td.matchWithInstance(sc, this, &dedtypes, ArgumentList(), 0);
7312 if (m == MATCH.nomatch)
7313 return 0;
7316 /* If there is more than one function template which matches, we may
7317 * need type inference (see https://issues.dlang.org/show_bug.cgi?id=4430)
7319 return ++count > 1 ? 1 : 0;
7321 if (r)
7322 return true;
7325 if (olderrs != global.errors)
7327 if (!global.gag)
7329 errorSupplemental(loc, "while looking for match for `%s`", toChars());
7330 semanticRun = PASS.semanticdone;
7331 inst = this;
7333 errors = true;
7335 //printf("false\n");
7336 return false;
7339 /*****************************************
7340 * Determines if a TemplateInstance will need a nested
7341 * generation of the TemplateDeclaration.
7342 * Sets enclosing property if so, and returns != 0;
7344 extern (D) final bool hasNestedArgs(Objects* args, bool isstatic)
7346 int nested = 0;
7347 //printf("TemplateInstance.hasNestedArgs('%s')\n", tempdecl.ident.toChars());
7349 // arguments from parent instances are also accessible
7350 if (!enclosing)
7352 if (TemplateInstance ti = tempdecl.toParent().isTemplateInstance())
7353 enclosing = ti.enclosing;
7356 /* A nested instance happens when an argument references a local
7357 * symbol that is on the stack.
7359 foreach (o; *args)
7361 Expression ea = isExpression(o);
7362 Dsymbol sa = isDsymbol(o);
7363 Tuple va = isTuple(o);
7364 if (ea)
7366 if (auto ve = ea.isVarExp())
7368 sa = ve.var;
7369 goto Lsa;
7371 if (auto te = ea.isThisExp())
7373 sa = te.var;
7374 goto Lsa;
7376 if (auto fe = ea.isFuncExp())
7378 if (fe.td)
7379 sa = fe.td;
7380 else
7381 sa = fe.fd;
7382 goto Lsa;
7384 // Emulate Expression.toMangleBuffer call that had exist in TemplateInstance.genIdent.
7385 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)
7387 if (!ea.type.isTypeError())
7388 .error(ea.loc, "%s `%s` expression `%s` is not a valid template value argument", kind, toPrettyChars, ea.toChars());
7389 errors = true;
7392 else if (sa)
7394 Lsa:
7395 sa = sa.toAlias();
7396 TemplateDeclaration td = sa.isTemplateDeclaration();
7397 if (td)
7399 TemplateInstance ti = sa.toParent().isTemplateInstance();
7400 if (ti && ti.enclosing)
7401 sa = ti;
7403 TemplateInstance ti = sa.isTemplateInstance();
7404 Declaration d = sa.isDeclaration();
7405 if ((td && td.literal) || (ti && ti.enclosing) || (d && !d.isDataseg() && !(d.storage_class & STC.manifest) && (!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) && !isTemplateMixin()))
7407 Dsymbol dparent = sa.toParent2();
7408 if (!dparent || dparent.isModule)
7409 goto L1;
7410 else if (!enclosing)
7411 enclosing = dparent;
7412 else if (enclosing != dparent)
7414 /* Select the more deeply nested of the two.
7415 * Error if one is not nested inside the other.
7417 for (Dsymbol p = enclosing; p; p = p.parent)
7419 if (p == dparent)
7420 goto L1; // enclosing is most nested
7422 for (Dsymbol p = dparent; p; p = p.parent)
7424 if (p == enclosing)
7426 enclosing = dparent;
7427 goto L1; // dparent is most nested
7430 //https://issues.dlang.org/show_bug.cgi?id=17870
7431 if (dparent.isClassDeclaration() && enclosing.isClassDeclaration())
7433 auto pc = dparent.isClassDeclaration();
7434 auto ec = enclosing.isClassDeclaration();
7435 if (pc.isBaseOf(ec, null))
7436 goto L1;
7437 else if (ec.isBaseOf(pc, null))
7439 enclosing = dparent;
7440 goto L1;
7443 .error(loc, "%s `%s` `%s` is nested in both `%s` and `%s`", kind, toPrettyChars, toChars(), enclosing.toChars(), dparent.toChars());
7444 errors = true;
7447 //printf("\tnested inside %s as it references %s\n", enclosing.toChars(), sa.toChars());
7448 nested |= 1;
7451 else if (va)
7453 nested |= cast(int)hasNestedArgs(&va.objects, isstatic);
7456 //printf("-TemplateInstance.hasNestedArgs('%s') = %d\n", tempdecl.ident.toChars(), nested);
7457 return nested != 0;
7460 /*****************************************
7461 * Append 'this' to the specific module members[]
7463 extern (D) final Dsymbols* appendToModuleMember()
7465 Module mi = minst; // instantiated . inserted module
7467 //printf("%s.appendToModuleMember() enclosing = %s mi = %s\n",
7468 // toPrettyChars(),
7469 // enclosing ? enclosing.toPrettyChars() : null,
7470 // mi ? mi.toPrettyChars() : null);
7471 if (global.params.allInst || !mi || mi.isRoot())
7473 /* If the instantiated module is speculative or root, insert to the
7474 * member of a root module. Then:
7475 * - semantic3 pass will get called on the instance members.
7476 * - codegen pass will get a selection chance to do/skip it (needsCodegen()).
7478 static Dsymbol getStrictEnclosing(TemplateInstance ti)
7482 if (ti.enclosing)
7483 return ti.enclosing;
7484 ti = ti.tempdecl.isInstantiated();
7485 } while (ti);
7486 return null;
7489 Dsymbol enc = getStrictEnclosing(this);
7490 // insert target is made stable by using the module
7491 // where tempdecl is declared.
7492 mi = (enc ? enc : tempdecl).getModule();
7493 if (!mi.isRoot())
7495 if (mi.importedFrom)
7497 mi = mi.importedFrom;
7498 assert(mi.isRoot());
7500 else
7502 // This can happen when using the frontend as a library.
7503 // Append it to the non-root module.
7507 else
7509 /* If the instantiated module is non-root, insert to the member of the
7510 * non-root module. Then:
7511 * - semantic3 pass won't be called on the instance.
7512 * - codegen pass won't reach to the instance.
7513 * Unless it is re-appended to a root module later (with changed minst).
7516 //printf("\t-. mi = %s\n", mi.toPrettyChars());
7518 if (memberOf) // already appended to some module
7520 assert(mi.isRoot(), "can only re-append to a root module");
7521 if (memberOf.isRoot())
7522 return null; // no need to move to another root module
7525 Dsymbols* a = mi.members;
7526 a.push(this);
7527 memberOf = mi;
7528 if (mi.semanticRun >= PASS.semantic2done && mi.isRoot())
7529 Module.addDeferredSemantic2(this);
7530 if (mi.semanticRun >= PASS.semantic3done && mi.isRoot())
7531 Module.addDeferredSemantic3(this);
7532 return a;
7535 /****************************************************
7536 * Declare parameters of template instance, initialize them with the
7537 * template instance arguments.
7539 extern (D) final void declareParameters(Scope* sc)
7541 TemplateDeclaration tempdecl = this.tempdecl.isTemplateDeclaration();
7542 assert(tempdecl);
7544 //printf("TemplateInstance.declareParameters()\n");
7545 foreach (i, o; tdtypes) // initializer for tp
7547 TemplateParameter tp = (*tempdecl.parameters)[i];
7548 //printf("\ttdtypes[%d] = %p\n", i, o);
7549 tempdecl.declareParameter(sc, tp, o);
7553 /****************************************
7554 * This instance needs an identifier for name mangling purposes.
7555 * Create one by taking the template declaration name and adding
7556 * the type signature for it.
7558 extern (D) final Identifier genIdent(Objects* args)
7560 //printf("TemplateInstance.genIdent('%s')\n", tempdecl.ident.toChars());
7561 assert(args is tiargs);
7562 OutBuffer buf;
7563 mangleToBuffer(this, buf);
7564 //printf("\tgenIdent = %s\n", buf.peekChars());
7565 return Identifier.idPool(buf[]);
7568 extern (D) final void expandMembers(Scope* sc2)
7570 members.foreachDsymbol( (s) { s.setScope (sc2); } );
7572 members.foreachDsymbol( (s) { s.importAll(sc2); } );
7574 if (!aliasdecl)
7576 /* static if's are crucial to evaluating aliasdecl correctly. But
7577 * evaluating the if/else bodies may require aliasdecl.
7578 * So, evaluate the condition for static if's, but not their if/else bodies.
7579 * Then try to set aliasdecl.
7580 * Later do the if/else bodies.
7581 * https://issues.dlang.org/show_bug.cgi?id=23598
7582 * It might be better to do this by attaching a lambda to the StaticIfDeclaration
7583 * to do the oneMembers call after the sid.include(sc2) is run as part of dsymbolSemantic().
7585 bool done;
7586 void staticIfDg(Dsymbol s)
7588 if (done || aliasdecl)
7589 return;
7590 //printf("\t staticIfDg on '%s %s' in '%s'\n", s.kind(), s.toChars(), this.toChars());
7591 if (!s.isStaticIfDeclaration())
7593 //s.dsymbolSemantic(sc2);
7594 done = true;
7595 return;
7597 auto sid = s.isStaticIfDeclaration();
7598 sid.include(sc2);
7599 if (members.length)
7601 Dsymbol sa;
7602 if (Dsymbol.oneMembers(members, &sa, tempdecl.ident) && sa)
7603 aliasdecl = sa;
7605 done = true;
7608 members.foreachDsymbol(&staticIfDg);
7611 void symbolDg(Dsymbol s)
7613 //printf("\t semantic on '%s' %p kind %s in '%s'\n", s.toChars(), s, s.kind(), this.toChars());
7614 //printf("test: enclosing = %d, sc2.parent = %s\n", enclosing, sc2.parent.toChars());
7615 //if (enclosing)
7616 // s.parent = sc.parent;
7617 //printf("test3: enclosing = %d, s.parent = %s\n", enclosing, s.parent.toChars());
7618 s.dsymbolSemantic(sc2);
7619 //printf("test4: enclosing = %d, s.parent = %s\n", enclosing, s.parent.toChars());
7620 Module.runDeferredSemantic();
7623 members.foreachDsymbol(&symbolDg);
7626 extern (D) final void tryExpandMembers(Scope* sc2)
7628 __gshared int nest;
7629 // extracted to a function to allow windows SEH to work without destructors in the same function
7630 //printf("%d\n", nest);
7631 if (++nest > global.recursionLimit)
7633 global.gag = 0; // ensure error message gets printed
7634 .error(loc, "%s `%s` recursive expansion exceeded allowed nesting limit", kind, toPrettyChars);
7635 fatal();
7638 expandMembers(sc2);
7640 nest--;
7643 extern (D) final void trySemantic3(Scope* sc2)
7645 // extracted to a function to allow windows SEH to work without destructors in the same function
7646 __gshared int nest;
7647 //printf("%d\n", nest);
7648 if (++nest > global.recursionLimit)
7650 global.gag = 0; // ensure error message gets printed
7651 .error(loc, "%s `%s` recursive expansion exceeded allowed nesting limit", kind, toPrettyChars);
7652 fatal();
7655 semantic3(this, sc2);
7657 --nest;
7660 override final inout(TemplateInstance) isTemplateInstance() inout
7662 return this;
7665 override void accept(Visitor v)
7667 v.visit(this);
7671 /**************************************
7672 * IsExpression can evaluate the specified type speculatively, and even if
7673 * it instantiates any symbols, they are normally unnecessary for the
7674 * final executable.
7675 * However, if those symbols leak to the actual code, compiler should remark
7676 * them as non-speculative to generate their code and link to the final executable.
7678 void unSpeculative(Scope* sc, RootObject o)
7680 if (!o)
7681 return;
7683 if (Tuple tup = isTuple(o))
7685 foreach (obj; tup.objects)
7687 unSpeculative(sc, obj);
7689 return;
7692 Dsymbol s = getDsymbol(o);
7693 if (!s)
7694 return;
7696 if (Declaration d = s.isDeclaration())
7698 if (VarDeclaration vd = d.isVarDeclaration())
7699 o = vd.type;
7700 else if (AliasDeclaration ad = d.isAliasDeclaration())
7702 o = ad.getType();
7703 if (!o)
7704 o = ad.toAlias();
7706 else
7707 o = d.toAlias();
7709 s = getDsymbol(o);
7710 if (!s)
7711 return;
7714 if (TemplateInstance ti = s.isTemplateInstance())
7716 // If the instance is already non-speculative,
7717 // or it is leaked to the speculative scope.
7718 if (ti.minst !is null || sc.minst is null)
7719 return;
7721 // Remark as non-speculative instance.
7722 ti.minst = sc.minst;
7723 if (!ti.tinst)
7724 ti.tinst = sc.tinst;
7726 unSpeculative(sc, ti.tempdecl);
7729 if (TemplateInstance ti = s.isInstantiated())
7730 unSpeculative(sc, ti);
7733 /**********************************
7734 * Return true if e could be valid only as a template value parameter.
7735 * Return false if it might be an alias or tuple.
7736 * (Note that even in this case, it could still turn out to be a value).
7738 bool definitelyValueParameter(Expression e) @safe
7740 // None of these can be value parameters
7741 if (e.op == EXP.tuple || e.op == EXP.scope_ ||
7742 e.op == EXP.type || e.op == EXP.dotType ||
7743 e.op == EXP.template_ || e.op == EXP.dotTemplateDeclaration ||
7744 e.op == EXP.function_ || e.op == EXP.error ||
7745 e.op == EXP.this_ || e.op == EXP.super_ ||
7746 e.op == EXP.dot)
7747 return false;
7749 if (e.op != EXP.dotVariable)
7750 return true;
7752 /* Template instantiations involving a DotVar expression are difficult.
7753 * In most cases, they should be treated as a value parameter, and interpreted.
7754 * But they might also just be a fully qualified name, which should be treated
7755 * as an alias.
7758 // x.y.f cannot be a value
7759 FuncDeclaration f = e.isDotVarExp().var.isFuncDeclaration();
7760 if (f)
7761 return false;
7763 while (e.op == EXP.dotVariable)
7765 e = e.isDotVarExp().e1;
7767 // this.x.y and super.x.y couldn't possibly be valid values.
7768 if (e.op == EXP.this_ || e.op == EXP.super_)
7769 return false;
7771 // e.type.x could be an alias
7772 if (e.op == EXP.dotType)
7773 return false;
7775 // var.x.y is the only other possible form of alias
7776 if (e.op != EXP.variable)
7777 return true;
7779 VarDeclaration v = e.isVarExp().var.isVarDeclaration();
7780 // func.x.y is not an alias
7781 if (!v)
7782 return true;
7784 // https://issues.dlang.org/show_bug.cgi?id=16685
7785 // var.x.y where var is a constant available at compile time
7786 if (v.storage_class & STC.manifest)
7787 return true;
7789 // TODO: Should we force CTFE if it is a global constant?
7790 return false;
7793 /***********************************************************
7794 * https://dlang.org/spec/template-mixin.html
7795 * Syntax:
7796 * mixin MixinTemplateName [TemplateArguments] [Identifier];
7798 extern (C++) final class TemplateMixin : TemplateInstance
7800 TypeQualified tqual;
7802 extern (D) this(const ref Loc loc, Identifier ident, TypeQualified tqual, Objects* tiargs)
7804 super(loc,
7805 tqual.idents.length ? cast(Identifier)tqual.idents[tqual.idents.length - 1] : (cast(TypeIdentifier)tqual).ident,
7806 tiargs ? tiargs : new Objects());
7807 //printf("TemplateMixin(ident = '%s')\n", ident ? ident.toChars() : "");
7808 this.ident = ident;
7809 this.tqual = tqual;
7812 override TemplateInstance syntaxCopy(Dsymbol s)
7814 auto tm = new TemplateMixin(loc, ident, tqual.syntaxCopy(), tiargs);
7815 return TemplateInstance.syntaxCopy(tm);
7818 override const(char)* kind() const
7820 return "mixin";
7823 override bool oneMember(Dsymbol* ps, Identifier ident)
7825 return Dsymbol.oneMember(ps, ident);
7828 override bool hasPointers()
7830 //printf("TemplateMixin.hasPointers() %s\n", toChars());
7831 return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
7834 override const(char)* toChars() const
7836 OutBuffer buf;
7837 toCBufferInstance(this, buf);
7838 return buf.extractChars();
7841 extern (D) bool findTempDecl(Scope* sc)
7843 // Follow qualifications to find the TemplateDeclaration
7844 if (!tempdecl)
7846 Expression e;
7847 Type t;
7848 Dsymbol s;
7849 tqual.resolve(loc, sc, e, t, s);
7850 if (!s)
7852 .error(loc, "%s `%s` is not defined", kind, toPrettyChars);
7853 return false;
7855 s = s.toAlias();
7856 tempdecl = s.isTemplateDeclaration();
7857 OverloadSet os = s.isOverloadSet();
7859 /* If an OverloadSet, look for a unique member that is a template declaration
7861 if (os)
7863 Dsymbol ds = null;
7864 foreach (i, sym; os.a)
7866 Dsymbol s2 = sym.isTemplateDeclaration();
7867 if (s2)
7869 if (ds)
7871 tempdecl = os;
7872 break;
7874 ds = s2;
7878 if (!tempdecl)
7880 .error(loc, "%s `%s` - `%s` is a %s, not a template", kind, toPrettyChars, s.toChars(), s.kind());
7881 return false;
7884 assert(tempdecl);
7886 // Look for forward references
7887 auto tovers = tempdecl.isOverloadSet();
7888 foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
7890 Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
7891 int r = overloadApply(dstart, (Dsymbol s)
7893 auto td = s.isTemplateDeclaration();
7894 if (!td)
7895 return 0;
7897 if (td.semanticRun == PASS.initial)
7899 if (td._scope)
7900 td.dsymbolSemantic(td._scope);
7901 else
7903 semanticRun = PASS.initial;
7904 return 1;
7907 return 0;
7909 if (r)
7910 return false;
7912 return true;
7915 override inout(TemplateMixin) isTemplateMixin() inout
7917 return this;
7920 override void accept(Visitor v)
7922 v.visit(this);
7926 /************************************
7927 * This struct is needed for TemplateInstance to be the key in an associative array.
7928 * Fixing https://issues.dlang.org/show_bug.cgi?id=15812 and
7929 * https://issues.dlang.org/show_bug.cgi?id=15813 would make it unnecessary.
7931 struct TemplateInstanceBox
7933 TemplateInstance ti;
7935 this(TemplateInstance ti)
7937 this.ti = ti;
7938 this.ti.toHash();
7939 assert(this.ti.hash);
7942 size_t toHash() const @trusted pure nothrow
7944 assert(ti.hash);
7945 return ti.hash;
7948 bool opEquals(ref const TemplateInstanceBox s) @trusted const
7950 bool res = void;
7951 if (ti.inst && s.ti.inst)
7953 /* This clause is only used when an instance with errors
7954 * is replaced with a correct instance.
7956 res = ti is s.ti;
7958 else
7960 /* Used when a proposed instance is used to see if there's
7961 * an existing instance.
7963 static if (__VERSION__ < 2099) // https://issues.dlang.org/show_bug.cgi?id=22717
7964 res = (cast()s.ti).equalsx(cast()ti);
7965 else
7966 res = (cast()ti).equalsx(cast()s.ti);
7969 debug (FindExistingInstance) ++(res ? nHits : nCollisions);
7970 return res;
7973 debug (FindExistingInstance)
7975 __gshared uint nHits, nCollisions;
7977 shared static ~this()
7979 printf("debug (FindExistingInstance) TemplateInstanceBox.equals hits: %u collisions: %u\n",
7980 nHits, nCollisions);
7985 /*******************************************
7986 * Match to a particular TemplateParameter.
7987 * Input:
7988 * instLoc location that the template is instantiated.
7989 * tiargs[] actual arguments to template instance
7990 * i i'th argument
7991 * parameters[] template parameters
7992 * dedtypes[] deduced arguments to template instance
7993 * *psparam set to symbol declared and initialized to dedtypes[i]
7995 MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
7997 MATCH matchArgNoMatch()
7999 if (psparam)
8000 *psparam = null;
8001 return MATCH.nomatch;
8004 MATCH matchArgParameter()
8006 RootObject oarg;
8008 if (i < tiargs.length)
8009 oarg = (*tiargs)[i];
8010 else
8012 // Get default argument instead
8013 oarg = tp.defaultArg(instLoc, sc);
8014 if (!oarg)
8016 assert(i < dedtypes.length);
8017 // It might have already been deduced
8018 oarg = (*dedtypes)[i];
8019 if (!oarg)
8020 return matchArgNoMatch();
8023 return tp.matchArg(sc, oarg, i, parameters, dedtypes, psparam);
8026 MATCH matchArgTuple(TemplateTupleParameter ttp)
8028 /* The rest of the actual arguments (tiargs[]) form the match
8029 * for the variadic parameter.
8031 assert(i + 1 == dedtypes.length); // must be the last one
8032 Tuple ovar;
8034 if (Tuple u = isTuple((*dedtypes)[i]))
8036 // It has already been deduced
8037 ovar = u;
8039 else if (i + 1 == tiargs.length && isTuple((*tiargs)[i]))
8040 ovar = isTuple((*tiargs)[i]);
8041 else
8043 ovar = new Tuple();
8044 //printf("ovar = %p\n", ovar);
8045 if (i < tiargs.length)
8047 //printf("i = %d, tiargs.length = %d\n", i, tiargs.length);
8048 ovar.objects.setDim(tiargs.length - i);
8049 foreach (j, ref obj; ovar.objects)
8050 obj = (*tiargs)[i + j];
8053 return ttp.matchArg(sc, ovar, i, parameters, dedtypes, psparam);
8056 if (auto ttp = tp.isTemplateTupleParameter())
8057 return matchArgTuple(ttp);
8058 else
8059 return matchArgParameter();
8062 MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, Objects* dedtypes, Declaration* psparam)
8064 MATCH matchArgNoMatch()
8066 //printf("\tm = %d\n", MATCH.nomatch);
8067 if (psparam)
8068 *psparam = null;
8069 return MATCH.nomatch;
8072 MATCH matchArgType(TemplateTypeParameter ttp)
8074 //printf("TemplateTypeParameter.matchArg('%s')\n", ttp.ident.toChars());
8075 MATCH m = MATCH.exact;
8076 Type ta = isType(oarg);
8077 if (!ta)
8079 //printf("%s %p %p %p\n", oarg.toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
8080 return matchArgNoMatch();
8082 //printf("ta is %s\n", ta.toChars());
8084 if (ttp.specType)
8086 if (!ta || ta == TemplateTypeParameter.tdummy)
8087 return matchArgNoMatch();
8089 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta.toChars(), ttp.specType.toChars());
8090 MATCH m2 = deduceType(ta, sc, ttp.specType, parameters, dedtypes);
8091 if (m2 == MATCH.nomatch)
8093 //printf("\tfailed deduceType\n");
8094 return matchArgNoMatch();
8097 if (m2 < m)
8098 m = m2;
8099 if ((*dedtypes)[i])
8101 Type t = cast(Type)(*dedtypes)[i];
8103 if (ttp.dependent && !t.equals(ta)) // https://issues.dlang.org/show_bug.cgi?id=14357
8104 return matchArgNoMatch();
8106 /* This is a self-dependent parameter. For example:
8107 * template X(T : T*) {}
8108 * template X(T : S!T, alias S) {}
8110 //printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
8111 ta = t;
8114 else
8116 if ((*dedtypes)[i])
8118 // Must match already deduced type
8119 Type t = cast(Type)(*dedtypes)[i];
8121 if (!t.equals(ta))
8123 //printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
8124 return matchArgNoMatch();
8127 else
8129 // So that matches with specializations are better
8130 m = MATCH.convert;
8133 (*dedtypes)[i] = ta;
8135 if (psparam)
8136 *psparam = new AliasDeclaration(ttp.loc, ttp.ident, ta);
8137 //printf("\tm = %d\n", m);
8138 return ttp.dependent ? MATCH.exact : m;
8141 MATCH matchArgValue(TemplateValueParameter tvp)
8143 //printf("TemplateValueParameter.matchArg('%s')\n", tvp.ident.toChars());
8144 MATCH m = MATCH.exact;
8146 Expression ei = isExpression(oarg);
8147 Type vt;
8149 if (!ei && oarg)
8151 Dsymbol si = isDsymbol(oarg);
8152 FuncDeclaration f = si ? si.isFuncDeclaration() : null;
8153 if (!f || !f.fbody || f.needThis())
8154 return matchArgNoMatch();
8156 ei = new VarExp(tvp.loc, f);
8157 ei = ei.expressionSemantic(sc);
8159 /* If a function is really property-like, and then
8160 * it's CTFEable, ei will be a literal expression.
8162 uint olderrors = global.startGagging();
8163 ei = resolveProperties(sc, ei);
8164 ei = ei.ctfeInterpret();
8165 if (global.endGagging(olderrors) || ei.op == EXP.error)
8166 return matchArgNoMatch();
8168 /* https://issues.dlang.org/show_bug.cgi?id=14520
8169 * A property-like function can match to both
8170 * TemplateAlias and ValueParameter. But for template overloads,
8171 * it should always prefer alias parameter to be consistent
8172 * template match result.
8174 * template X(alias f) { enum X = 1; }
8175 * template X(int val) { enum X = 2; }
8176 * int f1() { return 0; } // CTFEable
8177 * int f2(); // body-less function is not CTFEable
8178 * enum x1 = X!f1; // should be 1
8179 * enum x2 = X!f2; // should be 1
8181 * e.g. The x1 value must be same even if the f1 definition will be moved
8182 * into di while stripping body code.
8184 m = MATCH.convert;
8187 if (ei && ei.op == EXP.variable)
8189 // Resolve const variables that we had skipped earlier
8190 ei = ei.ctfeInterpret();
8193 //printf("\tvalType: %s, ty = %d\n", tvp.valType.toChars(), tvp.valType.ty);
8194 vt = tvp.valType.typeSemantic(tvp.loc, sc);
8195 //printf("ei: %s, ei.type: %s\n", ei.toChars(), ei.type.toChars());
8196 //printf("vt = %s\n", vt.toChars());
8198 if (ei.type)
8200 MATCH m2 = ei.implicitConvTo(vt);
8201 //printf("m: %d\n", m);
8202 if (m2 < m)
8203 m = m2;
8204 if (m == MATCH.nomatch)
8205 return matchArgNoMatch();
8206 ei = ei.implicitCastTo(sc, vt);
8207 ei = ei.ctfeInterpret();
8210 if (tvp.specValue)
8212 if (ei is null || (cast(void*)ei.type in TemplateValueParameter.edummies &&
8213 TemplateValueParameter.edummies[cast(void*)ei.type] == ei))
8214 return matchArgNoMatch();
8216 Expression e = tvp.specValue;
8218 sc = sc.startCTFE();
8219 e = e.expressionSemantic(sc);
8220 e = resolveProperties(sc, e);
8221 sc = sc.endCTFE();
8222 e = e.implicitCastTo(sc, vt);
8223 e = e.ctfeInterpret();
8225 ei = ei.syntaxCopy();
8226 sc = sc.startCTFE();
8227 ei = ei.expressionSemantic(sc);
8228 sc = sc.endCTFE();
8229 ei = ei.implicitCastTo(sc, vt);
8230 ei = ei.ctfeInterpret();
8231 //printf("\tei: %s, %s\n", ei.toChars(), ei.type.toChars());
8232 //printf("\te : %s, %s\n", e.toChars(), e.type.toChars());
8233 if (!ei.equals(e))
8234 return matchArgNoMatch();
8236 else
8238 if ((*dedtypes)[i])
8240 // Must match already deduced value
8241 Expression e = cast(Expression)(*dedtypes)[i];
8242 if (!ei || !ei.equals(e))
8243 return matchArgNoMatch();
8246 (*dedtypes)[i] = ei;
8248 if (psparam)
8250 Initializer _init = new ExpInitializer(tvp.loc, ei);
8251 Declaration sparam = new VarDeclaration(tvp.loc, vt, tvp.ident, _init);
8252 sparam.storage_class = STC.manifest;
8253 *psparam = sparam;
8255 return tvp.dependent ? MATCH.exact : m;
8258 MATCH matchArgAlias(TemplateAliasParameter tap)
8260 //printf("TemplateAliasParameter.matchArg('%s')\n", tap.ident.toChars());
8261 MATCH m = MATCH.exact;
8262 Type ta = isType(oarg);
8263 RootObject sa = ta && !ta.deco ? null : getDsymbol(oarg);
8264 Expression ea = isExpression(oarg);
8265 if (ea)
8267 if (auto te = ea.isThisExp())
8268 sa = te.var;
8269 else if (auto se = ea.isSuperExp())
8270 sa = se.var;
8271 else if (auto se = ea.isScopeExp())
8272 sa = se.sds;
8274 if (sa)
8276 if ((cast(Dsymbol)sa).isAggregateDeclaration())
8277 m = MATCH.convert;
8279 /* specType means the alias must be a declaration with a type
8280 * that matches specType.
8282 if (tap.specType)
8284 tap.specType = typeSemantic(tap.specType, tap.loc, sc);
8285 Declaration d = (cast(Dsymbol)sa).isDeclaration();
8286 if (!d)
8287 return matchArgNoMatch();
8288 if (!d.type.equals(tap.specType))
8289 return matchArgNoMatch();
8292 else
8294 sa = oarg;
8295 if (ea)
8297 if (tap.specType)
8299 if (!ea.type.equals(tap.specType))
8300 return matchArgNoMatch();
8303 else if (ta && ta.ty == Tinstance && !tap.specAlias)
8305 /* Specialized parameter should be preferred
8306 * match to the template type parameter.
8307 * template X(alias a) {} // a == this
8308 * template X(alias a : B!A, alias B, A...) {} // B!A => ta
8311 else if (sa && sa == TemplateTypeParameter.tdummy)
8313 /* https://issues.dlang.org/show_bug.cgi?id=2025
8314 * Aggregate Types should preferentially
8315 * match to the template type parameter.
8316 * template X(alias a) {} // a == this
8317 * template X(T) {} // T => sa
8320 else if (ta && ta.ty != Tident)
8322 /* Match any type that's not a TypeIdentifier to alias parameters,
8323 * but prefer type parameter.
8324 * template X(alias a) { } // a == ta
8326 * TypeIdentifiers are excluded because they might be not yet resolved aliases.
8328 m = MATCH.convert;
8330 else
8331 return matchArgNoMatch();
8334 if (tap.specAlias)
8336 if (sa == TemplateAliasParameter.sdummy)
8337 return matchArgNoMatch();
8338 // check specialization if template arg is a symbol
8339 Dsymbol sx = isDsymbol(sa);
8340 if (sa != tap.specAlias && sx)
8342 Type talias = isType(tap.specAlias);
8343 if (!talias)
8344 return matchArgNoMatch();
8346 TemplateInstance ti = sx.isTemplateInstance();
8347 if (!ti && sx.parent)
8349 ti = sx.parent.isTemplateInstance();
8350 if (ti && ti.name != sx.ident)
8351 return matchArgNoMatch();
8353 if (!ti)
8354 return matchArgNoMatch();
8356 Type t = new TypeInstance(Loc.initial, ti);
8357 MATCH m2 = deduceType(t, sc, talias, parameters, dedtypes);
8358 if (m2 == MATCH.nomatch)
8359 return matchArgNoMatch();
8361 // check specialization if template arg is a type
8362 else if (ta)
8364 if (Type tspec = isType(tap.specAlias))
8366 MATCH m2 = ta.implicitConvTo(tspec);
8367 if (m2 == MATCH.nomatch)
8368 return matchArgNoMatch();
8370 else
8372 error(tap.loc, "template parameter specialization for a type must be a type and not `%s`",
8373 tap.specAlias.toChars());
8374 return matchArgNoMatch();
8378 else if ((*dedtypes)[i])
8380 // Must match already deduced symbol
8381 RootObject si = (*dedtypes)[i];
8382 if (!sa || si != sa)
8383 return matchArgNoMatch();
8385 (*dedtypes)[i] = sa;
8387 if (psparam)
8389 if (Dsymbol s = isDsymbol(sa))
8391 *psparam = new AliasDeclaration(tap.loc, tap.ident, s);
8393 else if (Type t = isType(sa))
8395 *psparam = new AliasDeclaration(tap.loc, tap.ident, t);
8397 else
8399 assert(ea);
8401 // Declare manifest constant
8402 Initializer _init = new ExpInitializer(tap.loc, ea);
8403 auto v = new VarDeclaration(tap.loc, null, tap.ident, _init);
8404 v.storage_class = STC.manifest;
8405 v.dsymbolSemantic(sc);
8406 *psparam = v;
8409 return tap.dependent ? MATCH.exact : m;
8412 MATCH matchArgTuple(TemplateTupleParameter ttp)
8414 //printf("TemplateTupleParameter.matchArg('%s')\n", ttp.ident.toChars());
8415 Tuple ovar = isTuple(oarg);
8416 if (!ovar)
8417 return MATCH.nomatch;
8418 if ((*dedtypes)[i])
8420 Tuple tup = isTuple((*dedtypes)[i]);
8421 if (!tup)
8422 return MATCH.nomatch;
8423 if (!match(tup, ovar))
8424 return MATCH.nomatch;
8426 (*dedtypes)[i] = ovar;
8428 if (psparam)
8429 *psparam = new TupleDeclaration(ttp.loc, ttp.ident, &ovar.objects);
8430 return ttp.dependent ? MATCH.exact : MATCH.convert;
8433 if (auto ttp = tp.isTemplateTypeParameter())
8434 return matchArgType(ttp);
8435 else if (auto tvp = tp.isTemplateValueParameter())
8436 return matchArgValue(tvp);
8437 else if (auto tap = tp.isTemplateAliasParameter())
8438 return matchArgAlias(tap);
8439 else if (auto ttp = tp.isTemplateTupleParameter())
8440 return matchArgTuple(ttp);
8441 else
8442 assert(0);
8446 /***********************************************
8447 * Collect and print statistics on template instantiations.
8449 struct TemplateStats
8451 __gshared TemplateStats[const void*] stats;
8453 uint numInstantiations; // number of instantiations of the template
8454 uint uniqueInstantiations; // number of unique instantiations of the template
8456 TemplateInstances* allInstances;
8458 /*******************************
8459 * Add this instance
8461 static void incInstance(const TemplateDeclaration td,
8462 const TemplateInstance ti)
8464 void log(ref TemplateStats ts)
8466 if (ts.allInstances is null)
8467 ts.allInstances = new TemplateInstances();
8468 if (global.params.v.templatesListInstances)
8469 ts.allInstances.push(cast() ti);
8472 // message(ti.loc, "incInstance %p %p", td, ti);
8473 if (!global.params.v.templates)
8474 return;
8475 if (!td)
8476 return;
8477 assert(ti);
8478 if (auto ts = cast(const void*) td in stats)
8480 log(*ts);
8481 ++ts.numInstantiations;
8483 else
8485 stats[cast(const void*) td] = TemplateStats(1, 0);
8486 log(stats[cast(const void*) td]);
8490 /*******************************
8491 * Add this unique instance
8493 static void incUnique(const TemplateDeclaration td,
8494 const TemplateInstance ti)
8496 // message(ti.loc, "incUnique %p %p", td, ti);
8497 if (!global.params.v.templates)
8498 return;
8499 if (!td)
8500 return;
8501 assert(ti);
8502 if (auto ts = cast(const void*) td in stats)
8503 ++ts.uniqueInstantiations;
8504 else
8505 stats[cast(const void*) td] = TemplateStats(0, 1);
8509 extern (C++) void printTemplateStats()
8511 static struct TemplateDeclarationStats
8513 TemplateDeclaration td;
8514 TemplateStats ts;
8515 static int compare(scope const TemplateDeclarationStats* a,
8516 scope const TemplateDeclarationStats* b) @safe nothrow @nogc pure
8518 auto diff = b.ts.uniqueInstantiations - a.ts.uniqueInstantiations;
8519 if (diff)
8520 return diff;
8521 else
8522 return b.ts.numInstantiations - a.ts.numInstantiations;
8526 if (!global.params.v.templates)
8527 return;
8529 Array!(TemplateDeclarationStats) sortedStats;
8530 sortedStats.reserve(TemplateStats.stats.length);
8531 foreach (td_, ref ts; TemplateStats.stats)
8533 sortedStats.push(TemplateDeclarationStats(cast(TemplateDeclaration) td_, ts));
8536 sortedStats.sort!(TemplateDeclarationStats.compare);
8538 foreach (const ref ss; sortedStats[])
8540 if (global.params.v.templatesListInstances &&
8541 ss.ts.allInstances)
8543 message(ss.td.loc,
8544 "vtemplate: %u (%u distinct) instantiation(s) of template `%s` found, they are:",
8545 ss.ts.numInstantiations,
8546 ss.ts.uniqueInstantiations,
8547 ss.td.toCharsNoConstraints());
8548 foreach (const ti; (*ss.ts.allInstances)[])
8550 if (ti.tinst) // if has enclosing instance
8551 message(ti.loc, "vtemplate: implicit instance `%s`", ti.toChars());
8552 else
8553 message(ti.loc, "vtemplate: explicit instance `%s`", ti.toChars());
8556 else
8558 message(ss.td.loc,
8559 "vtemplate: %u (%u distinct) instantiation(s) of template `%s` found",
8560 ss.ts.numInstantiations,
8561 ss.ts.uniqueInstantiations,
8562 ss.td.toCharsNoConstraints());
8567 /// Pair of MATCHes
8568 private struct MATCHpair
8570 MATCH mta; /// match template parameters by initial template arguments
8571 MATCH mfa; /// match template parameters by inferred template arguments
8573 debug this(MATCH mta, MATCH mfa)
8575 assert(MATCH.min <= mta && mta <= MATCH.max);
8576 assert(MATCH.min <= mfa && mfa <= MATCH.max);
8577 this.mta = mta;
8578 this.mfa = mfa;
8582 private void write(ref OutBuffer buf, RootObject obj)
8584 if (obj)
8586 buf.writestring(obj.toChars());