Jump to page: 1 2
Thread overview
Re: dmd 1.046 and 2.031 releases
Jul 16, 2009
bearophile
Jul 16, 2009
John C
Jul 16, 2009
bearophile
Jul 16, 2009
BCS
Jul 17, 2009
Don
Jul 17, 2009
Don
Jul 17, 2009
bearophile
Jul 17, 2009
Stewart Gordon
Jul 16, 2009
Charles Hixson
Jul 16, 2009
Jason House
July 16, 2009
I'm playing with the new D2 a bit, this comes from some real D1 code:

void main(string[] args) {
    int n = args.length;
    ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
}

At compile-time the compiler says:
temp.d(3): Error: cannot implicitly convert expression (n <= 0 ? 0 : n >= 255 ? 255 : n) of type int to ubyte

You have to add a silly cast:

void main(string[] args) {
    int n = args.length;
    ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : cast(ubyte)n));
}

In theory if the compiler gets a smarter such cast can be unnecessary.

Bye,
bearophile
July 16, 2009
bearophile Wrote:

> I'm playing with the new D2 a bit, this comes from some real D1 code:
> 
> void main(string[] args) {
>     int n = args.length;
>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
> }
> 
> At compile-time the compiler says:
> temp.d(3): Error: cannot implicitly convert expression (n <= 0 ? 0 : n >= 255 ? 255 : n) of type int to ubyte
> 
> You have to add a silly cast:
> 
> void main(string[] args) {
>     int n = args.length;
>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : cast(ubyte)n));
> }
> 
> In theory if the compiler gets a smarter such cast can be unnecessary.
> 
> Bye,
> bearophile

Did you not read the change log?

"Implicit integral conversions that could result in loss of significant bits are no longer allowed."
July 16, 2009
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 (yes, I understand the compiler is not smart enough yet to understand it, but from the things explained by Andrei I have thought it was. So I am wrong and I have shown this to other people, that may be interested. I have also encouraged to make the compiler smarter to avoid a cast in such case, because this is a single expression, so range propagation is probably not too much hard to implement given the current design of the front-end. You have missed most of the purposes of my post).

Bye,
bearophile
July 16, 2009
On Thu, 16 Jul 2009 08:49:14 -0400, bearophile <bearophileHUGS@lycos.com> wrote:

> I'm playing with the new D2 a bit, this comes from some real D1 code:
>
> void main(string[] args) {
>     int n = args.length;
>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
> }
>
> At compile-time the compiler says:
> temp.d(3): Error: cannot implicitly convert expression (n <= 0 ? 0 : n  
> >= 255 ? 255 : n) of type int to ubyte
>
> You have to add a silly cast:
>
> void main(string[] args) {
>     int n = args.length;
>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : cast(ubyte)n));
> }
>
> In theory if the compiler gets a smarter such cast can be unnecessary.
>

I don't see how, doesn't this require semantic analysis to determine whether implicit casting is allowed?  I think you are asking too much of the compiler.  What if the expression was instead a function call, should the compiler look at the function source to determine whether it can fit in a ubyte?  Where do you draw the line?  I think the current behavior is fine.  The D1 code probably works not because the compiler is 'smarter' but because it blindly truncates data.

Perhaps if it were an optimization it could be implemented, but the result of an optimization cannot change the validity of the code...

In other words, it couldn't be a compiler feature, it would have to be part of the spec, which would mean all compilers must implement it.

BTW, I think cast is a perfect requirement here -- you are saying, yes I know the risks and I'm casting anyways.

-Steve
July 16, 2009
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 (yes, I understand
> the compiler is not smart enough yet to understand it, but from the
> things explained by Andrei I have thought it was. So I am wrong and I
> have shown this to other people, that may be interested. I have also
> encouraged to make the compiler smarter to avoid a cast in such case,
> because this is a single expression, so range propagation is probably
> not too much hard to implement given the current design of the
> front-end. You have missed most of the purposes of my post).
> 
> Bye,
> bearophile

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.


July 16, 2009
Steven Schveighoffer wrote:
> On Thu, 16 Jul 2009 08:49:14 -0400, bearophile <bearophileHUGS@lycos.com> wrote:
> 
>> I'm playing with the new D2 a bit, this comes from some real D1 code:
>>
>> void main(string[] args) {
>>     int n = args.length;
>>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
>> }
>>
>> At compile-time the compiler says:
>> temp.d(3): Error: cannot implicitly convert expression (n <= 0 ? 0 : n 
>> >= 255 ? 255 : n) of type int to ubyte
>>
>> You have to add a silly cast:
>>
>> void main(string[] args) {
>>     int n = args.length;
>>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : cast(ubyte)n));
>> }
>>
>> In theory if the compiler gets a smarter such cast can be unnecessary.
>>
> 
> I don't see how, doesn't this require semantic analysis to determine whether implicit casting is allowed?  I think you are asking too much of the compiler.  What if the expression was instead a function call, should the compiler look at the function source to determine whether it can fit in a ubyte?  Where do you draw the line?  I think the current behavior is fine.  The D1 code probably works not because the compiler is 'smarter' but because it blindly truncates data.
> 
> Perhaps if it were an optimization it could be implemented, but the result of an optimization cannot change the validity of the code...
> 
> In other words, it couldn't be a compiler feature, it would have to be part of the spec, which would mean all compilers must implement it.
> 
> BTW, I think cast is a perfect requirement here -- you are saying, yes I know the risks and I'm casting anyways.
> 
> -Steve
He's saying the cast shouldn't be required, as the code entails that n will fit into a ubyte without loss of information.

Perhaps it's too much to ask.  I'm not sure.  I don't think he's sure. But if he doesn't ask, he won't find out.  (And it sure would be nice to avoid casts in situations analogous to that.)

July 16, 2009
bearophile Wrote:

> I'm playing with the new D2 a bit, this comes from some real D1 code:
> 
> void main(string[] args) {
>     int n = args.length;
>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
> }
> 
> At compile-time the compiler says:
> temp.d(3): Error: cannot implicitly convert expression (n <= 0 ? 0 : n >= 255 ? 255 : n) of type int to ubyte
> 
> You have to add a silly cast:
> 
> void main(string[] args) {
>     int n = args.length;
>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : cast(ubyte)n));
> }
> 
> In theory if the compiler gets a smarter such cast can be unnecessary.
> 
> Bye,
> bearophile

add it to bugzilla.
July 16, 2009
On Thu, Jul 16, 2009 at 6:43 PM, Jason House<jason.james.house@gmail.com> wrote:
> bearophile Wrote:
>
>> I'm playing with the new D2 a bit, this comes from some real D1 code:
>>
>> void main(string[] args) {
>>     int n = args.length;
>>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n));
>> }
>>
>> At compile-time the compiler says:
>> temp.d(3): Error: cannot implicitly convert expression (n <= 0 ? 0 : n >= 255 ? 255 : n) of type int to ubyte
>>
>> You have to add a silly cast:
>>
>> void main(string[] args) {
>>     int n = args.length;
>>     ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : cast(ubyte)n));
>> }
>>
>> In theory if the compiler gets a smarter such cast can be unnecessary.
>>
>> Bye,
>> bearophile
>
> add it to bugzilla.

Bearophile has never reported anything in Bugzilla.  It's inexplicable.  He constantly complains about D and does nothing to help it.
July 17, 2009
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 (yes, I understand
>> the compiler is not smart enough yet to understand it, but from the
>> things explained by Andrei I have thought it was. So I am wrong and I
>> have shown this to other people, that may be interested. I have also
>> encouraged to make the compiler smarter to avoid a cast in such case,
>> because this is a single expression, so range propagation is probably
>> not too much hard to implement given the current design of the
>> front-end. You have missed most of the purposes of my post).
>>
>> Bye,
>> bearophile
> 
> 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.
> 
> 
In this case, I think bearophile's right: it's just a problem with range propagation of the ?: operator. I think the compiler should be required to do the semantics analysis for single expressions. Not more, not less.
July 17, 2009
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.
« First   ‹ Prev
1 2