digitalmars.D - Verbose checking of range category
- Andrei Alexandrescu (51/51) Dec 11 2010 Hello,
- Lutger Blijdestijn (10/10) Dec 11 2010 It would be a welcome improvement. One downside is that the relation bet...
- Jesse Phillips (2/19) Dec 11 2010 I think it would be best if DMD would emit which constraint failed. Bett...
- Jonathan M Davis (6/29) Dec 11 2010 It would be great if dmd said which constraint failed, but since you're ...
- Simen kjaeraas (8/15) Dec 11 2010 Not to mention SFINAE, which would lead to a wall of text when multiple
- Andrei Alexandrescu (5/33) Dec 11 2010 Exactly. Oftentimes certain tests are supposed to not fail. All we can
- Andrej Mitrovic (4/36) Dec 11 2010 That's why I think would be great to have constraint blocks. I threw
- Robert Jacques (12/24) Dec 11 2010 On Sat, 11 Dec 2010 12:15:31 -0500, Andrei Alexandrescu
- Andrej Mitrovic (29/58) Dec 11 2010 Why not just add an extra string parameter to constraint functions
- Andrej Mitrovic (4/64) Dec 11 2010 And to further hijack the topic, a hypothetical piece of code with
- Gerrit Wichert (7/58) Dec 12 2010 Hello,
Hello, Following Craig's questions about sort(), I was thinking of the following idea. How about defining a flag rangeCheckVerbose that emits explanatory messages during compilation whenever a range check fails? Consider this prototype: import std.stdio; version = rangeCheckVerbose; template isRandomAccessRange(T) { enum isRandomAccessRange = isRandomAccessRangeImpl!T.value; } template isRandomAccessRangeImpl(T) { enum hasEmpty = is(typeof(T.init.empty)); enum hasFront = is(typeof(T.init.front)); enum hasPopFront = is(typeof(T.init.popFront())); enum hasIndexing = is(typeof(T.init[1])); enum hasSlicing = is(typeof(T.init[1])); enum value = hasEmpty && hasFront && hasPopFront && hasIndexing && hasSlicing; version (rangeCheckVerbose) { static if (!value) { pragma(msg, "Type " ~ T.stringof ~ " is not a random access range because:"); static if (!hasEmpty) pragma(msg, " no empty property"); static if (!hasFront) pragma(msg, " no front property"); static if (!hasPopFront) pragma(msg, " no popFront method"); static if (!hasIndexing) pragma(msg, " no indexing"); static if (!hasSlicing) pragma(msg, " no slicing"); } } } void main() { writeln(isRandomAccessRange!int); } This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? Andrei
Dec 11 2010
It would be a welcome improvement. One downside is that the relation between the mismatched template and the range check is not there. I worry that it will be hard to understand when facing a lot of errors, but will have to try to find out. The error message dmd produces in the face of ambiguous overloading is the most model (foo matches both bar and baz). Template constraints are great, but have taken away the possibility of very good custom error messages that static if / else / assert have. unaryFun and binaryFun of std.functional for example give really helpful messages. I'm hesitant to suggest another feature, but maybe an 'else' counterpart to template constraint checks could go a long way.
Dec 11 2010
Andrei Alexandrescu Wrote:This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiI think it would be best if DMD would emit which constraint failed. Better support for automatically say why would be good too. Basically I like bearophile's suggestion to give them more structure. But until then, yes do this. It should be everywhere, but ranges a big, and need them now!
Dec 11 2010
On Saturday 11 December 2010 11:06:45 Jesse Phillips wrote:Andrei Alexandrescu Wrote:It would be great if dmd said which constraint failed, but since you're dealing with an arbitary boolean expression, in many cases, would not be particularly straightforward to say what failed, and I expect that it would be a _big_ change for the compiler. - Jonathan M DavisThis program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiI think it would be best if DMD would emit which constraint failed. Better support for automatically say why would be good too. Basically I like bearophile's suggestion to give them more structure. But until then, yes do this. It should be everywhere, but ranges a big, and need them now!
Dec 11 2010
Jonathan M Davis <jmdavisProg gmx.com> wrote:It would be great if dmd said which constraint failed, but since you're dealing with an arbitary boolean expression, in many cases, would not be particularly straightforward to say what failed, and I expect that it would be a _big_ change for the compiler.Not to mention SFINAE, which would lead to a wall of text when multiple specializations of a template exists (15 templates failed, each for 3 different reasons = 60 lines of error messages, none of which are likely to be useful). And in such a case, no error messages are to be printed if one match is found, right? -- Simen
Dec 11 2010
On 12/11/10 1:32 PM, Jonathan M Davis wrote:On Saturday 11 December 2010 11:06:45 Jesse Phillips wrote:Exactly. Oftentimes certain tests are supposed to not fail. All we can do is to be verbose and let the programmer see the last messages emitted prior to failure. AndreiAndrei Alexandrescu Wrote:It would be great if dmd said which constraint failed, but since you're dealing with an arbitary boolean expression, in many cases, would not be particularly straightforward to say what failed, and I expect that it would be a _big_ change for the compiler.This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiI think it would be best if DMD would emit which constraint failed. Better support for automatically say why would be good too. Basically I like bearophile's suggestion to give them more structure. But until then, yes do this. It should be everywhere, but ranges a big, and need them now!
Dec 11 2010
On 12/11/10, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Saturday 11 December 2010 11:06:45 Jesse Phillips wrote:That's why I think would be great to have constraint blocks. I threw the idea in the air a few days ago, but since it would be a big change I doubt it will be thought about, at least not for D2.Andrei Alexandrescu Wrote:It would be great if dmd said which constraint failed, but since you're dealing with an arbitary boolean expression, in many cases, would not be particularly straightforward to say what failed, and I expect that it would be a _big_ change for the compiler. - Jonathan M DavisThis program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiI think it would be best if DMD would emit which constraint failed. Better support for automatically say why would be good too. Basically I like bearophile's suggestion to give them more structure. But until then, yes do this. It should be everywhere, but ranges a big, and need them now!
Dec 11 2010
On Sat, 11 Dec 2010 12:15:31 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: [snip]This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiAn issue with this is that failed template type checks are both extremely common and expected in template code: i.e. static if(isRandomAccessRange!T) {...}. So, you'll get a lot of spurious error messages slowly. Add in parallel builds, and the last error message won't even be the one you're looking for. So, while I think the concept is usefully, I'd view this implementation as an intermediate stepping stone at best (and a distraction from you fixing other bugs at worse). I'd recommend, as an alternative, to have specific debug versions of the checks, i.e. isRandomAccessRangeDebug, as a way to avoid false positives.
Dec 11 2010
Why not just add an extra string parameter to constraint functions that will show a custom error message? This kind of works (although you still get standard errors): import std.conv; import std.stdio; alias int cool; bool isCool(T, string X)() { static if (is(T : cool)) { return true; } else { pragma(msg, "Constraint failure: " ~ X); return false; } } void foo(X)(X x) if (isCool!(X, "foo(X) argument must be cool!")()) { } void main() { cool myvar; double myvar2; foo!()(myvar); foo!()(myvar2); } On 12/11/10, Robert Jacques <sandford jhu.edu> wrote:On Sat, 11 Dec 2010 12:15:31 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: [snip]This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiAn issue with this is that failed template type checks are both extremely common and expected in template code: i.e. static if(isRandomAccessRange!T) {...}. So, you'll get a lot of spurious error messages slowly. Add in parallel builds, and the last error message won't even be the one you're looking for. So, while I think the concept is usefully, I'd view this implementation as an intermediate stepping stone at best (and a distraction from you fixing other bugs at worse). I'd recommend, as an alternative, to have specific debug versions of the checks, i.e. isRandomAccessRangeDebug, as a way to avoid false positives.
Dec 11 2010
And to further hijack the topic, a hypothetical piece of code with constraint blocks might look something like this: http://dpaste.org/xB2N/ On 12/11/10, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Why not just add an extra string parameter to constraint functions that will show a custom error message? This kind of works (although you still get standard errors): import std.conv; import std.stdio; alias int cool; bool isCool(T, string X)() { static if (is(T : cool)) { return true; } else { pragma(msg, "Constraint failure: " ~ X); return false; } } void foo(X)(X x) if (isCool!(X, "foo(X) argument must be cool!")()) { } void main() { cool myvar; double myvar2; foo!()(myvar); foo!()(myvar2); } On 12/11/10, Robert Jacques <sandford jhu.edu> wrote:On Sat, 11 Dec 2010 12:15:31 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: [snip]This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? AndreiAn issue with this is that failed template type checks are both extremely common and expected in template code: i.e. static if(isRandomAccessRange!T) {...}. So, you'll get a lot of spurious error messages slowly. Add in parallel builds, and the last error message won't even be the one you're looking for. So, while I think the concept is usefully, I'd view this implementation as an intermediate stepping stone at best (and a distraction from you fixing other bugs at worse). I'd recommend, as an alternative, to have specific debug versions of the checks, i.e. isRandomAccessRangeDebug, as a way to avoid false positives.
Dec 11 2010
Hello, maybe the template resolver can provide some kind of buffer where the constrains can emit their messages to. If finally a match is found the buffer can be discarded. If not the messages can be printed. So we only get messages for failed template instantiations. Am 11.12.2010 18:15, schrieb Andrei Alexandrescu:Hello, Following Craig's questions about sort(), I was thinking of the following idea. How about defining a flag rangeCheckVerbose that emits explanatory messages during compilation whenever a range check fails? Consider this prototype: import std.stdio; version = rangeCheckVerbose; template isRandomAccessRange(T) { enum isRandomAccessRange = isRandomAccessRangeImpl!T.value; } template isRandomAccessRangeImpl(T) { enum hasEmpty = is(typeof(T.init.empty)); enum hasFront = is(typeof(T.init.front)); enum hasPopFront = is(typeof(T.init.popFront())); enum hasIndexing = is(typeof(T.init[1])); enum hasSlicing = is(typeof(T.init[1])); enum value = hasEmpty && hasFront && hasPopFront && hasIndexing && hasSlicing; version (rangeCheckVerbose) { static if (!value) { pragma(msg, "Type " ~ T.stringof ~ " is not a random access range because:"); static if (!hasEmpty) pragma(msg, " no empty property"); static if (!hasFront) pragma(msg, " no front property"); static if (!hasPopFront) pragma(msg, " no popFront method"); static if (!hasIndexing) pragma(msg, " no indexing"); static if (!hasSlicing) pragma(msg, " no slicing"); } } } void main() { writeln(isRandomAccessRange!int); } This program will generate a valid executable, but will also print during compilation: Type int is not a random access range because: no empty property no front property no popFront method no indexing no slicing When a programmer has an odd issue with a range check, turning verboseness of checks could help. What do you think? Andrei
Dec 12 2010