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

Source: dtemplate.d

  • 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.

  • Declaration

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

    Is this Object an error?

  • Declaration

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

    Are any of the Objects an error?

  • Declaration

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

    Try to get arg as a type.

  • Declaration

    class TemplateDeclaration: dmd.dsymbol.ScopeDsymbol;

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

    • Declaration

      bool isTrivialAliasSeq;

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

    • Declaration

      bool isTrivialAlias;

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

    • Declaration

      bool deprecated_;

      this template declaration is deprecated

    • Declaration

      int inuse;

      for recursive expansion detection

    • Declaration

      bool overloadInsert(Dsymbol s);

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

    • Declaration

      const const(char)* toCharsNoConstraints();

      Similar to toChars, but does not print the template constraints

    • Declaration

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

      Check to see if constraint is satisfied.

    • 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

    • 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

    • Declaration

      MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, Expressions* fargs, 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.

    • Declaration

      MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, Expressions* fargs);

      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

    • Declaration

      MATCH deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, Expressions* fargs);

      Match function arguments against a specific template function.

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

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

      Return Value

      match level bit 0-3 Match template parameters by inferred template arguments bit 4-7 Match template parameters by initial template arguments

    • Declaration

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

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

    • Declaration

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

      Limited function template instantiation for using fd.leastAsSpecialized()

    • 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.

    • 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.

    • Declaration

      void removeInstance(TemplateInstance ti);

      Remove TemplateInstance from table of instances.

      Input: handle returned by addInstance()

    • 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

    • Declaration

      const bool isOverloadable();

      We can overload templates.

  • Declaration

    void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, Type tthis, Expressions* fargs, 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

    Expressions* fargs

    arguments to function

    const(char)** pMessage

    address to store error message, or null

  • 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.

  • Declaration

    abstract class TemplateParameter: dmd.ast_node.ASTNode;

  • Declaration

    class TemplateTypeParameter: dmd.dtemplate.TemplateParameter;

    Syntax: ident : specType = defaultType

  • Declaration

    class TemplateThisParameter: dmd.dtemplate.TemplateTypeParameter;

    Syntax: this ident : specType = defaultType

  • Declaration

    class TemplateValueParameter: dmd.dtemplate.TemplateParameter;

    Syntax: valType ident : specValue = defaultValue

  • Declaration

    class TemplateAliasParameter: dmd.dtemplate.TemplateParameter;

    Syntax: specType ident : specAlias = defaultAlias

  • Declaration

    class TemplateTupleParameter: dmd.dtemplate.TemplateParameter;

  • Declaration

    class TemplateInstance: dmd.dsymbol.ScopeDsymbol;

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

    • Declaration

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

      has semanticTiargs() been done?

    • Declaration

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

      if used second constructor

    • Declaration

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

      if the instantiation is done with error gagging

    • Declaration

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

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

    • 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.

    • Declaration

      final Identifier getIdent();

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

    • 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

    • 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.

    • 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.

    • 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.

    • 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.

    • Declaration

      static bool semanticTiargs(ref const Loc loc, Scope* sc, Objects* tiargs, int flags);

      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

      Return Value

      false if one or more arguments have errors.

    • 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.

    • Declaration

      final bool findBestMatch(Scope* sc, Expressions* fargs);

      Find the TemplateDeclaration that matches this TemplateInstance best.

      Parameters

      Scope* sc

      the scope this TemplateInstance resides in

      Expressions* fargs

      function arguments in case of a template function, null otherwise

      Return Value

      true if a match was found, false otherwise

    • 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.

    • 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;

    • Declaration

      final Dsymbols* appendToModuleMember();

      Append 'this' to the specific module members[]

    • Declaration

      final void declareParameters(Scope* sc);

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

    • 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.

  • 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.

  • 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).

  • Declaration

    class TemplateMixin: dmd.dtemplate.TemplateInstance;

    Syntax: mixin MixinTemplateName [TemplateArguments] Identifier;

  • 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.

  • 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]

  • Declaration

    struct TemplateStats;

    Collect and print statistics on template instantiations.

    • Declaration

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

      Add this instance

    • Declaration

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

      Add this unique instance