digitalmars.D.bugs - [Issue 1977] New: integral arithmetic operation only on int?
- d-bugmail puremagic.com (26/26) Apr 07 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (12/12) Nov 20 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (8/8) Nov 21 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (9/9) Nov 21 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (14/19) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (21/26) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- Don (10/47) Nov 26 2008 Personally I think having to insert a cast makes the code more
- Andrei Alexandrescu (4/61) Nov 26 2008 Could you paste your comment into bugzilla so we have the discussion
-
Stewart Gordon
(11/13)
Nov 26 2008
"Andrei Alexandrescu"
wrote in message - Jarrett Billingsley (4/8) Nov 26 2008 I got the impression from Brad that he was surprised that it no longer
- d-bugmail puremagic.com (22/26) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (17/39) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (12/29) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (5/8) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (29/42) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (27/33) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (21/69) Nov 22 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (27/40) Nov 24 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (8/26) Nov 24 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (5/27) Nov 24 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (77/77) Nov 24 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (30/132) Nov 24 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (24/64) Nov 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (9/20) Nov 25 2008 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (16/16) Aug 05 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (27/36) Aug 08 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (9/9) Aug 08 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (14/19) Aug 08 2009 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (14/14) Oct 12 2012 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (17/18) Oct 12 2012 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (7/14) Oct 13 2012 I don't see. In the example above( http://dpaste.dzfl.pl/8b9f5471 ), the...
- d-bugmail puremagic.com (11/12) Oct 13 2012 in y is 16777216, which is greater than ushort.max.
- d-bugmail puremagic.com (8/9) Oct 13 2012 http://d.puremagic.com/issues/show_bug.cgi?id=1977
- d-bugmail puremagic.com (7/8) Oct 13 2012 narrowing conversion.
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Summary: integral arithmetic operation only on int? Product: D Version: 2.012 Platform: PC OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: bugzilla digitalmars.com ReportedBy: someanon yahoo.com There's no arithmetic operation for byte? everything has to be cast to int (and back)? I try to use the '-w' switch to clear all warnings, but this one isn't necessary: $ cat bytewarn.d byte f(byte i) { byte t = 1; byte o = t - i; return o; } $ dmd -w -c bytewarn.d warning - bytewarn.d(4): Error: implicit conversion of expression (cast(int)t - cast(int)i) of type int to byte can cause loss of data --
Apr 07 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 smjg iname.com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |smjg iname.com Keywords| |diagnostic It's as documented. Integral types smaller than int are automagically converted to int when performing arithmetic on them. But it is somewhat ridiculous that it should still throw the warning in such cases as this. --
Nov 20 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 jarrett.billingsley gmail.com changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |schveiguy yahoo.com *** Bug 2466 has been marked as a duplicate of this bug. *** --
Nov 21 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Note that this also errors, and is provably correct. byte b; short s = b + b; IMO, all arithmetic should be allowed on homogeneous operations. That is, performing arithmetic on two like types should be implicitly assignable to the same type. --
Nov 21 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 andrei metalanguage.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |INVALIDIt's as documented. Integral types smaller than int are automagically converted to int when performing arithmetic on them. But it is somewhat ridiculous that it should still throw the warning in such cases as this.It's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable. The community has insisted for a long time to tighten integral operations, and now that it's happening, the tightening is reported as a bug :o). --
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 schveiguy yahoo.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID |It's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable.Why is this also flagged (no overflow possible): short f(byte i) { byte t = 1; short o = t - i; return o; }The community has insisted for a long time to tighten integral operations, and now that it's happening, the tightening is reported as a bug :o).But it's pretty inconsistent. If I add two random ints together, I will get an overflow in 25% of cases, why is that not flagged? I think the restriction is too tight. People expect to do math on homogeneous types without having to cast the result, as they do with ints. And I'll say I was not one of the people asking for this 'feature'. I'm not sure where that came from. --
Nov 22 2008
d-bugmail puremagic.com wrote:http://d.puremagic.com/issues/show_bug.cgi?id=1977 schveiguy yahoo.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID |Personally I think having to insert a cast makes the code more error-prone. The cure is worse than the disease. Consider also that with the original code, the compiler could install debug-time asserts on any such narrowing conversion. Once you insert a cast, that's impossible, since the language doesn't distinguish between (a) 'I know that is OK' casts, (b) 'I want to pretend that this is a different type' casts, and (c) 'I want you to change this into another type' casts. Compiler checks should only be inserted for case (a) and (c).It's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable.Why is this also flagged (no overflow possible): short f(byte i) { byte t = 1; short o = t - i; return o; }The community has insisted for a long time to tighten integral operations, and now that it's happening, the tightening is reported as a bug :o).But it's pretty inconsistent. If I add two random ints together, I will get an overflow in 25% of cases, why is that not flagged? I think the restriction is too tight. People expect to do math on homogeneous types without having to cast the result, as they do with ints. And I'll say I was not one of the people asking for this 'feature'. I'm not sure where that came from.
Nov 26 2008
Don wrote:d-bugmail puremagic.com wrote:Could you paste your comment into bugzilla so we have the discussion tracked there? Thanks. Andreihttp://d.puremagic.com/issues/show_bug.cgi?id=1977 schveiguy yahoo.com changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID |Personally I think having to insert a cast makes the code more error-prone. The cure is worse than the disease. Consider also that with the original code, the compiler could install debug-time asserts on any such narrowing conversion. Once you insert a cast, that's impossible, since the language doesn't distinguish between (a) 'I know that is OK' casts, (b) 'I want to pretend that this is a different type' casts, and (c) 'I want you to change this into another type' casts. Compiler checks should only be inserted for case (a) and (c).It's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable.Why is this also flagged (no overflow possible): short f(byte i) { byte t = 1; short o = t - i; return o; }The community has insisted for a long time to tighten integral operations, and now that it's happening, the tightening is reported as a bug :o).But it's pretty inconsistent. If I add two random ints together, I will get an overflow in 25% of cases, why is that not flagged? I think the restriction is too tight. People expect to do math on homogeneous types without having to cast the result, as they do with ints. And I'll say I was not one of the people asking for this 'feature'. I'm not sure where that came from.
Nov 26 2008
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:ggju97$2871$2 digitalmars.com... <snip>Could you paste your comment into bugzilla so we have the discussion tracked there? Thanks.Has the automatic relaying of newsgroup posts to Bugzilla been discontinued, or does it only work if the email address it's sent from is registered? It was probably the right thing to do considering the excessive quoting that happens too often. Stewart. -- My e-mail address is valid but not my primary mailbox. Please keep replies on the 'group where everybody may benefit.
Nov 26 2008
On Wed, Nov 26, 2008 at 12:30 PM, Stewart Gordon <smjg_1998 yahoo.com> wrote:Has the automatic relaying of newsgroup posts to Bugzilla been discontinued, or does it only work if the email address it's sent from is registered? It was probably the right thing to do considering the excessive quoting that happens too often.I got the impression from Brad that he was surprised that it no longer worked, at least when I mentioned it a couple weeks ago. Maybe some settings just got changed.
Nov 26 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 smjg iname.com changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |enhancement Summary|integral arithmetic |Relax warnings for implicit |operation only on int? |narrowing conversions caused | |by promotionsIt's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable.I disagree: - Read comment 3. How can adding (or even subtracting, multiplying or dividing) two numbers in the range [-128, 127] possibly produce a value outside the range [-32768, 32767]? - If you're using (u)byte/(u)short, it follows that you should know what you're doing. Especially if you're doing it in an initialiser of something declared explicitly as one of these types, in which case you've shown that you know what you're doing. - It happens even in the case of bitwise operations (&, |, ^, >>, >>>, but strangely not ~), by which overflow is impossible. It might be sensible for <<, but no more. --
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977This should go through no problem indeed, I hadn't seen your first reply when I replied.It's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable.Why is this also flagged (no overflow possible): short f(byte i) { byte t = 1; short o = t - i; return o; }In general, we want to go with the simple rule is to have an operation return the tightest type that won't engender overflow (which precludes making 8- and 16-bit values as closed sets for addition). The exception to that is int, which for a combination of practical reasons, "stays" int even if it could overflow, and also long, which cannot go any larger. Anecdotal evidence suggests that unintended overflows can be more annoying than having to insert the occasional cast. We could relax this rule by having the compiler statically tracking possible ranges of values. The random ints argument does not quite hold because one seldom adds fully random 32-bit values. "Most integers are small." --The community has insisted for a long time to tighten integral operations, and now that it's happening, the tightening is reported as a bug :o).But it's pretty inconsistent. If I add two random ints together, I will get an overflow in 25% of cases, why is that not flagged? I think the restriction is too tight. People expect to do math on homogeneous types without having to cast the result, as they do with ints. And I'll say I was not one of the people asking for this 'feature'. I'm not sure where that came from.
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977Sorry. Indeed, that is a good reason to keep the bug opened.It's not ridiculous at all. The compiler cannot tell what values will be possibly passed to f, and the range of byte and short are sufficiently small to make overflow as frequent as it is confusing and undesirable.I disagree: - Read comment 3. How can adding (or even subtracting, multiplying or dividing) two numbers in the range [-128, 127] possibly produce a value outside the range [-32768, 32767]?- If you're using (u)byte/(u)short, it follows that you should know what you're doing. Especially if you're doing it in an initialiser of something declared explicitly as one of these types, in which case you've shown that you know what you're doing.Often, a 8/16-bit int comes from a need to minimize occupied storage in a larger structure, to conform to some format etc. I do agree that often people operating with such structures/in such environments do know what they're doing, but that doesn't mean that implies they must increase their attention. Knowing what they're doing, they'll insert a cast.- It happens even in the case of bitwise operations (&, |, ^, >>, >>>, but strangely not ~), by which overflow is impossible. It might be sensible for <<, but no more.The plan is to have sensible bitwise operations preserve the size of their operands. Only arithmetic and shift will "spill" into larger types. --
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977The plan is to have sensible bitwise operations preserve the size of their operands. Only arithmetic and shift will "spill" into larger types.I hope you mean only *left* shift will spill into a larger type. --
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977In general, we want to go with the simple rule is to have an operation return the tightest type that won't engender overflow (which precludes making 8- and 16-bit values as closed sets for addition).Really? I disagree that 16 bit addition causes frequent overflow. I'm not sure in what contexts you are using it, can you give an example? And 8-bit addition is very frequent for character transformations, i.e. converting to upper case: c += 'A' - 'a'; Casting seems too strict a requirement in these types of situations. I can't imagine that anyone has a positive experience with these warnings, most are just going to grumble, then insert the cast without thinking about it.The exception to that is int, which for a combination of practical reasons, "stays" int even if it could overflow, and also long, which cannot go any larger. Anecdotal evidence suggests that unintended overflows can be more annoying than having to insert the occasional cast.I haven't seen such anecdotal evidence. I don't think I've ever seen an overflow due to addition that wasn't intended in my code on 16 or 8-bit values. The one case where casting should be required is doing comparisons of signed to unsigned values, where the comparison flips what it should be. A classic case that I've had with C++ is comparing the size() of a vector to some subtraction of integers. But this should be flagged because you are comparing signed to unsigned (and most good C++ compilers flag that). Multiplication might be a different story.We could relax this rule by having the compiler statically tracking possible ranges of values.Why not just relax it to allow reassignment to the same type? I don't think that's an uncommon usage, and I don't think it would cause rampant failures.The random ints argument does not quite hold because one seldom adds fully random 32-bit values. "Most integers are small."Most integers are small, including 16-bit integers. If one uses a 16-bit integer, they are generally doing so because they know the domain of such values is small. 8-bit integers that one performs math on are generally characters, generally used for transforming them. Most of the time, the domain of such values is known to be less than the domain of 8-bit integers. For example, ascii characters. --
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977Correct. So let's recap a possible set of rules: (a) Operations will yield the statically tightest type possible, but never smaller than the largest of the two operands. (b) However, (a) will not cause automatic promotion from 32-bit to 64-bit, i.e., unless at least one operand is 64-bit, the result will never be 64-bit. (c) (Not yet implemented) If one operand's value is statically-known, further tightening without a cast is possible, e.g.: uint a = ...; byte b = a & 1; // pass, no cast needed (d) (Not yet implemented, open-ended) Even if operand values are not statically known, their possible range is computed statically in a flow-insensitive manner and used for validation, e.g.: uint a = 4; if (condition) a = 200; // a is not in range [4, 200] ubyte x = a & 200; // pass ==== The "but never smaller than the largest of the two operands" is meant to avoid surprises of the following sort: uint a = ...; auto b = a & 1; // how do you mean b is ubyte?!? However, notice that due to (c), explicitly asking for a byte does work. --The plan is to have sensible bitwise operations preserve the size of their operands. Only arithmetic and shift will "spill" into larger types.I hope you mean only *left* shift will spill into a larger type.
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977The most recent example that comes to mind is std.format. Out of probably too much zeal, I store the width and precision as short numbers. There are several places in the code using them where I had to pay close attention to possible overflows.In general, we want to go with the simple rule is to have an operation return the tightest type that won't engender overflow (which precludes making 8- and 16-bit values as closed sets for addition).Really? I disagree that 16 bit addition causes frequent overflow. I'm not sure in what contexts you are using it, can you give an example?And 8-bit addition is very frequent for character transformations, i.e. converting to upper case: c += 'A' - 'a'; Casting seems too strict a requirement in these types of situations. I can't imagine that anyone has a positive experience with these warnings, most are just going to grumble, then insert the cast without thinking about it.Notice that in the particular example you mention, the code does go through because it uses +=.This may mean that you are a great coder and that you and I frequent different circles.The exception to that is int, which for a combination of practical reasons, "stays" int even if it could overflow, and also long, which cannot go any larger. Anecdotal evidence suggests that unintended overflows can be more annoying than having to insert the occasional cast.I haven't seen such anecdotal evidence. I don't think I've ever seen an overflow due to addition that wasn't intended in my code on 16 or 8-bit values.The one case where casting should be required is doing comparisons of signed to unsigned values, where the comparison flips what it should be. A classic case that I've had with C++ is comparing the size() of a vector to some subtraction of integers. But this should be flagged because you are comparing signed to unsigned (and most good C++ compilers flag that). Multiplication might be a different story.Walter believes the same. I disagree.We could relax this rule by having the compiler statically tracking possible ranges of values.Why not just relax it to allow reassignment to the same type? I don't think that's an uncommon usage, and I don't think it would cause rampant failures.Storage considerations may be at stake though. In fact, most of the uses of small integers I've seen in C and C++ come from a storage/format requirement, not a range requirement. In fact, what I'm saying is a tautology because in C and C++ there is very little enforcement on range, which means there is very low incentive to express small ranges with small integers.The random ints argument does not quite hold because one seldom adds fully random 32-bit values. "Most integers are small."Most integers are small, including 16-bit integers. If one uses a 16-bit integer, they are generally doing so because they know the domain of such values is small.8-bit integers that one performs math on are generally characters, generally used for transforming them. Most of the time, the domain of such values is known to be less than the domain of 8-bit integers. For example, ascii characters.The compiler can't guess such legitimacy. In the characters domain, we might be able to target our effort towards improving operations on char, wchar, and dchar. --
Nov 22 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977Wow, that surprises me. c = c + c should be equivalent to c += c; So right there, either both should be invalid, or neither should. Both have an equal chance of overflow. In fact, using obj2asm, I found that both are essentially equivalent. With optimization on, here are the two different code generations (minus all bookkeeping stuff): char foo(char c) { c += c; // version 1 c = c + c; // version 2 return c; } c += c; < mov ECX,EAX < add CL,CL < mov AL,CL c = c + c;c += 'A' - 'a'; Casting seems too strict a requirement in these types of situations. I can't imagine that anyone has a positive experience with these warnings, most are just going to grumble, then insert the cast without thinking about it.Notice that in the particular example you mention, the code does go through because it uses +=.push EAX movzx ECX,byte ptr -4[EBP] mov EAX,ECX add AL,ALThese are essentially the same, except in the second version, the compiler optimizer didn't see the oportunity to get down to the same code as the first version (there's probably even more optimization to be had even in the first version). But the danger of overflow still exists in both cases. I'm not sure why one is treated more dangerously than the other by the compiler. --
Nov 24 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977the same rules. The correct equivalence is that c = c + c is really c = cast(typeof(c))(c + c).Wow, that surprises me. c = c + c should be equivalent to c += c; So right there, either both should be invalid, or neither should. Both have an equal chance of overflow.c += 'A' - 'a'; Casting seems too strict a requirement in these types of situations. I can't imagine that anyone has a positive experience with these warnings, most are just going to grumble, then insert the cast without thinking about it.Notice that in the particular example you mention, the code does go through because it uses +=.In fact, using obj2asm, I found that both are essentially equivalent.That's irrelevant. Operational semantics are different from typechecking. --
Nov 24 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977I meant c += c is equivalent to cast(typeof(c))(c + c). --the same rules. The correct equivalence is that c = c + c is really c = cast(typeof(c))(c + c).Wow, that surprises me. c = c + c should be equivalent to c += c; So right there, either both should be invalid, or neither should. Both have an equal chance of overflow.c += 'A' - 'a'; Casting seems too strict a requirement in these types of situations. I can't imagine that anyone has a positive experience with these warnings, most are just going to grumble, then insert the cast without thinking about it.Notice that in the particular example you mention, the code does go through because it uses +=.
Nov 24 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 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). 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? --
Nov 24 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977operands, 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.That's not quite accurate. Again, it's one thing to pass typechecking and one thing to generate code. Any desired rule could have been implemented with only int arithmetic and subsequent masking.But C++ does not forbid it, at least with g++ (even with -Wall).C++ operates in a similar way (values are conceptually promoted to int before arithmetic operations) but it's much more lax with narrowing conversions. That's why there is no problem with assigning the result of adding e.g. two shorts back to a short: the computation really yields an int, but C++ has no qualms about narrowing that into a short, regardless of the potential loss of data.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.I think there is agreement on that, too.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.Well the "most" part doesn't quite pan out, and to me it looks like the argument fails here. For one thing, we need to eliminate people who accept Java do. Also, C and C++ are getting that right by paying a very large cost - of allowing all narrowing integral conversions. I believe there is a reasonable level of agreement that automatic lossy conversions are not to be encouraged.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?IMHO not enough rationale has been brought forth on why this *should* be implemented. It would make D implement an arcane set of rules for an odd, if any, benefit. A better problem to spend energy on is the signed <-> unsigned morass. We've discussed that many times and could not come up with a reasonable solution. For now, D has borrowed the C rule "if any operand is unsigned then the result is unsigned" leading to the occasional puzzling results known from C and C++. Eliminating those fringe cases without losing compatibility with C and C++ is a tough challenge. --
Nov 24 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977Just because people use a language, doesn't mean they agree with every overwhelming majority prefers no error to the oversafe current implementation. The defenders of the current rules invariably use the case of adding two bytes together and assigning to an integer, their argument being that if you have the result of adding two bytes be a byte, then the integer result is a truncated byte. If we eliminate that case from contention, as my solution has done, I think you'd be hard pressed to find anyone who thinks the loss of data errors are still needed in the cases such as the one that spawned this discussion.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.Well the "most" part doesn't quite pan out, and to me it looks like the argument fails here. For one thing, we need to eliminate people who accept Java do.Also, C and C++ are getting that right by paying a very large cost - of allowing all narrowing integral conversions. I believe there is a reasonable level of agreement that automatic lossy conversions are not to be encouraged.I agree, general narrowing conversions should be failed. It's just in the case of where arithmetic has artificially promoted the result where we disagree.Probably, it isn't that critical to the success of D that this be implemented. If I had to choose something to look at, this probably wouldn't be it. This is just one of those little things that seems unnecessary and annoying more than it is blocking. It shows up seldom enough that it probably isn't worth the trouble to fix. But I have put my solution forth, and as far as I can tell, you didn't find anything wrong with it, and that's about all I can do.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...IMHO not enough rationale has been brought forth on why this *should* be implemented. It would make D implement an arcane set of rules for an odd, if any, benefit.A better problem to spend energy on is the signed <-> unsigned morass. We've discussed that many times and could not come up with a reasonable solution. For now, D has borrowed the C rule "if any operand is unsigned then the result is unsigned" leading to the occasional puzzling results known from C and C++. Eliminating those fringe cases without losing compatibility with C and C++ is a tough challenge.Indeed. Without promoting to a larger type, I think you are forced to take this course of action. When adding an int to a uint, who wants it to wrap around to a negative value? I can't think of a better solution. --
Nov 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977You just did in fact. Your idea with defining some internal types is very similar to one of the promising solutions we've been exploring for resolving signedness of arithmetic operations. I will in fact stop here and paste the rest of my message to the main newsgroup because it's of general interest and segues away from this bug report. --A better problem to spend energy on is the signed <-> unsigned morass. We've discussed that many times and could not come up with a reasonable solution. For now, D has borrowed the C rule "if any operand is unsigned then the result is unsigned" leading to the occasional puzzling results known from C and C++. Eliminating those fringe cases without losing compatibility with C and C++ is a tough challenge.Indeed. Without promoting to a larger type, I think you are forced to take this course of action. When adding an int to a uint, who wants it to wrap around to a negative value? I can't think of a better solution.
Nov 25 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Jason House <jason.james.house gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason.james.house gmail.com 06:11:47 PDT --- Here's a related issue: long a; ... int b = a % 1000; The sample above gives an error that it can't implicitly convert to int, even though this us exactly the kind of thing implicit narrowing conversions should handle. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 05 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Stewart Gordon <smjg iname.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Version|2.012 |unspecified Summary|Relax warnings for implicit |Relax warnings (D1)/errors |narrowing conversions |(D2) for implicit narrowing |caused by promotions |conversions caused by | |promotions OS/Version|Linux |All ---Here's a related issue: long a; ... int b = a % 1000; The sample above gives an error that it can't implicitly convert to int, even though this us exactly the kind of thing implicit narrowing conversions should handle.That's different, since it isn't due to promotions beyond the lowest common denominator of the operand types. The best way to deal with this is to spec that the type of a % expression (and similarly &) on integers is the smaller of the operands' types. There's no loss of significant digits this way, at least if they're both signed or both unsigned. But if one's signed and the other's unsigned, _then_ what should happen? If you're worried about breaking existing D1 code, this can still be achieved by doing this only to the base type and not the promoted type (using the terminology I introduced at http://www.digitalmars.com/d/archives/24706.html#N24797 ) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 08 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1977 09:17:31 PDT --- I'm only worrying about D2 where implicit narrowing conversions is part of the spec. ulong%1000 should implicitly allowed when assigning to an integer. Should it be a distinct bugzilla entry? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 08 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Andrei Alexandrescu <andrei metalanguage.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |andrei metalanguage.com 09:39:54 PDT ---I'm only worrying about D2 where implicit narrowing conversions is part of the spec. ulong%1000 should implicitly allowed when assigning to an integer. Should it be a distinct bugzilla entry?Range value propagation, which was implemented recently, should take care of this. It's among the simplest examples that should work with range value propagation. The compiler must infer that a % 1000 has range -999 through 999 and therefore should allow it to fit in a short or int. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 08 2009
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Ryuichi OHORI <r.97all gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |r.97all gmail.com --- I still has read not all of the this conversation, but I think my issue is related to this. trivially incorrect use of op assignment operator is allowed: ushort |= int http://dpaste.dzfl.pl/8b9f5471 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 12 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1977 Jonathan M Davis <jmdavisProg gmx.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jmdavisProg gmx.com PDT ---trivially incorrect use of op assignment operator is allowed:Your example is perfectly valid. D uses range value propagation: http://www.drdobbs.com/tools/value-range-propagation/229300211 It knows the value of both x and y, so it knows that x |= y; will work just fine, because all of the values will fit in the correct types. If the value in y was too large to fit in a ushort, _then_ it should give you an error, but since it fits in a ushort just fine (and is positive, so there's no issues with two's complement or whatnot), the compiler knows that it's fine and allows it without complaint. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 12 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1977 ---Your example is perfectly valid.I don't see. In the example above( http://dpaste.dzfl.pl/8b9f5471 ), the value in y is 16777216, which is greater than ushort.max.It knows the value of both x and y, so it knows that x |= y; will work just fine, because all of the values will fit in the correct types. If the value in y was too large to fit in a ushort, _then_ it should give you an error, but since it fits in a ushort just fine (and is positive, so there's no issues with two's complement or whatnot), the compiler knows that it's fine and allows it without complaint.-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 13 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1977 PDT ---I don't see. In the example above( http://dpaste.dzfl.pl/8b9f5471 ), the valuein y is 16777216, which is greater than ushort.max. I thought that I tested that it wasn't, but I guess that I screwed that up, since upon testing it again, it looks like it indeed is greater than ushort.max, But what's probably happening then is that x gets promoted to (u)int for |= per the integral promotion rules and then is fine being reassigned to x because the result is only 4, which fits in a ushort just fine. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 13 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1977 ---reassigned to x because the result is only 4, which fits in a ushort just fine.The result is 16777220 if both operands are int. I think this is an implicit narrowing conversion. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 13 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1977 PDT ---The result is 16777220 if both operands are int. I think this is an implicitnarrowing conversion. Ah. Then yes, it sounds like it's doing the wrong thing. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Oct 13 2012