Jump to page: 1 2 3
Thread overview
Why there is too many uneccessary casts?
Jun 11, 2013
Temtaime
Jun 11, 2013
Simen Kjaeraas
Jun 11, 2013
Temtaime
Jun 11, 2013
Simen Kjaeraas
Jun 11, 2013
Simen Kjaeraas
Jun 11, 2013
Temtaime
Jun 11, 2013
Simen Kjaeraas
Jun 11, 2013
bearophile
Jun 11, 2013
Adam D. Ruppe
Jun 11, 2013
QAston
Jun 11, 2013
H. S. Teoh
Jun 11, 2013
Timothee Cour
Jun 11, 2013
Adam D. Ruppe
Jun 11, 2013
bearophile
Jun 11, 2013
Adam D. Ruppe
Jun 12, 2013
captaindet
Jun 12, 2013
Ali Çehreli
Jun 12, 2013
Adam D. Ruppe
Jun 12, 2013
Adam D. Ruppe
Jun 12, 2013
captaindet
June 11, 2013
ubyte k = 10;
ubyte c = k + 1;

This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte

Why? It's pain in the ass, i think. My code contains only casts then.
June 11, 2013
On Tue, 11 Jun 2013 12:12:25 +0200, Temtaime <temtaime@gmail.com> wrote:

> ubyte k = 10;
> ubyte c = k + 1;
>
> This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte
>
> Why? It's pain in the ass, i think. My code contains only casts then.

Because it's unsafe. The compiler does not know if k+1 fits in a ubyte.

(True, in this case it could know it, but it does not, and in the general
case it can't know)

-- 
Simen
June 11, 2013
There is overflow and it can be with int too.
It's standard behavior.
June 11, 2013
On Tue, 11 Jun 2013 12:39:47 +0200, Temtaime <temtaime@gmail.com> wrote:

> There is overflow and it can be with int too.
> It's standard behavior.

Indeed. And a class is a void* is an int is a char is a double? That's
perfectly possible - it's all just memory anyway. D has chosen to do
it like this to prevent common errors. If you think the cast stands
out like a sore thumb, use:

ubyte k = 10;
ubyte c = (k + 1) & 0xFF;

That way, value range propagation ensures the result fits in a ubyte,
and the code compiles happily.

-- 
Simen
June 11, 2013
Temtaime:

> ubyte k = 10;
> ubyte c = k + 1;
>
> This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte
>
> Why? It's pain in the ass, i think. My code contains only casts then.

I agree that sometimes that's a pain.
Currently D performs a range analysis only inside one expression, and not across different ones.

One way to avoid the cast is to perform a masking:

void main() {
    immutable ubyte UB = ubyte.max;
    ubyte k = 10;
    ubyte c = (k + 1) & UB;
}



The solution is to improve D.
Beside fixing this bug:
http://d.puremagic.com/issues/show_bug.cgi?id=9107

A first step is to keep the range value for immutable variables, but this is not enough to solve your problem because your k is mutable:
http://d.puremagic.com/issues/show_bug.cgi?id=10018

Your case is very simple. It's just a sequence of instructions, with no gotos, no jumps, no control instructions, no function calls. Introducing some simple conservative rules for such simple situation is possible. But the advantage of the current situation is that it make usually easy to know where to put a cast and where it's not needed. The more complex the rules become, the harder is to know where the casts are not needed.

Bye,
bearophile
June 11, 2013
On Tue, 11 Jun 2013 13:15:11 +0200, Simen Kjaeraas <simen.kjaras@gmail.com> wrote:

> On Tue, 11 Jun 2013 12:39:47 +0200, Temtaime <temtaime@gmail.com> wrote:
>
>> There is overflow and it can be with int too.
>> It's standard behavior.
>
> Indeed. And a class is a void* is an int is a char is a double? That's
> perfectly possible - it's all just memory anyway. D has chosen to do
> it like this to prevent common errors. If you think the cast stands
> out like a sore thumb, use:
>
> ubyte k = 10;
> ubyte c = (k + 1) & 0xFF;
>
> That way, value range propagation ensures the result fits in a ubyte,
> and the code compiles happily.

Also worth noting: both & 0xFF and cast(ubyte) shows that the programmer
has considered the possibility of overflow (or just programmed blindly,
but let's assume a rational programmer), something your original code did
not.

Looking at this code:

  ubyte a = foo();
  ubyte b = a + 1;
  doSomethingWith(b);

It's not possible for me to know if that code works correctly if foo()
returns 255 - perhaps it should actually be saturated (255+1 == 255),
perhaps it should even throw an exception. With this code:

  ubyte a = foo();
  ubyte b = cast(ubyte)(a + 1); // or (a + 1) & 0xFF;
  doSomethingWith(b);

The programmer has documented something: If this causes an overflow,
the value in b is still correct. Explicit is better than implicit.

-- 
Simen
June 11, 2013
No. I means, that

uint a = uint.max;
uint b = a + 1;
writeln(b);

Works OK.
Why? Compiler doesn't know if a + b fits in uint, right?
Then why overflow with ints are accepted?

So your example is meaningless.
June 11, 2013
On Tue, 11 Jun 2013 13:46:11 +0200, Temtaime <temtaime@gmail.com> wrote:

> No. I means, that
>
> uint a = uint.max;
> uint b = a + 1;
> writeln(b);
>
> Works OK.
> Why? Compiler doesn't know if a + b fits in uint, right?
> Then why overflow with ints are accepted?

Because there's a limit to how far this goes without introducing
arbitrary-precision numbers. There is indeed an argument for uint+uint
giving a ulong answer, and I'm confused myself at why this is not the
case.


> So your example is meaningless.

No.

-- 
Simen
June 11, 2013
Temtaime:

> Why? Compiler doesn't know if a + b fits in uint, right?
> Then why overflow with ints are accepted?

It's an inconstancy based on practical considerations.

Walter decided that applying the same rule to uint/int/long causes too many casts in normal problems.

And the range of a 32 bit int is much larger than the range of a ubyte/byte/ushort/short, so in normal programs the probability of overflowing an int by mistake is much lower than overflowing a ubyte.


> So your example is meaningless.

You should be more gentle if you want people to keep giving you answers :-)

Bye,
bearophile
June 11, 2013
On Tuesday, 11 June 2013 at 10:12:27 UTC, Temtaime wrote:
> ubyte k = 10;
> ubyte c = k + 1;
>
> This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte

The reason is arithmetic operations transform the operands into ints, that's why the error says cast(int)k. Then it thinks int is too big for ubyte. It really isn't about overflow, it is about truncation.

That's why uint + 1 is fine. The result there is still 32 bits so assigning it to a 32 bit number is no problem, even if it does overflow. But k + 1 is promoted to int first, so it is a 32 bit number and now the compiler complains that you are trying to shove it into an 8 bit variable. Unless it can prove the result still fits in 8 bits, it complains, and it doesn't look outside the immediate line of code to try to prove it. So it thinks k can be 255, and 255 + 1 = 256, which doesn't fit in 8 bits.

The promotion to int is something D inherited from C and probably isn't going anywhere.
« First   ‹ Prev
1 2 3