www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Type checking on typed enum

reply "ixid" <nuaccount gmail.com> writes:
If I use code like:

enum ulong VAR = 10;

I'd have expected this to be type checked when used as a ulong. 
Instead it seems to be checked based on its absolute value and is 
accepted for a function like:

void fun(int n) {
     // Do stuff
}

If the value of VAR is set to more than int.max then the compiler 
(DMD2 latest non-beta) notices the type mismatch. This would seem 
like an understandable enum behaviour if VAR was just enum rather 
than enum ulong but intuitively I'd have expected the specifier 
to limit what would accept the enum. Is this how it's supposed to 
work? As a beginner with D I came across the advice that enum was 
the correct way to specify global constants but this makes it 
feel safer to use const when you want type checking and perhaps 
enum isn't the right choice.
Sep 16 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, September 17, 2012 01:03:46 ixid wrote:
 If I use code like:
 
 enum ulong VAR = 10;
 
 I'd have expected this to be type checked when used as a ulong.
 Instead it seems to be checked based on its absolute value and is
 accepted for a function like:
 
 void fun(int n) {
      // Do stuff
 }
 
 If the value of VAR is set to more than int.max then the compiler
 (DMD2 latest non-beta) notices the type mismatch. This would seem
 like an understandable enum behaviour if VAR was just enum rather
 than enum ulong but intuitively I'd have expected the specifier
 to limit what would accept the enum. Is this how it's supposed to
 work? As a beginner with D I came across the advice that enum was
 the correct way to specify global constants but this makes it
 feel safer to use const when you want type checking and perhaps
 enum isn't the right choice.

That's how it works with integral values in general in D. If the compiler can determine that the integral value will fit in the type that you're trying to assign it to, then it'll let you do it. There's a term for this, but I forget what it is at the moment. It's a very deliberate feature decision which does vary from how it works in C/C++, and it shouldn't cause you any problems. In most cases, of course, the compiler has no idea what the value of your variable is and will have to assume that it's larger than will fit if a narrowing conversion is required, but with an enum, it always knows what the value is. But I'd expect that you'd get the same behavior if you changed VAR to immutable or const, because it's value would still always be known. Now, if you overloaded fun on int and ulong, then the ulong version should be used, because you typed VAR as being ulong, but as long as there's no ambiguity, and the compiler knows that the value that you're trying to assign to a smaller integral type will fit in that smaller integral type, it should do the narrowing conversion without an explicit cast. - Jonathan M Davis
Sep 16 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 09/16/2012 04:40 PM, Jonathan M Davis wrote:
 On Monday, September 17, 2012 01:03:46 ixid wrote:
 If I use code like:

 enum ulong VAR = 10;

 I'd have expected this to be type checked when used as a ulong.
 Instead it seems to be checked based on its absolute value and is
 accepted for a function like:

 void fun(int n) {
       // Do stuff
 }


 That's how it works with integral values in general in D. If the 

 determine that the integral value will fit in the type that you're 

 assign it to, then it'll let you do it. There's a term for this, but 

 what it is at the moment.

Value range propagation: http://www.drdobbs.com/tools/value-range-propagation/229300211 Ali
Sep 16 2012
prev sibling next sibling parent "ixid" <nuaccount gmail.com> writes:
Thanks, I had no idea that that was how it works, I tripped 
myself up with my own assumptions so took a while to find an 
error, knowing that makes it clearer.
Sep 16 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
ixid:

 As a beginner with D I came across the advice that enum was the 
 correct way to specify global constants but this makes it feel 
 safer to use const when you want type checking and perhaps enum 
 isn't the right choice.

It's a safe and quite feature of D. Unfortunately for implementation simplicity (and maybe compilation performance) this kind of static analysis is limited to single expressions. This limits its usefulness (and sometimes forces you to write larger single expressions to avoid casts, instead of assigning parts of an expression to intermediate variables). Don and Hara have discussed a bit the possibility of extending this D feature (value range propagation) to include simple cases like this, that currently don't compile: void main() { ubyte[10] array; foreach (i, ref x; array) x = i; } Even for a simple compiler it's not hard to see that this 'i' will not go past the max value of an ubyte. There are C lints that toady are able to do far more than this, and they run very fast. Bye, bearophile
Sep 16 2012