www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - __traits(compiles) is true with warnings as errors

reply Jonathan Levi <catanscout gmail.com> writes:
When dmd is passed the "-w" tag, it "treats warnings as errors" 
but not with the "__traits(compiles)" expression.  Is this the 
intended action?

This code should compile even with "-w", but it does not.

     int i;
     static if (__traits(compiles,i += 5.2))
     	i += 5.2;


`pragma(msg, __traits(compiles,i += 5.2))` is `true`, even though 
it will stop the compiler.

My specific use case, where I am hindered by this, is with a 
guarded template function akin to this:

     void fun(T,U)(ref T a, const U b)
     if (__traits(compiles, a += b))
     {
         a += b;
     }

I think this is a bug.  The Docs for __traits compiles state 
"Returns a bool true if all of the arguments compile . . ." which 
is not holding true.
Oct 13 2021
parent reply Tejas <notrealemail gmail.com> writes:
On Wednesday, 13 October 2021 at 17:58:23 UTC, Jonathan Levi 
wrote:
 When dmd is passed the "-w" tag, it "treats warnings as errors" 
 but not with the "__traits(compiles)" expression.  Is this the 
 intended action?

 This code should compile even with "-w", but it does not.

     int i;
     static if (__traits(compiles,i += 5.2))
     	i += 5.2;


 `pragma(msg, __traits(compiles,i += 5.2))` is `true`, even 
 though it will stop the compiler.

 My specific use case, where I am hindered by this, is with a 
 guarded template function akin to this:

     void fun(T,U)(ref T a, const U b)
     if (__traits(compiles, a += b))
     {
         a += b;
     }

 I think this is a bug.  The Docs for __traits compiles state 
 "Returns a bool true if all of the arguments compile . . ." 
 which is not holding true.
But it _is_ compiling, just with a warning. If you wish to force the code to compile, you can manually cast it to prevent the compiler from erroring out: ```d void main(){ int i; static if (__traits(compiles,i += 5.2)) i += cast(int)5.2; } ``` Or in general: ```d void fun(T,U)(ref T a, const U b) if (__traits(compiles, a += b)) { a += cast(T)b; } ``` It seems the `__traits(compiles, ..)` feature was designed to operate independent of the command line flags passed to the D compiler. I don't know if that's a bug or not though; best wait for someone more experienced to chime in.
Oct 13 2021
parent reply bauss <jj_1337 live.dk> writes:
On Thursday, 14 October 2021 at 05:41:01 UTC, Tejas wrote:
 On Wednesday, 13 October 2021 at 17:58:23 UTC, Jonathan Levi 
 wrote:
 When dmd is passed the "-w" tag, it "treats warnings as 
 errors" but not with the "__traits(compiles)" expression.  Is 
 this the intended action?

 This code should compile even with "-w", but it does not.

     int i;
     static if (__traits(compiles,i += 5.2))
     	i += 5.2;


 `pragma(msg, __traits(compiles,i += 5.2))` is `true`, even 
 though it will stop the compiler.

 My specific use case, where I am hindered by this, is with a 
 guarded template function akin to this:

     void fun(T,U)(ref T a, const U b)
     if (__traits(compiles, a += b))
     {
         a += b;
     }

 I think this is a bug.  The Docs for __traits compiles state 
 "Returns a bool true if all of the arguments compile . . ." 
 which is not holding true.
But it _is_ compiling, just with a warning. If you wish to force the code to compile, you can manually cast it to prevent the compiler from erroring out: ```d void main(){ int i; static if (__traits(compiles,i += 5.2)) i += cast(int)5.2; } ``` Or in general: ```d void fun(T,U)(ref T a, const U b) if (__traits(compiles, a += b)) { a += cast(T)b; } ``` It seems the `__traits(compiles, ..)` feature was designed to operate independent of the command line flags passed to the D compiler. I don't know if that's a bug or not though; best wait for someone more experienced to chime in.
__traits(compiles) just checks whether the arguments given are semantically correct. The given arguments in the example of OP are technically semantically correct and that's why it returns true. What could be useful is a new trait (to not break existing code) like __traits(warning, ...) which does the same as __traits(compiles) but also checks whether the arguments would cause a warning by the compiler. OR __traits(compiles, ..., true) where true means aggressive (warnings as error) and false or nothing means the default behavior we have today. The default behavior can't or shouldn't change as existing code that relies on it could break and the problem here is that the failure could be silent as you don't get an error message unless your specific use-case relies on the arguments compiling, but in a lot of cases it's used optionally to create branching.
Oct 14 2021
parent Dennis <dkorpel gmail.com> writes:
On Thursday, 14 October 2021 at 11:08:24 UTC, bauss wrote:
 What could be useful is a new trait (to not break existing 
 code) like __traits(warning, ...) which does the same as 
 __traits(compiles) but also checks whether the arguments would 
 cause a warning by the compiler.
Noooo! Warnings suck. Errors are fine, nothing is fine, a big bag of unspecified 'maybes' that are put on either side depending on the user is not. Unfortunately, dub makes warnings into errors by default, but you can use `buildRequirements "silenceWarnings"` or `buildRequirements "allowWarnings"` to mitigate it. If implicit float truncation is really error prone, it should be deprecated. Otherwise the compiler should shut up about it.
Oct 15 2021