Thread overview
static if else behavior and is type comparison
Mar 11, 2016
Fynn Schröder
Mar 11, 2016
Ali Çehreli
Mar 11, 2016
Fynn Schröder
Mar 11, 2016
Artur Skawina
Mar 11, 2016
Marc Schütz
Mar 11, 2016
Chris Wright
Mar 11, 2016
Andrea Fontana
March 11, 2016
Hi all,

I'm currently working on a small utility to control the EC (embedded controller) of my notebook. I need to call an external C library and choose different methods based on the desired return type. I came up with a solution based on type checking and static if - however I ran into a weird issue:

void main()
{
	pragma(msg, "only ubytes:");
	ubyte x = typeBasedDispatcher!ubyte();
	
	pragma(msg, "only ushorts:");
	ushort y = typeBasedDispatcher!ushort();
	
	pragma(msg, "only uints:");
	uint z = typeBasedDispatcher!uint();
}

U typeBasedDispatcher(U)() if (is(U == ubyte) || is(U == ushort) || is(U == uint)) {
	static if (is(U == ubyte)) {
		pragma(msg, "is ubyte");
		return fnUbyte();
	} else if (is(U == ushort)) {
		pragma(msg, "is ushort");
		return fnUshort();
	} else if (is(U == uint)) {
		pragma(msg, "is unit");
		return fnUint();
	} else {
		pragma(msg, "ERROR!? should not reach this in any case!?");
	}
}

ubyte fnUbyte() { return ubyte.init; }

ushort fnUshort() { return ushort.init; }

uint fnUint() { return uint.init; }

Output of dmd 2.070.0 on Windows:

only ubytes:
is ubyte
only ushorts:
is ushort
is unit
ERROR! should not reach this in any case!
staticIfElse.d(22): Error: cannot implicitly convert expression (fnUint()) of type uint to ushort
staticIfElse.d(7): Error: template instance staticIfElse.typeBasedDispatcher!ushort error instantiating
only uints:
is ushort
is unit
ERROR! should not reach this in any case!


Am I doing anything wrong here or is this a bug?

March 11, 2016
You've been bitten by a common usability issue. :)

On 03/11/2016 12:02 AM, Fynn Schröder wrote:
>      static if (is(U == ubyte)) {
>          pragma(msg, "is ubyte");
>          return fnUbyte();
>      } else if (is(U == ushort)) {

You mean 'else static if'. (Not your fault: I (and others) wish the compiler warned about this problem.)

Ali

March 11, 2016
On Friday, 11 March 2016 at 08:02:41 UTC, Fynn Schröder wrote:
> Am I doing anything wrong here or is this a bug?

You should write:

static if { ... }
else static if { ... }
else static if { ... }
March 11, 2016
On Friday, 11 March 2016 at 08:21:33 UTC, Ali Çehreli wrote:
> You mean 'else static if'. (Not your fault: I (and others) wish the compiler warned about this problem.)


Thanks! Such an easy mistake..
You're right Ali, it would be nice if the compiler gave a warning :)
March 11, 2016
On 03/11/16 09:21, Ali Çehreli via Digitalmars-d-learn wrote:
> You've been bitten by a common usability issue. :)
> 
> On 03/11/2016 12:02 AM, Fynn Schröder wrote:
>>      static if (is(U == ubyte)) {

>>      } else if (is(U == ushort)) {
> 
> You mean 'else static if'. (Not your fault: I (and others) wish the compiler warned about this problem.)

It can not warn about this "problem" - because it's a perfectly
fine and relatively common construct (a RT check guarded by a CT
check).
The problem comes from the static-if pseudo-keyword hack --
"static if" is effectively a keyword; if the syntax was eg "#if"
then such mistakes would be less likely. Obviously, it's a bit late
for such language change. One thing that the compiler could warn
about is: a RT-if that depends only on the result of an is-expression;
that would have caught the case above and rarely be wrong (with an
easy way to make the compiler happy). It would still miss more
complex cases, but those can't be warned about as they can occur
legitimately in generic code.

artur
March 11, 2016
On Friday, 11 March 2016 at 12:10:53 UTC, Artur Skawina wrote:
> On 03/11/16 09:21, Ali Çehreli via Digitalmars-d-learn wrote:
>> You've been bitten by a common usability issue. :)
>> 
>> On 03/11/2016 12:02 AM, Fynn Schröder wrote:
>>>      static if (is(U == ubyte)) {
>
>>>      } else if (is(U == ushort)) {
>> 
>> You mean 'else static if'. (Not your fault: I (and others) wish the compiler warned about this problem.)
>
> It can not warn about this "problem" - because it's a perfectly
> fine and relatively common construct (a RT check guarded by a CT
> check).

It can first deprecate and later disallow

    static if(...) ... else if(...) ...

It's always possible (and IMO preferable) to write the clearer

    static if(...) { ... } else { if(...) ... }

It already does this for similar error-prone cases, e.g.

    if(...) ;
    while(...) ;
    // Error: use '{ }' for an empty statement, not a ';'
March 11, 2016
On Fri, 11 Mar 2016 00:21:33 -0800, Ali Çehreli wrote:

> You've been bitten by a common usability issue. :)
> 
> On 03/11/2016 12:02 AM, Fynn Schröder wrote:
>  >      static if (is(U == ubyte)) {
>  >          pragma(msg, "is ubyte");
>  >          return fnUbyte();
>  >      } else if (is(U == ushort)) {
> 
> You mean 'else static if'. (Not your fault: I (and others) wish the
> compiler warned about this problem.)
> 
> Ali

https://github.com/Hackerpilot/Dscanner/pull/309

Turns out it's much faster to change a lint tool than to change the compiler.