www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Re: dmd 1.046 and 2.031 releases

reply bearophile <bearophileHUGS lycos.com> writes:
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
Jul 16 2009
next sibling parent reply John C <johnch_atms hotmail.com> writes:
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."
Jul 16 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Jul 16 2009
next sibling parent reply BCS <ao pathlink.com> writes:
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."

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.
Jul 16 2009
next sibling parent reply Don <nospam nospam.com> writes:
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."

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.

propagation of the ?: operator. I think the compiler should be required to do the semantics analysis for single expressions. Not more, not less.
Jul 17 2009
parent reply Don <nospam nospam.com> writes:
Steven Schveighoffer wrote:
 On Fri, 17 Jul 2009 08:08:23 -0400, Don <nospam nospam.com> wrote:
 
 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.

Why? What is the benefit of keeping track of the range of integral variables inside an expression, to eliminate a cast? I don't think it's worth it. As far as I know, the ?: is the only expression where this can happen. You will get cries of inconsistency when the compiler doesn't allow: ubyte foo(uint x) { if(x < 256) return x; return 0; } -Steve

ubyte foo(uint n) { return true ? 255 : n; } And this fails: ubyte boo(uint n) { if (true) return 255; else return n; }
Jul 17 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:
 Does this compile:
 
 class C {}
 
 ubyte foo(C n)
 {
    return true ? 255 : n;
 }
 
 (don't have the latest compiler installed yet, so I couldn't check it  
 myself)

It doesn't compile (DMD v2.031): temp.d(5): Error: incompatible types for ((255) ? (n)): 'int' and 'temp.C' Bye, bearophile
Jul 17 2009
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
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."

ubyte m = (n <= 0 ? 0 : (n >= 255 ? 255 : n)); That last n is guaranteed to fit inside an ubyte


 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.
Jul 17 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 17 Jul 2009 08:08:23 -0400, Don <nospam nospam.com> wrote:

 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.

Why? What is the benefit of keeping track of the range of integral variables inside an expression, to eliminate a cast? I don't think it's worth it. As far as I know, the ?: is the only expression where this can happen. You will get cries of inconsistency when the compiler doesn't allow: ubyte foo(uint x) { if(x < 256) return x; return 0; } -Steve
Jul 17 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 17 Jul 2009 09:46:11 -0400, Don <nospam nospam.com> wrote:

 Steven Schveighoffer wrote:
 On Fri, 17 Jul 2009 08:08:23 -0400, Don <nospam nospam.com> wrote:

 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.

variables inside an expression, to eliminate a cast? I don't think it's worth it. As far as I know, the ?: is the only expression where this can happen. You will get cries of inconsistency when the compiler doesn't allow: ubyte foo(uint x) { if(x < 256) return x; return 0; } -Steve

ubyte foo(uint n) { return true ? 255 : n; } And this fails: ubyte boo(uint n) { if (true) return 255; else return n; }

Does that require range propogation? That is, when the compiler sees: return true ? 255 does it even look at the type or range of the other branch? Does this compile: class C {} ubyte foo(C n) { return true ? 255 : n; } (don't have the latest compiler installed yet, so I couldn't check it myself) I think the situation is different because the compiler isn't forced to consider the other branch, it can be optimized out (I'm surprised it doesn't do that in the general if(true) case anyways, even with optimization turned off). -Steve
Jul 17 2009
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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
Jul 16 2009
parent Charles Hixson <charleshixsn earthlink.net> writes:
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

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.)
Jul 16 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
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.
Jul 16 2009
parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 16, 2009 at 6:43 PM, Jason House<jason.james.house gmail.com> w=
rote:
 bearophile Wrote:

 I'm playing with the new D2 a bit, this comes from some real D1 code:

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

 At compile-time the compiler says:
 temp.d(3): Error: cannot implicitly convert expression (n <=3D 0 ? 0 : n=

 You have to add a silly cast:

 void main(string[] args) {
 =A0 =A0 int n =3D args.length;
 =A0 =A0 ubyte m =3D (n <=3D 0 ? 0 : (n >=3D 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.
Jul 16 2009