http://d.puremagic.com/issues/show_bug.cgi?id=1977
------- Comment #16 from [EMAIL PROTECTED] 2008-11-24 16:55 ------- I searched around, and you are right that C# disallows compiling byte + byte operands, and it does allow += operands. The reasons given were not to forbid reassignment to the same type for fear of overflow (as is obvious by allowing the += operation), the point is to prevent operation overflow where it is not expected. for example: int x = (byte)64 + (byte)64; should result in x == 128, not x == -128. And the enforcement is not in the compiler warning system, the enforcement is that they only define op codes for integer arithmetic, so the compiler promotes the bytes to integers which result in an integer. But C++ does not forbid it, at least with g++ (even with -Wall). This is not to say that the choices C# made are correct, it's just that there is precedent in C# (couldn't find Java reference, but I'm sure it's the same). Here is a possible solution that allows current safe behavior and relaxes the implicit casting rules enough so that overflow is allowed to happen in the correct situations: I think everyone agrees that the following: byte b = 64; int i = b + b; should produce i == 128. And most believe that: byte b2 = b + b; should produce b2 == -128 without error, and should be equivalent semantically to: byte b2 = b; b2 += b; We don't want adding 2 bytes together to result in a byte result in all cases, only in cases where the actual assignment or usage is to a byte. What if we defined several 'internal' types that were only used by the compiler? pbyte -> byte promoted to an int (represented as an int internally) pubyte -> ubyte promoted to an int pshort -> short promoted to an int pushort -> ushort promoted to an int etc... The 'promoted' types internally work just like int except in certain cases: If you have (px or x) <op> (px or x), the resulting type is px If you have (px or x) <op> (py or y), or (py or y) <op> (px or x), and the rules of promotion allow x to be implicitly cast to y, the resulting type is py. Otherwise, the resulting type is int. px is implicitly castable to x. if the rules of promotion allow x to be implicitly cast to y, px is implicitly castable to y. otherwise, assigning px to y requires an explicit cast. if calling a function foo with argument type px, where foo accepts type x, it is allowed. If calling a function foo with argument type px, where foo accepts type y, and x is implicitly castable to y, it is allowed. If x is not implicitly castable to y, it requires a cast. if a variable is declared with 'auto', and the initializer is of type px, then the variable is declared as an int. You can't declare any variables of type pbyte, etc, and the types actually don't have symbolic names, they are used internally by the compiler. Now you have correct resolution of homogeneous operations, and no overflow of data where it is not desired. examples: byte b = 64; b + b -> evaluates to pbyte(128) b = b + b -> evaluates to b = pbyte(128), results in b == -128 int i = b + b -> evaluates to int i = pbyte(128), results in i == 128. short s = b + b -> evaultes to short s = pbyte(128), results in s == 128. short s = 64; byte b = s + s; -> evaluates to byte b = pshort(128), requires a cast because short does not fit into byte. void foo(byte b); void foo2(short s); byte x; short s; foo(x + x); // allowed foo2(x + x); // allowed foo(s + s); // requires cast foo2(s + s); // allowed Does this cover the common cases? Is there a reason why this can't be implemented? Is there a reason why this *shouldn't* be implemented? --