[Issue 24197] New: Allow typeof(return) in template constraints
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Tue Oct 24 15:32:43 UTC 2023
https://issues.dlang.org/show_bug.cgi?id=24197
Issue ID: 24197
Summary: Allow typeof(return) in template constraints
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: enhancement
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: qs.il.paperinik at gmail.com
This is from the first question of [DConf '23 Day 2
Keynote](https://youtu.be/3iWn4S8JV8g?t=2323): How do I communicate to the user
of a function template that the return type is a range?
The compiler has all it needs to check it (per template instance). We just
cannot express it with D’s syntax.
I see two solutions:
SOLUTION 1: Make template `if` constraints work with `typeof(return)` even if
it’s inferred by deferring the constraint check.
SOLUTION 2: Introduce a new kind of template constraint that’s checked after
instantiation, a template `assert`.
I’d guess that Solution 2 is easier to implement and communicates better. I
like both solutions, tho.
## Solution 1
I have no idea how templates are compiled and how their constraints are
checked, but I’ll assume the constraints are checked before the body is
instantiated.
Of course if `typeof(return)` targets an inferred return type, it cannot be
checked before instantiating the template.
Because a template constraint is a logical expression tree composed of `&&`s,
`||`s and `!`s and other expressions as leafs, I’d imagine it like this:
1. Leaves that contain `typeof(return)` are pretended to be `true` if the leaf
is under an even number of negations, otherwise `false`. (They’re essentially
skipped.)
2. Then the template is instantiated. If there were `typeof(return)` in step 1,
errors are throttled.
3. If the template has constraints with `typeof(return)` (that were skipped),
now that the return type is known, the constraints are checked again.
(Constraints without `typeof(return)` could be pretended `true` or `false` as
above.) If the constraint evaluates to `true`, there were `typeof(return)` in
step 1, and throttled errors in step 2, then report the errors of step 2.
For the most part, constraints will look like this:
```d
auto someAlgo(R)(R range)
if (isInputRange!R && isInputRange!(typeof(return)))
{ … }
```
## Solution 2
An alternative would be a new construct next to template constraints. I suggest
`assert`; while constraints are checked as one of the first steps of template
instantiation, template `assert`s would be checked as one of the last steps (at
a point the return type is successfully inferred).
```d
auto someAlgo(R)(R range)
if (isInputRange!R)
assert (isInputRange!(typeof(return)))
{ … }
```
The template `assert` would be essentially a `static assert` the same way a
template `if` constraint essentially is a `static if`.
Template `if` and template `assert` are the compile-time/static analogue of
runtime `in` and `out` function contracts.
--
More information about the Digitalmars-d-bugs
mailing list