Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 17, 2018 New integer promotion rules | ||||
---|---|---|---|---|
| ||||
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; |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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 |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Wednesday, 17 January 2018 at 19:54:50 UTC, ag0aep6g wrote: > 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. Wrong, compiled with 2.077 or 2.078 with -transition=intpromote byte b = byte.min; ulong u = -b; writeln(u); outputs correctly 128 > > 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 |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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. |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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 ;) |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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 128 And 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; |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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);
|
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rubn | On Wednesday, 17 January 2018 at 21:12:07 UTC, Rubn wrote:
> 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);
"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)b
|
January 18, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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)b As 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. |
January 17, 2018 Re: New integer promotion rules | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | 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)b Same issue: the question is about what -b means before your cast in the 2.077 version of the code. Ali |
Copyright © 1999-2021 by the D Language Foundation