__traits(compiles) is true with warnings as errors

bauss jj_1337 at live.dk
Thu Oct 14 11:08:24 UTC 2021


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.



More information about the Digitalmars-d-learn mailing list