-
-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[New DIP] Multiple Template constraints #131
base: master
Are you sure you want to change the base?
Conversation
Thanks, @thewilsonator. Please set the status to Draft. |
Done |
Sorry for the dev in queue, but I am going to change this somewhat because I've had a better idea. |
That is `if` is to static foreach and static assert what `in` is to foreach and assert.
|
What good does that do? You already know that the template is false. What Petar was talking about was reporting the exact reason why the template returned false. The best that the compiler can do is run any CNF parts of the template, which this DIP says nothing about and does not preclude from happening. |
You will note that the DIP is called "Expression and Block Statement Template Constraints". |
@thewilsonator I'm not Peter, but I think that's not what he was talking about. if (isArrayLike!R) // use the err msg phobos devs wrote So off the top of my head, I came up with a way to show what I meant. The following is just an example, and probably not a very good idea: Assume struct BoolWithErr {
bool b;
string error;
alias b this;
} And in template isArrayLike(T) {
...
else static if (!is(typeof(T.init.popBack)))
enum isArrayLike = BoolWithErr(false, T.stringof~" does not have popBack");
else
...
} Then, when
The main motivation and benefit of this DIP is to have clearer and more understandable error messages, not having a template constraint block. IMO this title still does not convey that. |
That works fine for single template constraints, its even a good idea, but it is orthogonal to this DIP even if it is made feasible by it.
It is consistent with the rest of the DIPs whose title describes what, and the rationale describes why. |
Yes. Having multiple if's and if blocks itself is a good idea. I should've said "this solution is missing parts that would make it more practical", rather than "this is not a good solution". |
~~[OT] Hahaha, https://issues.dlang.org/show_bug.cgi?id=19203 ~~ This got fixed. |
@yshui @ZombineDev Ahh, you mean like https://run.dlang.io/is/yzotl4 (will work as a |
Hmm actually it might be better to do something like template isInputRange(T)
{
@("is(typeof(R.init) == R)") enum canInit = is(typeof(R.init) == R);
@("is(ReturnType!((R r) => r.empty) == bool") enum hasEmpty = is(ReturnType!((R r) => r.empty) == bool;
...
enum bool isInputRange = canInit && hasEmpty && ...;
} to save on compile time. Anyway, point being, this is all this is all independent of the DIP. |
@thewilsonator For better error messages, what about Atila's concepts library? |
Thanks, I had completely forgotten about that. Constraints of the form void checkFoo(T)()
{
T t = T.init;
t.foo();
}
enum isFoo(T) = is(typeof(checkFoo!T)); Would be easy to give nice errors for (now that I've seen how concepts does it), but I'm wary of proscribing in this DIP what must happen beyond the grammar since concepts and this DIP solve the same problem (better error messages) but in a different problem space: Concepts are for range/container writers validating that their code is e.g. an input range. Whereas this DIP is for algorithm writers (and their users) to validate the constraints of the algorithm, this includes non-modelling-type constraints like making sure predicates are valid. Put another way if/when this goes in there are a number of possible solutions to the problem of more information about unsatisfied constraints (which is now much more granular than before) and I don't want to make that decision up front because I don't know what the other solutions would look like. I do like the concepts solution though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the whole idea. I thought that perhaps we could simply highlight the failing parts in the boolean expression, but this provides so much better power AND gives the compiler easy ability to show the line if that's all that's needed. Only downside compared to parsing the existing format out is that you have to change your constraints to take advantage.
Such is the price of progress. |
The new Dlangoliers tool will take care of it and eat up your past constraints. |
What? |
I thought after Voldemort types, we'd recreate Dfix with a Stephen King reference. Breaking changes or just new methods to do old things mean that at some point someone (or a tool) will go over the code and remove traces of the old ways. Langoliers are creatures that erase the past by literally eating it up. |
DIPs/DIP1xxx.md
Outdated
bool all(Range)(Range range) | ||
if (isInputRange!Range) | ||
if (is(typeof(unaryFun!pred(range.front))), | ||
"`" ~ pred.stringof[1..$-1] ~ "` isn't a unary predicate function for range.front")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variant isn't equivalent to the two below, right? Presenting three forms of the same equivalent contracts would help comparing them.
Co-Authored-By: thewilsonator <[email protected]>
@thewilsonator Please email me! |
It's been a while. In the meantime the constraint error reporting has gotten much better: void foo(T, U)(T t, U u) if (is(T == int) && is(U == int)) {}
void main()
{
foo("hello", 4);
}
Is this DIP still necessary? |
@schveiguy As an aside, I am still finding some cases where the template deduction error messages could use some improvement. I just filed this for the case of template parameter default values. |
@jmh530 Thanks, that does look like it needs work. But if fixed, I still am wondering if this DIP is relevant. At the least, it needs updating, as some of the rationale no longer applies. |
@schveiguy One year later I still think we have a very long way to go in terms template error messages. See my previous comment for more details: #131 (comment) |
@PetarKirov agreed. One of the most frustrating things is, if you fail something like At the same time, this DIP doesn't seem to address any of that. |
This is a DIP to enable the compiler to emit better error messages for constrained template overloads and better document the constraints when reading the source. Essentially
if
constraints become thestatic
equivalent ofin
contracts (assert
andforeach
becomestatic assert
andstatic foreach
). Expression (á la DIP1009 but for constraints) and block statement forms are allowed.The static foreach section is to deal with constraints expressed over template variable arguments, as these are currently expressed as recursive templates which do not give nice error messages with the base DIP. The source is still able to convey the meaning with the constrains with messages.This is superseded by block constraints.