www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Enumeration Type-Safety in D

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
What is the state and plans on type-safety of enums in D?

I expected

import std.stdio: writeln;

void main(string args[]) {
     enum E {x, y, z}
     E e;
     writeln(e);
     e = cast(E)3;
     writeln(e);
}

to fail to compile because of D's otherwise strong static 
type/range checking or at least give an RangeException when run.

To my surprise, it instead prints

cast(E)3

Is this really the preferred default behaviour for the majority 
of use cases?
Nov 07 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Thursday, 7 November 2013 at 13:25:40 UTC, Nordlöw wrote:
 Is this really the preferred default behaviour for the majority 
 of use cases?
cast usage == breaking type system. Don't expect any help from it if you are using explicit casts.
Nov 07 2013
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Thursday, 7 November 2013 at 13:25:40 UTC, Nordlöw wrote:
 What is the state and plans on type-safety of enums in D?

 I expected

 import std.stdio: writeln;

 void main(string args[]) {
     enum E {x, y, z}
     E e;
     writeln(e);
     e = cast(E)3;
     writeln(e);
 }

 to fail to compile because of D's otherwise strong static 
 type/range checking or at least give an RangeException when run.

 To my surprise, it instead prints

 cast(E)3

 Is this really the preferred default behaviour for the majority 
 of use cases?
Use std.conv : to: e = to!E(3); results in: std.conv.ConvException /opt/compilers/dmd2/include/std/conv.d(1854): Value (3) does not match any member value of enum 'E'
Nov 07 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Nordlöw:

 to fail to compile because of D's otherwise strong static 
 type/range checking or at least give an RangeException when run.
cast() is designed to punch holes in the type system, so your code doesn't show problems in D. On the other hand see: https://d.puremagic.com/issues/show_bug.cgi?id=3999 Bye, bearophile
Nov 07 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Thursday, 7 November 2013 at 13:25:40 UTC, Nordlöw wrote:
 What is the state and plans on type-safety of enums in D?

 I expected

 import std.stdio: writeln;

 void main(string args[]) {
     enum E {x, y, z}
     E e;
     writeln(e);
     e = cast(E)3;
     writeln(e);
 }

 to fail to compile because of D's otherwise strong static 
 type/range checking or at least give an RangeException when run.

 To my surprise, it instead prints

 cast(E)3

 Is this really the preferred default behaviour for the majority 
 of use cases?
The problem is in cast() and it will pop up in both final and usual switch, as well as in other places.
Nov 07 2013
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, November 07, 2013 14:25:38 Nordl=C3=B6w wrote:
 What is the state and plans on type-safety of enums in D?
=20
 I expected
=20
 import std.stdio: writeln;
=20
 void main(string args[]) {
      enum E {x, y, z}
      E e;
      writeln(e);
      e =3D cast(E)3;
      writeln(e);
 }
=20
 to fail to compile because of D's otherwise strong static
 type/range checking or at least give an RangeException when run.
=20
 To my surprise, it instead prints
=20
 cast(E)3
=20
 Is this really the preferred default behaviour for the majority
 of use cases?
If you're casting, then I think that it's perfectly reasonable that thi= s sort=20 of thing can happen. The problem is when it happens without casting. e.= g. enum E : string { a =3D "hello", b =3D "goodbye" } void main() { E foo =3D E.a; foo ~=3D " world"; assert(foo =3D=3D "hello world"); } or enum E : int { a =3D 1, b =3D 2 } void main() { E foo =3D E.a | E.b; assert(foo =3D=3D 3); } IMHO, it should not be legal to construct invalid enums without casting= , but=20 unfortunately, right now, it very much is. For the most part, you can d= o=20 operations on enums that are completely valid for their base type, and = the=20 result ends up being the enum type instead of the base type like it sho= uld. I=20 don't know what the odds are of getting this fixed, but I think that it= should=20 be. However, even it were properly enforced that operations done on enum va= lues=20 would either be guaranteed to result in a valid enum value or would res= ult in=20 the base type instead of the enum type, I'd still expect casting to get= around=20 that as casting is a blunt instrument which forces the issue. As others= have=20 pointed out, you should use std.conv.to if you want the conversion to b= e=20 checked for validity. - Jonathan M Davis
Nov 07 2013