digitalmars.D.learn - New integer promotion rules
- rumbu (16/16) Jan 17 2018 This started in the last DMD version (2.078):
- ag0aep6g (6/17) Jan 17 2018 Actually, for b = byte.min, you get u = 18446744073709551488.
- rumbu (6/24) Jan 17 2018 Wrong, compiled with 2.077 or 2.078 with -transition=intpromote
- rumbu (13/13) Jan 17 2018 And here is why is bothering me:
- Basile B. (12/25) Jan 17 2018 Yes i know. In a way i agree but in another i've accepted the
- ag0aep6g (12/34) Jan 17 2018 So here you prefer the old behavior.
- Rubn (4/17) Jan 17 2018 Or write some wrapper code, which you prob should have done in
- rumbu (12/33) Jan 17 2018 "max" was just an over-templated example to highlight the
- ag0aep6g (16/22) Jan 17 2018 Those two snippets are not equivalent.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (8/14) Jan 17 2018 You're not assigning your byte to ulong; you're assigning the expression...
- Rubn (3/4) Jan 17 2018 That code is worth a wrapper, it's called "abs"...
- rumbu (6/10) Jan 17 2018 Well, since I'm in the learn forum and you seem to have a
- Dominikus Dittes Scherkl (5/17) Jan 18 2018 target = isNegative ? cast(Unsigned!T)(-c) : cast(Unsigned!T)c;
- Steven Schveighoffer (16/37) Jan 18 2018 I was going to respond with a helpful guide on what to do here, but I
- ag0aep6g (2/4) Jan 18 2018 You don't need casts when you use `-transition=intpromote`.
- Steven Schveighoffer (8/13) Jan 18 2018 Sure, but what does the statement "Once deprecated this will become an
This started in the last DMD version (2.078): byte b = -10; ulong u = b < 0 ? -b : b; //Deprecation: integral promotion not done for `-b`, use '-transition=intpromote' switch or `-cast(int)(b) Why do I need a to promote a byte to int to obtain an ulong? Even in the extreme case where b is byte.min, -byte.min as unsigned is exactly what i need: 128; This leads to more cases: ubyte u = cast(ubyte)-b; //Deprecation: integral promotion not done for `-b`, use '-transition=intpromote' switch or `-cast(int)(b)` Last time I checked, casting is somehow synonym with "I know what I'm doing", why do I need another cast to prove my sanity: ubyte u = cast(ubyte)-cast(int)b;
Jan 17 2018
On 01/17/2018 08:40 PM, rumbu wrote:This started in the last DMD version (2.078): byte b = -10; ulong u = b < 0 ? -b : b; //Deprecation: integral promotion not done for `-b`, use '-transition=intpromote' switch or `-cast(int)(b) Why do I need a to promote a byte to int to obtain an ulong? Even in the extreme case where b is byte.min, -byte.min as unsigned is exactly what i need: 128;Actually, for b = byte.min, you get u = 18446744073709551488. 2.078 is starting to fix this so that you get 128. But that's a breaking change, so you have to use the compiler switch or the cast for a couple releases. In the changelog: https://dlang.org/changelog/2.078.0.html#fix16997
Jan 17 2018
On Wednesday, 17 January 2018 at 19:54:50 UTC, ag0aep6g wrote:On 01/17/2018 08:40 PM, rumbu wrote:Wrong, compiled with 2.077 or 2.078 with -transition=intpromote byte b = byte.min; ulong u = -b; writeln(u); outputs correctly 128This started in the last DMD version (2.078): byte b = -10; ulong u = b < 0 ? -b : b; //Deprecation: integral promotion not done for `-b`, use '-transition=intpromote' switch or `-cast(int)(b) Why do I need a to promote a byte to int to obtain an ulong? Even in the extreme case where b is byte.min, -byte.min as unsigned is exactly what i need: 128;Actually, for b = byte.min, you get u = 18446744073709551488.2.078 is starting to fix this so that you get 128. But that's a breaking change, so you have to use the compiler switch or the cast for a couple releases. In the changelog: https://dlang.org/changelog/2.078.0.html#fix16997
Jan 17 2018
And here is why is bothering me: auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max); The generic code above (which worked for all signed integral types T in 2.077) must be rewritten like this in 2.078: static if (T.sizeof >= 4) auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max; else auto max = isNegative ? cast(Unsigned!T)(-cast(int)T.min) : cast(Unsigned!T)T.max; Now I have to translate an 1-liner in a 4-liner all around my project.
Jan 17 2018
On Wednesday, 17 January 2018 at 20:30:07 UTC, rumbu wrote:And here is why is bothering me: auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max); The generic code above (which worked for all signed integral types T in 2.077) must be rewritten like this in 2.078: static if (T.sizeof >= 4) auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max; else auto max = isNegative ? cast(Unsigned!T)(-cast(int)T.min) : cast(Unsigned!T)T.max; Now I have to translate an 1-liner in a 4-liner all around my project.Yes i know. In a way i agree but in another i've accepted the thing, that's why for example there's: https://github.com/dlang/phobos/pull/5958/files I had to do similar things in my own stuff. Other people had to as well. In my stuff i've used `cast(ubyte) (stuff * -1)` instead of `-stuff` because i've verified that in both cases an asm NEG is generated. But well, i understand your concern ;)
Jan 17 2018
On 01/17/2018 09:30 PM, rumbu wrote:And here is why is bothering me: auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max); The generic code above (which worked for all signed integral types T in 2.077) must be rewritten like this in 2.078: static if (T.sizeof >= 4) auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max; else auto max = isNegative ? cast(Unsigned!T)(-cast(int)T.min) : cast(Unsigned!T)T.max; Now I have to translate an 1-liner in a 4-liner all around my project.So here you prefer the old behavior. But in your previous post you wrote:compiled with 2.077 or 2.078 with -transition=intpromote byte b = byte.min; ulong u = -b; writeln(u); outputs correctly 128And that's the new behavior. You can't have both. You either get to keep the shorter version of your max code, or you get "correct" results on `ulong u = -b;`. Except you can actually (almost) keep your max code, as far as I see. Under the old rules `-T.min` is just `T.min` again. So you can just drop the negation there and get the same result. And then it works under the new rules too, because there's no negation involved. I.e.: auto max = isNegative ? cast(Unsigned!T)(T.min) : cast(Unsigned!T)T.max;
Jan 17 2018
On Wednesday, 17 January 2018 at 20:30:07 UTC, rumbu wrote:And here is why is bothering me: auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max); The generic code above (which worked for all signed integral types T in 2.077) must be rewritten like this in 2.078: static if (T.sizeof >= 4) auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max; else auto max = isNegative ? cast(Unsigned!T)(-cast(int)T.min) : cast(Unsigned!T)T.max; Now I have to translate an 1-liner in a 4-liner all around my project.Or write some wrapper code, which you prob should have done in the first place if you use that all around your project: auto max = myMaxFunc!(isNegative, T);
Jan 17 2018
On Wednesday, 17 January 2018 at 21:12:07 UTC, Rubn wrote:On Wednesday, 17 January 2018 at 20:30:07 UTC, rumbu wrote:"max" was just an over-templated example to highlight the problem, code like "m = n < 0 ? -n : n" doesn't worth a wrapper, for example. But the original questions remain: 1. Why do I need explicitely to promote my byte to int in order to assign it to an ulong? 2.077: ulong u = -b; 2.088: ulong u = -cast(int)b; 2. Why do I need a cast(int) to assign a byte to an ubyte, since I'm explicitely cast it? 2.077: ubyte c = cast(ubyte)-b; 2.088: ubyte c = cast(ubyte)-cast(int)bAnd here is why is bothering me: auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max); The generic code above (which worked for all signed integral types T in 2.077) must be rewritten like this in 2.078: static if (T.sizeof >= 4) auto max = isNegative ? cast(Unsigned!T)(-T.min) : cast(Unsigned!T)T.max; else auto max = isNegative ? cast(Unsigned!T)(-cast(int)T.min) : cast(Unsigned!T)T.max; Now I have to translate an 1-liner in a 4-liner all around my project.Or write some wrapper code, which you prob should have done in the first place if you use that all around your project: auto max = myMaxFunc!(isNegative, T);
Jan 17 2018
On 01/17/2018 11:30 PM, rumbu wrote:1. Why do I need explicitely to promote my byte to int in order to assign it to an ulong? 2.077: ulong u = -b; 2.088: ulong u = -cast(int)b;Those two snippets are not equivalent. When b = byte.min, the 2.077 snippet gives u = 18446744073709551488, while the 2.078 snippet gives u = 128 even when compiled with 2.077. Old code may rely on u = 18446744073709551488, and that's why dmd 2.078 doesn't just silently give you 128. Instead you have to use the cast or the compiler switch to tell dmd that you actually want the new behavior. In the future, the new behavior is going to become the default. You have to be explicit about this so that dmd doesn't break your code without you noticing.2. Why do I need a cast(int) to assign a byte to an ubyte, since I'm explicitely cast it? 2.077: ubyte c = cast(ubyte)-b; 2.088: ubyte c = cast(ubyte)-cast(int)bAs above, when b = byte(-128), then `-b` is going to change from byte(-128) to int(128). In this case, that doesn't affect the result, because `cast(ubyte) byte(-128)` and `cast(ubyte) int(128)` are both 128. But the compiler obviously doesn't look that far. And it's not possible for the compiler to analyse the whole program before giving you the deprecation message.
Jan 17 2018
On 01/17/2018 02:30 PM, rumbu wrote:1. Why do I need explicitely to promote my byte to int in order to assign it to an ulong? 2.077: ulong u = -b; 2.088: ulong u = -cast(int)b;You're not assigning your byte to ulong; you're assigning the expression -b to ulong. -b is discovered to have unintended behavior, which is now fixed. We have to go throught a transition period not to break old code that may have depended on the old unintended behavior.2. Why do I need a cast(int) to assign a byte to an ubyte, since I'm explicitely cast it? 2.077: ubyte c = cast(ubyte)-b; 2.088: ubyte c = cast(ubyte)-cast(int)bSame issue: the question is about what -b means before your cast in the 2.077 version of the code. Ali
Jan 17 2018
On Wednesday, 17 January 2018 at 22:30:11 UTC, rumbu wrote:code like "m = n < 0 ? -n : n" doesn't worth a wrapperThat code is worth a wrapper, it's called "abs"... m = abs(n);
Jan 17 2018
On Thursday, 18 January 2018 at 02:30:17 UTC, Rubn wrote:On Wednesday, 17 January 2018 at 22:30:11 UTC, rumbu wrote:Well, since I'm in the learn forum and you seem to have a response to anything, can you help me translate this line under the new integer promotion rules? https://github.com/rumbu13/decimal/blob/master/src/decimal/decimal.d#L7804 Thanks.code like "m = n < 0 ? -n : n" doesn't worth a wrapperThat code is worth a wrapper, it's called "abs"... m = abs(n);
Jan 17 2018
On Thursday, 18 January 2018 at 06:05:08 UTC, rumbu wrote:On Thursday, 18 January 2018 at 02:30:17 UTC, Rubn wrote:target = isNegative ? cast(Unsigned!T)(-c) : cast(Unsigned!T)c; That would have been better even before the change, because the operator '-' used on unsigned types is likely to produce unexpected results, if the behaviour is defined at all.On Wednesday, 17 January 2018 at 22:30:11 UTC, rumbu wrote:Well, since I'm in the learn forum and you seem to have a response to anything, can you help me translate this line under the new integer promotion rules? https://github.com/rumbu13/decimal/blob/master/src/decimal/decimal.d#L7804 Thanks.code like "m = n < 0 ? -n : n" doesn't worth a wrapperThat code is worth a wrapper, it's called "abs"... m = abs(n);
Jan 18 2018
On Thursday, 18 January 2018 at 12:51:48 UTC, Dominikus Dittes Scherkl wrote:On Thursday, 18 January 2018 at 06:05:08 UTC, rumbu wrote:I don't think so: ulong c = 128; bool isNegative = true; byte target = isNegative ? -cast(ubyte)c : cast(ubyte)c; Error Deprecation: integral promotion not done for `-cast(ubyte)c`, use '-transition=intpromote' switch or `-cast(int)(cast(ubyte)c)`On Thursday, 18 January 2018 at 02:30:17 UTC, Rubn wrote:target = isNegative ? cast(Unsigned!T)(-c) : cast(Unsigned!T)c; That would have been better even before the change, because the operator '-' used on unsigned types is likely to produce unexpected results, if the behaviour is defined at all.On Wednesday, 17 January 2018 at 22:30:11 UTC, rumbu wrote:Well, since I'm in the learn forum and you seem to have a response to anything, can you help me translate this line under the new integer promotion rules? https://github.com/rumbu13/decimal/blob/master/src/decimal/decimal.d#L7804 Thanks.code like "m = n < 0 ? -n : n" doesn't worth a wrapperThat code is worth a wrapper, it's called "abs"... m = abs(n);
Jan 18 2018
On Thursday, 18 January 2018 at 17:54:59 UTC, rumbu wrote:On Thursday, 18 January 2018 at 12:51:48 UTC, Dominikus DittesMy bad, it works. Thanks: ulong c = 128; bool isNegative = true; byte target = isNegative ? cast(ubyte)-c : cast(ubyte)c;target = isNegative ? cast(Unsigned!T)(-c) : cast(Unsigned!T)c; That would have been better even before the change, because the operator '-' used on unsigned types is likely to produce unexpected results, if the behaviour is defined at all.I don't think so: ulong c = 128; bool isNegative = true; byte target = isNegative ? -cast(ubyte)c : cast(ubyte)c; Error Deprecation: integral promotion not done for `-cast(ubyte)c`, use '-transition=intpromote' switch or `-cast(int)(cast(ubyte)c)`
Jan 18 2018
On Thursday, 18 January 2018 at 18:00:51 UTC, rumbu wrote:On Thursday, 18 January 2018 at 17:54:59 UTC, rumbu wrote:But this doesn't: ushort c = 128; bool isNegative = true; byte target = isNegative ? cast(ubyte)-c : cast(ubyte)c; Error Deprecation: integral promotion not done for `-c`, use '-transition=intpromote' switch or `-cast(int)(c) This is starting to become truly crazy.On Thursday, 18 January 2018 at 12:51:48 UTC, Dominikus DittesMy bad, it works. Thanks: ulong c = 128; bool isNegative = true; byte target = isNegative ? cast(ubyte)-c : cast(ubyte)c;target = isNegative ? cast(Unsigned!T)(-c) : cast(Unsigned!T)c; That would have been better even before the change, because the operator '-' used on unsigned types is likely to produce unexpected results, if the behaviour is defined at all.I don't think so: ulong c = 128; bool isNegative = true; byte target = isNegative ? -cast(ubyte)c : cast(ubyte)c; Error Deprecation: integral promotion not done for `-cast(ubyte)c`, use '-transition=intpromote' switch or `-cast(int)(cast(ubyte)c)`
Jan 18 2018
On 1/17/18 2:40 PM, rumbu wrote:This started in the last DMD version (2.078): byte b = -10; ulong u = b < 0 ? -b : b; //Deprecation: integral promotion not done for `-b`, use '-transition=intpromote' switch or `-cast(int)(b) Why do I need a to promote a byte to int to obtain an ulong? Even in the extreme case where b is byte.min, -byte.min as unsigned is exactly what i need: 128; This leads to more cases: ubyte u = cast(ubyte)-b; //Deprecation: integral promotion not done for `-b`, use '-transition=intpromote' switch or `-cast(int)(b)` Last time I checked, casting is somehow synonym with "I know what I'm doing", why do I need another cast to prove my sanity: ubyte u = cast(ubyte)-cast(int)b;I was going to respond with a helpful guide on what to do here, but I either misunderstand the docs, or I don't agree with the transition requirements. I thought that you could simply ignore this deprecation message if it doesn't affect you (i.e. you don't have the possibility of seeing the corner cases that are fixed), but looking at the changelog it says: "Once deprecated this will become an error, and then the C-like behavior will become the default." So this says, even if you aren't affected, you *still* have to add casts to avoid a future error? I thought it was going to be deprecated, and then after some number of versions it would just be switched to the new behavior. Is there going to be a point where casts aren't needed? Otherwise, this is pretty ugly. -Steve
Jan 18 2018
On 01/18/2018 03:30 PM, Steven Schveighoffer wrote:Is there going to be a point where casts aren't needed? Otherwise, this is pretty ugly.You don't need casts when you use `-transition=intpromote`.
Jan 18 2018
On 1/18/18 11:14 AM, ag0aep6g wrote:On 01/18/2018 03:30 PM, Steven Schveighoffer wrote:Sure, but what does the statement "Once deprecated this will become an error" mean? Will I have to use the -transition=intpromote switch forever to avoid an error? Thinking about the fact that the deprecation doesn't show an error for the -transition switch, makes me think possibly the changelog message is incorrect. -SteveIs there going to be a point where casts aren't needed? Otherwise, this is pretty ugly.You don't need casts when you use `-transition=intpromote`.
Jan 18 2018
On 01/18/2018 05:22 PM, Steven Schveighoffer wrote:Sure, but what does the statement "Once deprecated this will become an error" mean? Will I have to use the -transition=intpromote switch forever to avoid an error?As you quoted before: "Once deprecated this will become an error, and then the C-like behavior will become the default." I'm interpreting that to mean that it will become an error for some time, but later it will be allowed again with the new behavior. And then you can throw away `-transition=intpromote`.
Jan 18 2018
On Thursday, 18 January 2018 at 16:31:02 UTC, ag0aep6g wrote:I'm interpreting that to mean that it will become an error for some time, but later it will be allowed again with the new behavior. And then you can throw away `-transition=intpromote`.Seeing as it's almost 3 years later, I'd like to ask, is there an indication of when this will happen? It seems to still be around.
Jan 01 2021