Jump to page: 1 2 3
Thread overview
New integer promotion rules
Jan 17, 2018
rumbu
Jan 17, 2018
ag0aep6g
Jan 17, 2018
rumbu
Jan 17, 2018
rumbu
Jan 17, 2018
Basile B.
Jan 17, 2018
ag0aep6g
Jan 17, 2018
Rubn
Jan 17, 2018
rumbu
Jan 17, 2018
ag0aep6g
Jan 17, 2018
Ali Çehreli
Jan 18, 2018
Rubn
Jan 18, 2018
rumbu
Jan 18, 2018
rumbu
Jan 18, 2018
rumbu
Jan 18, 2018
rumbu
Jan 18, 2018
ag0aep6g
Jan 18, 2018
ag0aep6g
Jan 01
Paul
January 17, 2018
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
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
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
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
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
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
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
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
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
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

« First   ‹ Prev
1 2 3