Issue 23665 - Add traits to retrieve template parameter information
Summary: Add traits to retrieve template parameter information
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-02-02 16:02 UTC by Bolpat
Modified: 2023-05-09 15:42 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Bolpat 2023-02-02 16:02:51 UTC
Add `__traits` to expose information about a template’s parameters: A template parameter has the following properties:

1. An identifier.
2. A kind: It is a value parameter, a type parameter, an alias parameter, or a sequence parameter. Arguably, a template `this` parameter is a type parameter, but IMO, it should be its own kind.
3. A type if it is a value parameter. (Alias and sequence parameters can be bound to value arguments that have types, but the parameter itself has no type.)
4. Optionally a constraint.
5. Optionally a default.

Chellanges:
1. Only values have types.
2. Types, constraints, and defaults might not be accessible, a symbolic (not a string) return is useful.
3. Types, constraints, and defaults can be dependent on previous paramters; a symbolic return is not possible in that case.


Proposed specification:

First, provide the trait `templateParameterLength` taking an alias to a template that returns the number of (lexical) template parameters. (By lexical, I mean that a sequence parameter counts as exactly 1 parameter, even if logically, it is “0 or many”.)

Note: For the following that take an index, if the index is out of range (≥ `templateParameterLength`), it is a compile error. The wording assumes that the index is in range.

For each template parameter property, provide a trait named `templateParameter(Identifier|Kind|Type|Constraint|Default)`, respectively, taking an alias to a template and an index that returns compile-time information of the respective properties (if available – a parameter might not have a type, constraint, or default).
E.g. `__traits(templateParameterKind, std.meta.AliasSeq, 0)` returns the kind of the only parameter: sequence.

Also provide the trait `templateParameterHas(Type|Constraint|Default)` taking an alias to a template and an index that returns a bool providing information about the availability of that property:
`templateParameterHasType` is a compile-error when the parameter is not of kind value. (The programmer should use `static if` to enusre the parameter queried is of kind value.) It returns `true` if the type is independent of previous template parameters and `false` if it is dependent on them. (This might be a best-effort, i.e. there could be edge cases in which `false` could be returned when `true` is actually possible.)
`templateParameterHas(Constraint|Default)` returns returns `true` if the template parameter has a constraint or default, respectively.

Identifiers are returned as strings (cf. `__traits(identifier)`). Unnamed parameters are syntactically not possible, the string is never empty or `null`.

The kind could be designated by a finite set of strings ("value", "type", "alias", "sequence", and "this") or by values of an `enum`.

`__traits(templateParameterType)` returns a sequence consisting of 1 or 2 entries: The first entry is the string used to define the parameter; the second entry is present and an alias to the type when `__traits(templateParameterHasType)` is `true` (and thus the type is well-defined).

For constraints and defaults, `__traits(templateParameter(Constraint|Default))` compiles if `__traits(templateParameterHas(Constraint|Default))` is `true`. Because constraints and defaults can depend on previous parameters, they cannot always be extracted symbolically. Again, a sequence consisting of 1 or 2 entries is returned: The first entry is the string consisting of the tokens making up the constraint/default, the second is present if the constraint/default is independent of previous parameters and thus can be extracted symbolically.