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?");

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?");

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.
 


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.
 


 as I have explained in my bug report/enhancement request.
 

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.

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 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.
 

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

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