October 24, 2023 [Issue 24197] New: Allow typeof(return) in template constraints | ||||
---|---|---|---|---|
| ||||
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@puremagic.com Reporter: qs.il.paperinik@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. -- |
Copyright © 1999-2021 by the D Language Foundation