# dmd.dtemplate

Defines `TemplateDeclaration`, `TemplateInstance` and a few utilities

#### Discussion

This modules holds the two main template types: `TemplateDeclaration`, which is the user-provided declaration of a template, and `TemplateInstance`, which is an instance of a `TemplateDeclaration` with specific arguments.

Template Parameter: Additionally, the classes for template parameters are defined in this module. The base class, `TemplateParameter`, is inherited by:

- `TemplateTypeParameter`
- `TemplateThisParameter`
- `TemplateValueParameter`
- `TemplateAliasParameter`
- `TemplateTupleParameter`

Templates semantic: The start of the template instantiation process looks like this:

- A `TypeInstance` or `TypeIdentifier` is encountered. `TypeInstance` have a bang (e.g. `Foo!(arg)`) while `TypeIdentifier` don't.
- A `TemplateInstance` is instantiated
- Semantic is run on the `TemplateInstance` (see `dmd.dsymbolsem`)
- The `TemplateInstance` search for its `TemplateDeclaration`, runs semantic on the template arguments and deduce the best match among the possible overloads.
- The `TemplateInstance` search for existing instances with the same arguments, and uses it if found.
- Otherwise, the rest of semantic is run on the `TemplateInstance`.

#### Authors

Walter Bright

#### License

Boost License 1.0

Source: dtemplate.d

Documentation: https://dlang.org/phobos/dmd_dtemplate.html

Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dtemplate.d

- `isExpression`

  #### Declaration

  `pure nothrow @nogc inout(Expression) `isExpression`(inout RootObject `o`);`

  These functions substitute for dynamic_cast. dynamic_cast does not work on earlier versions of gcc.

- `isError`

  #### Declaration

  `pure nothrow @nogc bool `isError`(const RootObject `o`);`

  Is this Object an error?

- `arrayObjectIsError`

  #### Declaration

  `pure nothrow @nogc bool `arrayObjectIsError`(const Objects* `args`);`

  Are any of the Objects an error?

- `getType`

  #### Declaration

  `pure nothrow @nogc inout(Type) `getType`(inout RootObject `o`);`

  Try to get arg as a type.

- `TemplateDeclaration`

  #### Declaration

  `class `TemplateDeclaration`: dmd.dsymbol.ScopeDsymbol;`

  [mixin] template Identifier (parameters) [Constraint] https://dlang.org/spec/template.html https://dlang.org/spec/template-mixin.html

  - `isTrivialAliasSeq`

    #### Declaration

    `bool `isTrivialAliasSeq`;`

    matches pattern `template AliasSeq(T...) { alias AliasSeq = T; }`

  - `isTrivialAlias`

    #### Declaration

    `bool `isTrivialAlias`;`

    matches pattern `template Alias(T) { alias Alias = qualifiers(T); }`

  - `deprecated_`

    #### Declaration

    `bool `deprecated_`;`

    this template declaration is deprecated

  - `overloadInsert`

    #### Declaration

    `bool `overloadInsert`(Dsymbol `s`);`

    Overload existing TemplateDeclaration 'this' with the new one '`s`'. Return `true` if successful; i.e. no conflict.

  - `toCharsNoConstraints`

    #### Declaration

    `const const(char)* `toCharsNoConstraints`();`

    Similar to `toChars`, but does not print the template constraints

  - `evaluateConstraint`

    #### Declaration

    `bool `evaluateConstraint`(TemplateInstance `ti`, Scope* `sc`, Scope* `paramscope`, Objects* `dedargs`, FuncDeclaration `fd`);`

    Check to see if constraint is satisfied.

  - `getConstraintEvalError`

    #### Declaration

    `const(char)* `getConstraintEvalError`(ref const(char)* `tip`);`

    Destructively get the error message from the last constraint evaluation

    #### Parameters

    `const(char)* `tip`` | `tip` to show after printing all overloads

  - `scopeForTemplateParameters`

    #### Declaration

    `Scope* `scopeForTemplateParameters`(TemplateInstance `ti`, Scope* `sc`);`

    Create a scope for the parameters of the TemplateInstance ``ti`` in the parent scope `sc` from the ScopeDsymbol paramsym.

    #### Discussion

    If paramsym is `null` a new ScopeDsymbol is used in place of paramsym.

    #### Parameters

    `TemplateInstance `ti`` | the TemplateInstance whose parameters to generate the scope for.
    `Scope* `sc`` | the parent scope of `ti`

    #### Return Value

    a scope for the parameters of `ti`

  - `matchWithInstance`

    #### Declaration

    `MATCH `matchWithInstance`(Scope* `sc`, TemplateInstance `ti`, Objects* `dedtypes`, ArgumentList `argumentList`, int `flag`);`

    Given that `ti` is an instance of this TemplateDeclaration, deduce the types of the parameters to this, and store those deduced types in `dedtypes`[].

    Input: `flag` 1: don't do semantic() because of dummy types 2: don't change types in matchArg()

    Output: `dedtypes` deduced arguments Return match level.

  - `leastAsSpecialized`

    #### Declaration

    `MATCH `leastAsSpecialized`(Scope* `sc`, TemplateDeclaration `td2`, ArgumentList `argumentList`);`

    Determine partial specialization order of 'this' vs `td2`.

    #### Return Value

    match this is at least as specialized as `td2` 0 `td2` is more specialized than this

  - `deduceFunctionTemplateMatch`

    #### Declaration

    `MATCHpair `deduceFunctionTemplateMatch`(TemplateInstance `ti`, Scope* `sc`, ref FuncDeclaration `fd`, Type `tthis`, ArgumentList `argumentList`);`

    Match function arguments against a specific template function.

    Input: `ti` `sc` instantiation scope `fd` `tthis` 'this' argument if !NULL `argumentList` arguments to function

    Output: `fd` Partially instantiated function declaration `ti`.tdtypes Expression/Type deduced template arguments

    #### Return Value

    match pair of initial and inferred template arguments

  - `declareParameter`

    #### Declaration

    `RootObject `declareParameter`(Scope* `sc`, TemplateParameter `tp`, RootObject `o`);`

    Declare template parameter `tp` with value `o`, and install it in the scope `sc`.

  - `doHeaderInstantiation`

    #### Declaration

    `FuncDeclaration `doHeaderInstantiation`(TemplateInstance `ti`, Scope* `sc2`, FuncDeclaration `fd`, Type `tthis`, Expressions* `fargs`);`

    Limited function template instantiation for using `fd`.leastAsSpecialized()

  - `findExistingInstance`

    #### Declaration

    `TemplateInstance `findExistingInstance`(TemplateInstance `tithis`, Expressions* `fargs`);`

    Given a new instance `tithis` of this TemplateDeclaration, see if there already exists an instance. If so, return that existing instance.

  - `addInstance`

    #### Declaration

    `TemplateInstance `addInstance`(TemplateInstance `ti`);`

    Add instance `ti` to TemplateDeclaration's table of instances. Return a handle we can use to later remove it if it fails instantiation.

  - `removeInstance`

    #### Declaration

    `void `removeInstance`(TemplateInstance `ti`);`

    Remove TemplateInstance from table of instances.

    Input: handle returned by addInstance()

  - `isVariadic`

    #### Declaration

    `TemplateTupleParameter `isVariadic`();`

    Check if the last template parameter is a tuple one, and returns it if so, else returns `null`.

    #### Return Value

    The last template parameter if it's a `TemplateTupleParameter`

  - `isOverloadable`

    #### Declaration

    `const bool `isOverloadable`();`

    We can overload templates.

- `functionResolve`

  #### Declaration

  `void `functionResolve`(ref MatchAccumulator `m`, Dsymbol `dstart`, Loc `loc`, Scope* `sc`, Objects* `tiargs`, Type `tthis`, ArgumentList `argumentList`, const(char)** `pMessage` = null);`

  Given function arguments, figure out which template function to expand, and return matching result.

  #### Parameters

  `MatchAccumulator `m`` | matching result
  `Dsymbol `dstart`` | the root of overloaded function templates
  `Loc `loc`` | instantiation location
  `Scope* `sc`` | instantiation scope
  `Objects* `tiargs`` | initial list of template arguments
  `Type `tthis`` | if !NULL, the 'this' pointer argument
  `ArgumentList `argumentList`` | arguments to function
  `const(char)** `pMessage`` | address to store error message, or `null`

- `reliesOnTident`

  #### Declaration

  `bool `reliesOnTident`(Type `t`, TemplateParameters* `tparams`, size_t `iStart` = 0);`

  Check whether the type `t` representation relies on one or more the template parameters.

  #### Parameters

  `Type `t`` | Tested type, if `null`, returns `false`.
  `TemplateParameters* `tparams`` | Template parameters.
  `size_t `iStart`` | Start index of `tparams` to limit the tested parameters. If it's nonzero, `tparams`[0..`iStart`] will be excluded from the test target.

- `TemplateParameter`

  #### Declaration

  `abstract class `TemplateParameter`: dmd.ast_node.ASTNode;`

  https://dlang.org/spec/template.html#TemplateParameter

- `TemplateTypeParameter`

  #### Declaration

  `class `TemplateTypeParameter`: dmd.dtemplate.TemplateParameter;`

  https://dlang.org/spec/template.html#TemplateTypeParameter

  Syntax: ident : specType = defaultType

- `TemplateThisParameter`

  #### Declaration

  `class `TemplateThisParameter`: dmd.dtemplate.TemplateTypeParameter;`

  https://dlang.org/spec/template.html#TemplateThisParameter

  Syntax: this ident : specType = defaultType

- `TemplateValueParameter`

  #### Declaration

  `class `TemplateValueParameter`: dmd.dtemplate.TemplateParameter;`

  https://dlang.org/spec/template.html#TemplateValueParameter

  Syntax: valType ident : specValue = defaultValue

- `TemplateAliasParameter`

  #### Declaration

  `class `TemplateAliasParameter`: dmd.dtemplate.TemplateParameter;`

  https://dlang.org/spec/template.html#TemplateAliasParameter

  Syntax: specType ident : specAlias = defaultAlias

- `TemplateTupleParameter`

  #### Declaration

  `class `TemplateTupleParameter`: dmd.dtemplate.TemplateParameter;`

  https://dlang.org/spec/template.html#TemplateSequenceParameter

  Syntax: ident ...

- `TemplateInstance`

  #### Declaration

  `class `TemplateInstance`: dmd.dsymbol.ScopeDsymbol;`

  https://dlang.org/spec/template.html#explicit_tmp_instantiation

  Given: foo!(args) => name = foo tiargs = args

  - `semantictiargsdone`

    #### Declaration

    `final const pure nothrow @nogc @property @safe bool `semantictiargsdone`();`

    has semanticTiargs() been done?

  - `havetempdecl`

    #### Declaration

    `final const pure nothrow @nogc @property @safe bool `havetempdecl`();`

    if used second constructor

  - `gagged`

    #### Declaration

    `final const pure nothrow @nogc @property @safe bool `gagged`();`

    if the instantiation is done with error gagging

  - `this`

    #### Declaration

    `scope this(const ref Loc `loc`, TemplateDeclaration `td`, Objects* `tiargs`);`

    This constructor is only called when we figured out which function template to instantiate.

  - `printInstantiationTrace`

    #### Declaration

    `final void `printInstantiationTrace`(Classification `cl` = Classification.error);`

    Given an error instantiating the TemplateInstance, give the nested TemplateInstance instantiations that got us here. Those are a list threaded into the nested scopes.

  - `getIdent`

    #### Declaration

    `final Identifier `getIdent`();`

    Lazily generate identifier for template instance. This is because 75% of the ident's are never needed.

  - `equalsx`

    #### Declaration

    `final bool `equalsx`(TemplateInstance `ti`);`

    Compare proposed template instantiation with existing template instantiation. Note that this is not commutative because of the auto ref check.

    #### Parameters

    `TemplateInstance `ti`` | existing template instantiation

    #### Return Value

    `true` for match

  - `isDiscardable`

    #### Declaration

    `final bool `isDiscardable`();`

    #### Return Value

    `true` if the instances' innards are discardable.
    The idea of this function is to see if the template instantiation can be 100% replaced with its eponymous member. All other members can be discarded, even in the compiler to free memory (for example, the template could be expanded in a region allocator, deemed trivial, the end result copied back out independently and the entire region freed), and can be elided entirely from the binary.
    The current implementation affects code that generally looks like:

    1. `template foo(args...) { some_basic_type_or_string helper() { .... } enum foo = helper(); }`
    since it was the easiest starting point of implementation but it can and should be expanded more later.
  - `needsCodegen`

    #### Declaration

    `final bool `needsCodegen`();`

    Returns `true` if this is not instantiated in non-root module, and is a part of non-speculative instantiatiation.

    Note: minst does not stabilize until semantic analysis is completed, so don't call this function during semantic analysis to return precise result.

  - `findTempDecl`

    #### Declaration

    `final bool `findTempDecl`(Scope* `sc`, WithScopeSymbol* `pwithsym`);`

    Find template declaration corresponding to template instance.

    #### Return Value

    `false` if finding fails.

    Note: This function is reentrant against error occurrence. If returns `false`, any members of this object won't be modified, and repetition call will reproduce same error.

  - `updateTempDecl`

    #### Declaration

    `final bool `updateTempDecl`(Scope* `sc`, Dsymbol `s`);`

    Confirm `s` is a valid template, then store it.

    Input: `sc` `s` candidate symbol of template. It may be: TemplateDeclaration FuncDeclaration with findTemplateDeclRoot() != NULL OverloadSet which contains candidates

    #### Return Value

    `true` if updating succeeds.

  - `semanticTiargs`

    #### Declaration

    `static bool `semanticTiargs`(const ref Loc `loc`, Scope* `sc`, Objects* `tiargs`, int `flags`, TupleDeclaration `atd` = null);`

    Run semantic of `tiargs` as arguments of template.

    Input: `loc` `sc` `tiargs` array of template arguments `flags` 1: replace const variables with their initializers 2: don't devolve Parameter to Type `atd` tuple being optimized. If found, it's not expanded here but in AliasAssign semantic.

    #### Return Value

    `false` if one or more arguments have errors.

  - `semanticTiargs`

    #### Declaration

    `final bool `semanticTiargs`(Scope* `sc`);`

    Run semantic on the elements of tiargs.

    Input: `sc`

    #### Return Value

    `false` if one or more arguments have errors.

    Note: This function is reentrant against error occurrence. If returns `false`, all elements of tiargs won't be modified.

  - `findBestMatch`

    #### Declaration

    `final bool `findBestMatch`(Scope* `sc`, ArgumentList `argumentList`);`

    Find the TemplateDeclaration that matches this TemplateInstance best.

    #### Parameters

    `Scope* `sc`` | the scope this TemplateInstance resides in
    `ArgumentList `argumentList`` | function arguments in case of a template function

    #### Return Value

    `true` if a match was found, `false` otherwise

  - `needsTypeInference`

    #### Declaration

    `final bool `needsTypeInference`(Scope* `sc`, int `flag` = 0);`

    Determine if template instance is really a template function, and that template function needs to infer types from the function arguments.

    #### Discussion

    Like findBestMatch, iterate possible template candidates, but just looks only the necessity of type inference.

  - `hasNestedArgs`

    #### Declaration

    `final bool `hasNestedArgs`(Objects* `args`, bool `isstatic`);`

    Determines if a TemplateInstance will need a nested generation of the TemplateDeclaration. Sets enclosing property if so, and returns != 0;

  - `appendToModuleMember`

    #### Declaration

    `final Dsymbols* `appendToModuleMember`();`

    Append 'this' to the specific module members[]

  - `declareParameters`

    #### Declaration

    `final void `declareParameters`(Scope* `sc`);`

    Declare parameters of template instance, initialize them with the template instance arguments.

  - `genIdent`

    #### Declaration

    `final Identifier `genIdent`(Objects* `args`);`

    This instance needs an identifier for name mangling purposes. Create one by taking the template declaration name and adding the type signature for it.

- `unSpeculative`

  #### Declaration

  `void `unSpeculative`(Scope* `sc`, RootObject `o`);`

  IsExpression can evaluate the specified type speculatively, and even if it instantiates any symbols, they are normally unnecessary for the final executable. However, if those symbols leak to the actual code, compiler should remark them as non-speculative to generate their code and link to the final executable.

- `definitelyValueParameter`

  #### Declaration

  `bool `definitelyValueParameter`(Expression `e`);`

  Return `true` if `e` could be valid only as a template value parameter. Return `false` if it might be an alias or tuple. (Note that even in this case, it could still turn out to be a value).

- `TemplateMixin`

  #### Declaration

  `class `TemplateMixin`: dmd.dtemplate.TemplateInstance;`

  https://dlang.org/spec/template-mixin.html

  Syntax: mixin MixinTemplateName [TemplateArguments] `Identifier`;

- `TemplateInstanceBox`

  #### Declaration

  `struct `TemplateInstanceBox`;`

  This struct is needed for TemplateInstance to be the key in an associative array. Fixing https://issues.dlang.org/show_bug.cgi?id=15812 and https://issues.dlang.org/show_bug.cgi?id=15813 would make it unnecessary.

- `matchArg`

  #### Declaration

  `MATCH `matchArg`(TemplateParameter `tp`, Loc `instLoc`, Scope* `sc`, Objects* `tiargs`, size_t `i`, TemplateParameters* `parameters`, Objects* `dedtypes`, Declaration* `psparam`);`

  Match to a particular TemplateParameter.

  Input: `instLoc` location that the template is instantiated. `tiargs`[] actual arguments to template instance `i` `i`'th argument `parameters`[] template `parameters` `dedtypes`[] deduced arguments to template instance *`psparam` set to symbol declared and initialized to `dedtypes`[`i`]

- `TemplateStats`

  #### Declaration

  `struct `TemplateStats`;`

  Collect and print statistics on template instantiations.

  - `incInstance`

    #### Declaration

    `static void `incInstance`(const TemplateDeclaration `td`, const TemplateInstance `ti`);`

    Add this instance

  - `incUnique`

    #### Declaration

    `static void `incUnique`(const TemplateDeclaration `td`, const TemplateInstance `ti`);`

    Add this unique instance