Feature request: enum init shouldn't create a new enumeration

Tommi tommitissari at hotmail.com
Sat Oct 13 23:20:40 PDT 2012


On Saturday, 13 October 2012 at 20:25:56 UTC, Jonathan M Davis 
wrote:
>> 
>>      MyEnum me;
>> 
>>      final switch (me) // no init case necessary nor allowed
>>      {
>>      case MyEnum.first:  break;
>>      case MyEnum.second: break;
>>      }
>> }
>
> Think about that for a moment. What happens when that final 
> switch statement is actually run?

There's a bug in that code, because MyEnum default-initializes to 
an invalid value. It's effectively the same as this following 
code, where the programmer has failed to initialize MyEnum 
variable with a valid value:

enum MyEnum { first, second }

void main()
{
     MyEnum me = cast(MyEnum)(-123);
	
     final switch (me)
     {
     case MyEnum.first:  break;
     case MyEnum.second: break;
     }
}

I think that the final switch statement above should throw an 
unrecoverable error. I tested it, and nothing happens. I strongly 
disagree with this behavior of the compiler (a bug perhaps?).

> And remember, that in many cases, T.init is considered to be 
> perfectly valid. By allowing a final switch _not_ to have it,
> it then becomes easy to forget to add a case for it when you
> _need_ to, completely defeating the purpose of the final
> switch (to make it so that both you and the compiler know that 
> all of the possible values are accounted for).

If T.init is considered to be perfectly valid, then it means, 
that a synonym for it exists among the enumerations. E.g:

enum MyEnum  { init = 1, first = 1, second = 42 }
enum ThyEnum { first, second }

In both of those cases, T.first is the synonym of T.init, which 
is what both of those enums default-initialize to. Therefore, if 
T.init is a valid value, and thus has a synonym among the 
enumerations of T, then you can't add a case for init in a final 
switch:

MyEnum me;

final switch (me)
{
     MyEnum.first:  break;
     MyEnum.second: break;
     MyEnum.init:   // Error: duplicate case cast(MyEnum)1
                    // in switch statement
}

So, this situation you describe, where you *need* to add a case 
for init in a final switch, it doesn't exist. T.init should 
always either 1) have a synonym among the enumerations or 2) 
represent an invalid value.


More information about the Digitalmars-d mailing list