BCS wrote:
Reply to bearophile,

John C:

Did you not read the change log?
"Implicit integral conversions that could result in loss of
significant bits are no longer allowed."
This was the code:
ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
That last n is guaranteed to fit inside an ubyte
<snip>
I'm going with Steven on this one. Making the legality of code dependent on it's semantics is risky because it then ends up with bazaar portability issues or requiters that the scope of the semantics analysts engine be part of the language spec.

For the record, Nice has a form of automatic downcasting that works something like this, though not AFAIK on numerical comparisons. To take an example from
http://nice.sourceforge.net/safety.html#id2488356 :

----------
Component c = ...;

?List<Component> children;
if (c instanceof ContainerComponent)
  children = c.getChildren();
else
  children = null;
----------

getChildren is a method of ContainerComponent, but not of general Component. The test performed in the condition of the if statement has the additional effect of casting c to a ContainerComponent within the if statement's body. Nice also has nullable and non-nullable types (note the ?) and, in the same way, it forces you to check that it isn't null before you try to dereference it.

The principle could be applied to if statements and ?: expressions alike (as it would appear Nice does), and even && and || expressions. And it could be extended to arithmetic comparisons. A possible way is to spec that, if n is an int, and k is a compile-time constant >= 0, then given

    n >= k ? expr1 : expr2

any occurrence of n in expr1 is treated as cast(uint) n. And similarly for the other relational operators and other signed integer types. And then that, if u is of some unsigned integer type, and k is a compile-time constant within the range of u's type, then given

    u <= k ? expr1 : expr2

any occurrence of u in expr1 is treated as cast to the smallest unsigned integer type that u will fit into. And similarly for the other relational operators. Then your example would compile. However,

- if we're going to do this, then for consistency we probably ought to define all literals to be of the smallest type they'll fit into, and prefer unsigned over signed, unless overridden with a suffix

- we could go on defining rules like this for more complicated conditions, and it could get complicated

- I'm not sure if this kind of automatic casting is desirable from a generic programming POV.

Stewart.

Reply via email to