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