Bug 13387 – Bug with arithmetic opertions on integer types smaller than int

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-08-28T06:25:06Z
Last change time
2020-03-21T03:56:41Z
Assigned to
No Owner
Creator
Uranuz

Comments

Comment #0 by neuranuz — 2014-08-28T06:25:06Z
I consider it is buggy behaviour that when I sum two values of the same type and I get resulting value of another type. And also when sum two integer values of different type I think that resulting value must be biggest in size type of these two, but not other third type that is not expected to be. //---------- void main() { ubyte a = 1; ushort b = 2; ushort c = a + b; } // Error: cannot implicitly convert expression (cast(int)a + cast(int)b) of type int to ushort //---------- void main() { byte a = 1; byte b = 2; byte c = a + b; } //---------- void main() { short a = 1; short b = 2; short c = a - b; } //---------- Also I consider assigning uint to int without explicit cast is senseless and unsafe //---------- void main() { uint a = uint.max; int c = a; //This must issue an error } //---------- But this could be allowed because ubyte max number could be stored in int or in short //---------- void main() { ubyte a = ubyte.max; short b = a; //Is OK int c = a; //Is OK } //---------- Also implicit cast from byte, short. etc. with combination with *alias this* becomes source of silent bugs. But I don't know what to do with it, because forbidding all the integer implicit casts is not good to, because assigning short -> int is useful in most cases. Example that demonstrates these silent bugs with using alias this and integers: //---------- import std.stdio, std.typecons; interface ListControl { @property { void selValue(int value); void selValue(Nullable!int value); } } class CheckBoxList: ListControl { override @property { void selValue(int value) { writeln("value: int"); } void selValue(Nullable!int value) { writeln("value: Nullable!int"); } } } void main() { //Someone considered to make it of byte type //instead of int to save memory Nullable!byte myValue; //it is null/uninitialized //Creating object auto checkBoxList = new CheckBoxList; //Let's assign value to our property //You see that types don't match. But let's imagine that it is a complicated project //and class implementation and *myValue* located in different modules so programmer don't remember right type checkBoxList.selValue = myValue; //This just silently fails in runtime without some compile-time error } //---------- More simple example shows that Nullable based on integer types is source of silent (at compile-time) bugs //---------- import std.typecons; void main() { Nullable!byte a; Nullable!int b; b = a; //This fails in runtime } //----------
Comment #1 by neuranuz — 2014-08-28T07:06:39Z
AFAIK, in C++ the same rules used, but it don't have problems with assignment of type *unsigned short = unsigned short + unsigned short*. So it's strange that we have such type of problem in D. But still integer promotions are used to, although I disagree with it. //------------- #include <iostream> #include <typeinfo> int main() { unsigned short a = 5; unsigned short b = 3; unsigned short c = a + b; //This compiles if( typeid(a + b) == typeid(int) ) { std::cout << "int" << std::endl; } else if( typeid(a + b) == typeid(unsigned short) ) { std::cout << "unsigned short" << std::endl; } else if( typeid(a + b) == typeid(unsigned int) ) { std::cout << "unsigned int" << std::endl; } return 0; } //------------- This programme outputs: int
Comment #2 by bearophile_hugs — 2014-08-29T06:59:14Z
(In reply to Uranuz from comment #1) > So it's strange that we have such type of problem in D. It's a "problem" introduced on purposes in D. Regarding byte+byte=int it's done like this in D to follow the C rules. I think it's hard to change this.
Comment #3 by b2.temp — 2020-02-20T11:04:12Z
There's nothing applicable here, despite of personnal preferences. Implicit conversions and integral promotions rules are specified and this cannot change without creating massive breakages.