www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template constraints error messages using cputs()

reply bearophile <bearophileHUGS lycos.com> writes:
In D1 there were no template constraints, so to test the template arguments I
used to add some static asserts inside them. So a wrong template argument shows
a error message written by me that explains why the instantiation has failed
(unfortunately those error messages show the line number inside the template).

When a template constraint is composed of some different parts in &&, it's less
easy to understand what condition has failed, so I miss the error messages
written by me. This is an example (that probably I will simplify), there are
four conditions, and for a person that has not written this code, and is just
using Phobos, it's not immediately obvious what part has failed:


auto opBinary(string op, TOther)(TOther other)
  if (op == "~" && is(TOther == struct) &&
      (!__traits(compiles, { void isTuple(U...)(Tuple!U){} isTuple(other); }) ||
       distinctFieldNames!(T, TOther.TypesAndStrings)() )) { ...


There is a simple solution. The simple template constraints often don't need
extra error messages, so they can be left as they are now.

Putting one or more error message inside a template constraints turns them into
messy code, so in such cases it's better to move the tests elsewhere, in an
external template/CTFE:

template IsGoodFoo(T) {
    static if (...) {
        enum bool IsGoodFoo = true;
    } else {
        ctputs("this is an error message");
        return false;
    }
}

void foo(T)(T x) if (IsGoodFoo!T) { ...


So the ctputs() I have suggested here is usable for the template constraints
error messages too (this 3952 is in truth a bug report and enhancement request
fused in one, later Brad has explained me to avoid this):
http://d.puremagic.com/issues/show_bug.cgi?id=3952

This shows one more purpose for ctputs().
Later I will add those comments to the bug 3952.

Bye,
bearophile
Aug 06 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 In D1 there were no template constraints, so to test the template arguments I
used to add some static asserts inside them. So a wrong template argument shows
a error message written by me that explains why the instantiation has failed
(unfortunately those error messages show the line number inside the template).
 
 When a template constraint is composed of some different parts in &&, it's
less easy to understand what condition has failed, so I miss the error messages
written by me. This is an example (that probably I will simplify), there are
four conditions, and for a person that has not written this code, and is just
using Phobos, it's not immediately obvious what part has failed:
 
 
 auto opBinary(string op, TOther)(TOther other)
   if (op == "~" && is(TOther == struct) &&
       (!__traits(compiles, { void isTuple(U...)(Tuple!U){} isTuple(other); })
||
        distinctFieldNames!(T, TOther.TypesAndStrings)() )) { ...
 
 
 There is a simple solution. The simple template constraints often don't need
extra error messages, so they can be left as they are now.
 
 Putting one or more error message inside a template constraints turns them
into messy code, so in such cases it's better to move the tests elsewhere, in
an external template/CTFE:
 
 template IsGoodFoo(T) {
     static if (...) {
         enum bool IsGoodFoo = true;
     } else {
         ctputs("this is an error message");
         return false;
     }
 }
 
 void foo(T)(T x) if (IsGoodFoo!T) { ...
 
 
 So the ctputs() I have suggested here is usable for the template constraints
error messages too (this 3952 is in truth a bug report and enhancement request
fused in one, later Brad has explained me to avoid this):
 http://d.puremagic.com/issues/show_bug.cgi?id=3952
 
 This shows one more purpose for ctputs().
 Later I will add those comments to the bug 3952.
 
 Bye,
 bearophile
pragma(msg, "Is this what you need?"); Andrei
Aug 06 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 pragma(msg, "Is this what you need?");
You are right, in some situations it works :-) But you have to guard the pragma(msg) with a static if, so if your template constraint is a CTFE (that uses a normal 'if' instead of a 'static if') you can't use it, while ctputs() is OK, this shows the error message: bool isGoodFoo(int x) { if (x > 10) { return true; } else { pragma(msg, "no good"); // ctputs("no good"); return false; } } void foo(int N)() if (isGoodFoo(N)) {} void main() { foo!(20)(); } Bye, bearophile
Aug 06 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 pragma(msg, "Is this what you need?");
And just to express my feelings with better clarity, I think pragma(msg) is so buggy and unflexible that it deserves to go killed :-) Bye, bearophile
Aug 06 2010
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
bearophile wrote:

 Andrei Alexandrescu:
 pragma(msg, "Is this what you need?");
And just to express my feelings with better clarity, I think pragma(msg) is so buggy and unflexible that it deserves to go killed :-) Bye, bearophile
What kind of bugs?
Aug 06 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Lutger:
 What kind of bugs?
If you take a look at my original post in this thread you can see it contains a reference to the bug 3952, that contains some examples. There are other problems I have not listed in that bug report. Bye, bearophile
Aug 06 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lutger wrote:
 bearophile wrote:
 
 Andrei Alexandrescu:
 pragma(msg, "Is this what you need?");
And just to express my feelings with better clarity, I think pragma(msg) is so buggy and unflexible that it deserves to go killed :-) Bye, bearophile
What kind of bugs?
And how would changing its syntax help with them? Andrei
Aug 06 2010
parent reply Don <nospam nospam.com> writes:
Andrei Alexandrescu wrote:
 Lutger wrote:
 bearophile wrote:

 Andrei Alexandrescu:
 pragma(msg, "Is this what you need?");
And just to express my feelings with better clarity, I think pragma(msg) is so buggy and unflexible that it deserves to go killed :-) Bye, bearophile
What kind of bugs?
And how would changing its syntax help with them? Andrei
pragma(msg) creates its output as part of its semantic pass. And that's a problem, because the need to deal with forward references means that the order in which symbols get the semantic pass run on them isn't defined. And the semantics of pragma(msg) aren't well defined, because it wasn't designed to be used in this way (it was intended to only allow string literals). So you get inconsistencies.
Aug 06 2010
parent BCS <none anon.com> writes:
Hello Don,

 pragma(msg) creates its output as part of its semantic pass. And
 that's a problem, because the need to deal with forward references
 means that the order in which symbols get the semantic pass run on
 them isn't defined. And the semantics of pragma(msg) aren't well
 defined, because it wasn't designed to be used in this way (it was
 intended to only allow string literals). So you get inconsistencies.
The solution there is to assume that pragma(msg) will be reordered and make each one atomic; compleat in it's own right rather than assume it works like printf. -- ... <IXOYE><
Aug 07 2010
prev sibling parent reply BCS <none anon.com> writes:
Hello bearophile,

 And just to express my feelings with better clarity, I think
 pragma(msg) is so buggy and unflexible that it deserves to go killed
 :-)
 
How is pragma(msg,) buggy? It does exactly what it's supposed to do. Unless you can point to a deficiency that it has and something that fixes it. I see no reason to consider dumping it. -- ... <IXOYE><
Aug 07 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
BCS:
 How is pragma(msg,) buggy? It does exactly what it's supposed to do. Unless 
 you can point to a deficiency that it has and something that fixes it. I 
 see no reason to consider dumping it.
The thing is is supposed to do is not useful enough, as I have explained in my bug report/enhancement request. And even if you want to keep it, it's buggy & messy anyway, because it accepts as input things that it is not able to digest correctly. It is currently buggy, and I see no reason to keep it when there is a better replacement. I don't understand what people as you see good in pragma(msg), I think you are just mistaken or you have not used it often enough yet. The ctputs I have suggested can go in the std.intrisic module. Bye, bearophile
Aug 07 2010
parent reply BCS <none anon.com> writes:
Hello bearophile,

 BCS:
 
 How is pragma(msg,) buggy? It does exactly what it's supposed to do.
 Unless you can point to a deficiency that it has and something that
 fixes it. I see no reason to consider dumping it.
 
The thing it is supposed to do is not useful enough,
I dissagree. Strongly.
 as I have explained in my bug report/enhancement request.
Link: http://d.puremagic.com/issues/show_bug.cgi?id=3952 All the issues you address up to where you propose ctputs are bugs in DMD, not pragma(msg,...) as for ctputs as a /replacement/ see my replay to the bug.
 And even if you want
 to keep it, it's buggy & messy anyway, because it accepts as input
 things that it is not able to digest correctly. It is currently buggy,
 and I see no reason to keep it when there is a better replacement. I
 don't understand what people as you see good in pragma(msg), I think
 you are just mistaken or you have not used it often enough yet.
With regards to that, I have used it quite a lot so either you are just flat wrong or what you are talking about is something very esoteric that requiters huge amounts of experience to even begin to notice. While you may be able to convince me there are things that it can't do that are useful and maybe even that there are things that it does that it shouldn't, you will not convince me that what it currently does is less than /very useful/. My minimum requirements for a pragma(msgm...) replacement would be that it take any expression that results in an immutable(char[]) and, at compile time (and only compile time) during the semantic pass (while the code is processed, not evaluated) output the string. The major cases where your ctputs fails on this are inside a function that can be evaluated via CTFE: - If placed in a RT loop it could be evaluated to many times. - If placed in a code path that isn't hit via CTFE, it never outputs anything. - If the function gets run at RT, then you need to add a guard to prevent it from generating output at RT. -- ... <IXOYE><
Aug 08 2010
parent BCS <none anon.com> writes:
Hello BCS,

 Hello bearophile,
 
 BCS:
 
 How is pragma(msg,) buggy? It does exactly what it's supposed to do.
 Unless you can point to a deficiency that it has and something that
 fixes it. I see no reason to consider dumping it.
 
The thing it is supposed to do is not useful enough,
I dissagree. Strongly.
 as I have explained in my bug report/enhancement request.
 
Link: http://d.puremagic.com/issues/show_bug.cgi?id=3952 All the issues you address up to where you propose ctputs are bugs in DMD, not pragma(msg,...) as for ctputs as a /replacement/ see my replay to the bug.
 And even if you want
 to keep it, it's buggy & messy anyway, because it accepts as input
 things that it is not able to digest correctly. It is currently
 buggy,
 and I see no reason to keep it when there is a better replacement. I
 don't understand what people as you see good in pragma(msg), I think
 you are just mistaken or you have not used it often enough yet.
With regards to that, I have used it quite a lot so either you are just flat wrong or what you are talking about is something very esoteric that requiters huge amounts of experience to even begin to notice. While you may be able to convince me there are things that it can't do that are useful and maybe even that there are things that it does that it shouldn't, you will not convince me that what it currently does is less than /very useful/. My minimum requirements for a pragma(msgm...) replacement would be that it take any expression that results in an immutable(char[]) and, at compile time (and only compile time) during the semantic pass (while the code is processed, not evaluated) output the string. The major cases where your ctputs fails on this are inside a function that can be evaluated via CTFE: - If placed in a RT loop it could be evaluated to many times. - If placed in a code path that isn't hit via CTFE, it never outputs anything. - If the function gets run at RT, then you need to add a guard to prevent it from generating output at RT.
Oh, and it must be usable at any scope (without hacks): module foo; pragma(msg, "foo"); // note: a bare function call here woldn't work with a CTFE function. template Bar(string s) { pragam(msg, bar); } class Baz(string s) { pragam(msg, bar); } ... -- ... <IXOYE><
Aug 08 2010
prev sibling next sibling parent reply BCS <none anon.com> writes:
Hello bearophile,

 When a template constraint is composed of some different parts in &&,
 it's less easy to understand what condition has failed, so I miss the
 error messages written by me.
 
One solution to this issue would be to have an unconstrained temple that contains nothing but prgam(msg,"...") inside static ifs. That way failing the constraint produces a nice message and then, because the template has nothing it it, using it for almost anything will generate an error and block compilation. -- ... <IXOYE><
Aug 07 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
BCS:
 One solution to this issue would be to have an unconstrained temple that 
 contains nothing but prgam(msg,"...") inside static ifs. That way failing 
 the constraint produces a nice message and then, because the template has 
 nothing it it, using it for almost anything will generate an error and block 
 compilation.
I will try this solution, thank you. But cputs will be useful regardless. You can usually find a twisted way to solve most problems, but keeping pragms(msg) in D is not good, it's a temporary solution at best. One of the 'temporary solutions' in D that risks to stick around forever, I fear. Bye, bearophile
Aug 07 2010
parent reply Don <nospam nospam.com> writes:
bearophile wrote:
 BCS:
 One solution to this issue would be to have an unconstrained temple that 
 contains nothing but prgam(msg,"...") inside static ifs. That way failing 
 the constraint produces a nice message and then, because the template has 
 nothing it it, using it for almost anything will generate an error and block 
 compilation.
I will try this solution, thank you. But cputs will be useful regardless. You can usually find a twisted way to solve most problems, but keeping pragms(msg) in D is not good, it's a temporary solution at best. One of the 'temporary solutions' in D that risks to stick around forever, I fear. Bye, bearophile
pragma(msg) was NOT intended for metaprogramming. It's an accident that it works at all for the things people are using it for.
Aug 08 2010
parent BCS <none anon.com> writes:
Hello Don,

 bearophile wrote:
 
 BCS:
 
 One solution to this issue would be to have an unconstrained temple
 that contains nothing but prgam(msg,"...") inside static ifs. That
 way failing the constraint produces a nice message and then, because
 the template has nothing it it, using it for almost anything will
 generate an error and block compilation.
 
I will try this solution, thank you. But cputs will be useful regardless. You can usually find a twisted way to solve most problems, but keeping pragms(msg) in D is not good, it's a temporary solution at best. One of the 'temporary solutions' in D that risks to stick around forever, I fear. Bye, bearophile
pragma(msg) was NOT intended for metaprogramming. It's an accident that it works at all for the things people are using it for.
Yes but a very useful accident. And a use that ctputs doesn't match up with. -- ... <IXOYE><
Aug 08 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
BCS:

 All the issues you address up to where you propose ctputs are bugs in DMD, 
 not pragma(msg,...) as for ctputs as a /replacement/ see my replay to the 
 bug.
Thank you for this answer and the answer in bugzilla. I explain the problems I find while I program in D, and sometimes I try to give a starting point for a solution, but usually it's not hard to find solutions better than the ones I suggest. I have written an answer in Bugzilla, I don't know if it's enough.
 you will not convince me that what it currently does is less than /very
useful/. 
You are right :-)
 My minimum requirements for a pragma(msgm...) replacement would be that it 
 take any expression that results in an immutable(char[]) and, at compile 
 time (and only compile time) during the semantic pass (while the code is 
 processed, not evaluated) output the string.
I'd like to ctputs() to act as std.c.stdio.puts() if the function is run at run time.
 The major cases where your ctputs fails on this are inside a function that 
 can be evaluated via CTFE:
 - If placed in a RT loop it could be evaluated to many times.
 - If placed in a code path that isn't hit via CTFE, it never outputs anything.
 - If the function gets run at RT, then you need to add a guard to prevent 
 it from generating output at RT.
This is by design. But I understand your point, ctputs seems designed for a purpose different than pragma(msg), it doesn't seem a replacement. ctputs is meant as a way to print strings from function if you call the function both at runtime or compile time with CTFE. pragma(msg) is meant to show a message at compile time. So pragma(msg) needs to be debugged and then kept. I probably have update the bug report, and I'd like to split it in a pragma(msg) bug report (essentially to make it test its input argument better), plus an enhancement request for a ctputs() probably in std.intrinsic :-) Bye and thank you, bearophile
Aug 08 2010
next sibling parent BCS <none anon.com> writes:
Hello bearophile,

 BCS:
 
 All the issues you address up to where you propose ctputs are bugs in
 DMD, not pragma(msg,...) as for ctputs as a /replacement/ see my
 replay to the bug.
 
Thank you for this answer and the answer in bugzilla. I explain the problems I find while I program in D, and sometimes I try to give a starting point for a solution, but usually it's not hard to find solutions better than the ones I suggest. I have written an answer in Bugzilla, I don't know if it's enough.
 you will not convince me that what it currently does is less than
 /very useful/.
 
You are right :-)
 My minimum requirements for a pragma(msgm...) replacement would be
 that it take any expression that results in an immutable(char[]) and,
 at compile time (and only compile time) during the semantic pass
 (while the code is processed, not evaluated) output the string.
 
I'd like to ctputs() to act as std.c.stdio.puts() if the function is run at run time.
 The major cases where your ctputs fails on this are inside a function
 that
 can be evaluated via CTFE:
 - If placed in a RT loop it could be evaluated to many times.
 - If placed in a code path that isn't hit via CTFE, it never outputs
 anything.
 - If the function gets run at RT, then you need to add a guard to
 prevent
 it from generating output at RT.
This is by design.
Understood, and I see it's value. I'm not going to argue for not having ctputs() but I want (need?) a way to have the other option. I don't think these can be combined (but I could be wrong). Just as a point to consider; it might be reasonable to implement ctputs in terms of a combination of a compile time only puts and a runtime only puts. Either the runtime/compile time version or the compile time only version can be derived from the other but deriving the former seems cleaner than deriving the latter.
 
 But I understand your point, ctputs seems designed for a purpose
 different than pragma(msg), it doesn't seem a replacement. ctputs is
 meant as a way to print strings from function if you call the function
 both at runtime or compile time with CTFE. pragma(msg) is meant to
 show a message at compile time. So pragma(msg) needs to be debugged
 and then kept.
Good. We agree.
 
 I probably have update the bug report, and I'd like to split it in a
 pragma(msg) bug report (essentially to make it test its input argument
 better), plus an enhancement request for a ctputs() probably in
 std.intrinsic :-)
Souinds like a good way to go. -- ... <IXOYE><
Aug 08 2010
prev sibling parent reply Mafi <mafi example.org> writes:
Am 08.08.2010 17:41, schrieb bearophile:
 BCS:

 All the issues you address up to where you propose ctputs are bugs in DMD,
 not pragma(msg,...) as for ctputs as a /replacement/ see my replay to the
 bug.
Thank you for this answer and the answer in bugzilla. I explain the problems I find while I program in D, and sometimes I try to give a starting point for a solution, but usually it's not hard to find solutions better than the ones I suggest. I have written an answer in Bugzilla, I don't know if it's enough.
 you will not convince me that what it currently does is less than /very
useful/.
You are right :-)
 My minimum requirements for a pragma(msgm...) replacement would be that it
 take any expression that results in an immutable(char[]) and, at compile
 time (and only compile time) during the semantic pass (while the code is
 processed, not evaluated) output the string.
I'd like to ctputs() to act as std.c.stdio.puts() if the function is run at run time.
 The major cases where your ctputs fails on this are inside a function that
 can be evaluated via CTFE:
 - If placed in a RT loop it could be evaluated to many times.
 - If placed in a code path that isn't hit via CTFE, it never outputs anything.
 - If the function gets run at RT, then you need to add a guard to prevent
 it from generating output at RT.
This is by design. But I understand your point, ctputs seems designed for a purpose different than pragma(msg), it doesn't seem a replacement. ctputs is meant as a way to print strings from function if you call the function both at runtime or compile time with CTFE. pragma(msg) is meant to show a message at compile time. So pragma(msg) needs to be debugged and then kept.
I see the need for ctputs-like construct but I don't like the name. What about simply making puts magically ctfe-able. The runtime behavior is clearly defined and the compiler has to to simply catch calls to the real puts when ctfe-ing and replace it with it's implemantation. What do you, bearophile and others, think?
 I probably have update the bug report, and I'd like to split it in a
pragma(msg) bug report (essentially to make it test its input argument better),
plus an enhancement request for a ctputs() probably in std.intrinsic :-)
Aug 08 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Mafi:
 I see the need for ctputs-like construct but I don't like the name. What 
 about simply making puts magically ctfe-able. The runtime behavior is 
 clearly defined and the compiler has to to simply catch calls to the 
 real puts when ctfe-ing and replace it with it's implemantation.
 What do you, bearophile and others, think?
If that can be done, then I am OK with that too. Bye, bearophile
Aug 08 2010