Thread overview
__traits(compiles) is true with warnings as errors
4 days ago
Jonathan Levi
3 days ago
Tejas
3 days ago
bauss
2 days ago
Dennis
4 days ago

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.

3 days ago

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.

3 days ago

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.

2 days ago

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.