Thread overview
__traits(compiles) is true with warnings as errors
Oct 13, 2021
Jonathan Levi
Oct 14, 2021
Tejas
Oct 14, 2021
bauss
Oct 15, 2021
Dennis
October 13, 2021

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.

October 14, 2021

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:


void main(){
	int i;
	static if (__traits(compiles,i += 5.2))
		i += cast(int)5.2;
}

Or in general:

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.

October 14, 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:


void main(){
	int i;
	static if (__traits(compiles,i += 5.2))
		i += cast(int)5.2;
}

Or in general:

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.

October 15, 2021

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.