Make -preview=intpromote not suck

Steven Schveighoffer schveiguy at gmail.com
Mon Oct 26 13:06:09 UTC 2020


For those who don't know, the current compiler does not integer promote 
for negation. This means that typeof(-x) is typeof(x). This also means 
that for things like short and byte:

short x = short.min; // -32768
int y = -x; // still -32768
ulong z = -x; // 18446744073709518848

In C (and in common sense), y and z are 32768.

So we have a new system, which integer-promotes a value from short or 
byte to int *before* the negation.

However, this perfectly valid code will no longer work:

short x2 = -x;

Instead, you must *cast* the -x to short (and to get rid of the 
deprecation, you must also cast the x to int before using - on it).

The annoying thing here is, this *buys you nothing*. Before the new 
integer promotion rules, if x was short.min, x2 is short.min. After the 
new integer promotion rules, with a cast, x2 is *still* short.min.

I think this one problem is going to cause us to never turn on the 
intpromote rule by default. It will be insanely disruptive.

I have an idea to make this better. The true cases where integer 
promotion is a problem is when you use the negation of a smaller type 
implicitly as a larger type. Other than that, the differing rules 
produce the same results.

I propose that the VRP state has a flag added indicating that the range 
came from a negation directly (a cast or any other operations will 
eliminate the flag). In the case where a value of a larger type VRP 
range is assigned to a value that holds all of the range EXCEPT the 
topmost value, and the negation flag is set, the assignment is allowed. 
Otherwise, if it is assigned to a larger type, and the type's minimum is 
in the VRP, then trigger the deprecation.

How this might look:

short x2 = -x;

Without -preview=intpromote:

-x has type short with VRP range short.min to short.max inclusive, and 
negation flag set.
Assigning to a short works, because the VRP allows it. No warnings/errors.

With -preview=intpromote:

-x has type int with VRP range short.min + 1 to short.max + 1 inclusive, 
and negation flag set.
Assigning to a short is allowed because of the new rule (if negation was 
involved, then it's allowed to assign if the upper range is only one 
higher than allowed).

int i = -x;

Without -preview=intpromote:

-x has type short with VRP range short.min to short.max inclusive, and 
negation flag set.
Assigning to an int works, but triggers the deprecation because of the 
negation flag, type being promoted implicitly, and the VRP includes 
short.min.

With -preview=intpromote:

-x has type int with VRP range short.min + 1 to short.max + 1 inclusive, 
and negation flag set.
Assigning to an int works, because int can hold all the values.

Does this make sense? I think it makes for a lot better targeted 
diagnostic and problem fix.

-Steve


More information about the Digitalmars-d mailing list