digitalmars.D - Ideas how to improve template constraint errors
- Martin Nowak (43/43) Dec 05 2013 I'm sitting here trying to figure out why I can't combine join
- Martin Nowak (2/2) Dec 05 2013 Ah well, this was a question for ideas.
- monarch_dodra (38/40) Dec 05 2013 IMO, one of the initial problems is "argument type validation" vs
- bearophile (6/8) Dec 05 2013 Perhaps in D we need some syntax & semantics to differentiate the
- Jason House (17/19) Dec 05 2013 I can think of a few things:
- Martin Nowak (3/3) Dec 05 2013 And a fix for this particular issue.
I'm sitting here trying to figure out why I can't combine join pathSplitter components with pathSeparator. import std.range, std.path; void bug() { auto comps = pathSplitter("foo/bar"); auto path = join(comps, pathSeparator); } This is the error message: path.d(6): Error: template std.array.join does not match any function template declaration. Candidates are: DPL/dmd/src/../../phobos/std/array.d(1559): std.array.join(RoR, R)(RoR ror, R sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && isInputRange!R && is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))) DPL/dmd/src/../../phobos/std/array.d(1606): std.array.join(RoR)(RoR ror) if (isInputRange!RoR && isInputRange!(ElementType!RoR)) path.d(6): Error: template std.array.join(RoR, R)(RoR ror, R sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && isInputRange!R && is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))) cannot deduce template function from argument types !()(PathSplitter, string) This is what I currently have to do to figure out what is going on. // declare types of arguments alias RoR = typeof(comps); alias R = typeof(pathSeparator); // static assert each constraint static assert(isInputRange!RoR); // Bingo! static assert(isInputRange!(ElementType!RoR)); // path.d(9): Error: static assert (isInputRange!(const(char[]))) is false static assert(isInputRange!R); static assert(is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))); A useful error message should be something along this line. path.d(6): Error: Can't call template function 'join' because the element type of 'comps' is not an input range. path.d(6): Error: Can't call template function 'join' because the following constraint failed. isInputRange!(ElementType!RoR), RoR == const(char[]) deduced from argument 'comps'.
Dec 05 2013
Ah well, this was a question for ideas. I don't really know to get there.
Dec 05 2013
On Thursday, 5 December 2013 at 13:55:30 UTC, Martin Nowak wrote:Ah well, this was a question for ideas. I don't really know to get there.IMO, one of the initial problems is "argument type validation" vs "overload resolution". I've talked about this some before: http://forum.dlang.org/thread/znlqobvvdywdskhiriwx forum.dlang.org It's the kind of thing that I think makes some of our constraints too complicated. -------- This would not have helped you in this situation. While a backend solution would be nice, I also think the library can itself keep things in check by limiting gratuitous overloads, when an internal static if will be enough. Also, judicious use of traits can help clarify the situation. In some extreme situations, I think writing an explicit trait that "consolidates" a couple of traits at once helps: Keeping the length of the constraint in check always helps. For example, having a "std.algorithm.areComparableRanges!(R1, R2)" would help a *ton* of algorithms, while keeping things a bit clearer. Keeping them as "package" means we can write them without having to worry too much about public use. -------- Finally, one of the things I had toyed with, but never got to submitting, were "assertive traits". I had written something you could add in code, such as: //---- struct R {...} checkIsRandomAccessRange!R; void main() {} //---- With this, if R was *not* an actual random access range, it failed with an assert that said something along the lines of: R is not a BidirectionalRange because it does not have back. R is not a RandomAccessRange because it is not a BidirectionalRange. While it was quite the useful "trait", it required about 4 times the code to implement as the trait itself, and required parallel maintenance :/
Dec 05 2013
monarch_dodra:IMO, one of the initial problems is "argument type validation" vs "overload resolution".Perhaps in D we need some syntax & semantics to differentiate the two use cases, to make it more clear the difference to the compiler. Bye, bearophile
Dec 05 2013
On Thursday, 5 December 2013 at 13:55:30 UTC, Martin Nowak wrote:Ah well, this was a question for ideas. I don't really know to get there.I can think of a few things: 1. The compiler could mark what made it reject a candidate. If it failed due to a template constraint it could flag the last evaluated condition. If the constraint passed, it could flag the arguments whose types did not match. Flagging could be with a special symbol. An IDE could use a different font, colors, bold etc. 2. If a constraint is a function requirement rather than a condition for matching, it could be replaced with a static assert. 3. It may be possible to embed constraints into a type specification. It might not help a lot, but may make it easier for people to parse the description easier. 4. I frequently think a lot of this constraint stuff could be done in some kind if cascading if then else style. I'm not sure how a failure would be reported, but it could greatly reduce the number of constraints.
Dec 05 2013
And a fix for this particular issue. https://d.puremagic.com/issues/show_bug.cgi?id=11691 https://github.com/D-Programming-Language/phobos/pull/1749
Dec 05 2013