Negating a short?

Dennis dkorpel at gmail.com
Wed Nov 6 00:00:48 UTC 2024


On Tuesday, 5 November 2024 at 20:29:08 UTC, Andy Valencia wrote:
> I still see:
>
> tst15.d(6): Error: cannot implicitly convert expression 
> `-cast(int)s` of type `int` to `short`

That's right, it only removes the deprecation that requires a 
double cast to fix, but you still need an explicit cast to 
truncate the result of `-s` (which got promoted to `int`) back to 
a `short`, unless the compiler can prove at compile time it will 
always fit in 16 bits. This analysis is called Value Range 
Propagation (VRP) in the specification: 
https://dlang.org/spec/type.html#vrp

For example, this compiles:

```D
void f(short s)
{
     short t = -s / 2; // will always fit
     short u = -s % 1024;  // will always fit
}
```

In your example, you get an error because:
- VRP doesn't do data flow analysis: it only looks at the current 
expression without looking at variable assignments that came 
before it. It doesn't see the value of `s` will always be -5 in 
that case (though in your actual code there's not a hardcoded 
constant like -5 so it wouldn't even matter).
- Then, considering `s` could be anything from -32768 to 32767, 
there's a chance of integer overflow because -(-32768) = 32768 
which overflows to -32768 when cast to a short.

To signal that this possible overflow is okay, an explicit cast 
is needed:

```D
s = cast(short) -s;
```

You can also use an assignment operator, which allows overflow 
without explicit cast:

```D
s *= -1;
```

Which integer conversions are implicit and which ones must be 
explicit is somewhat controversial. In this case, the compiler 
can be annoyingly strict, but there's also cases where the 
compiler is surprisingly lenient: like implicitly converting 
`bool` / `char` to `int`, or implicitly converting `int` to 
`uint` (where negative ints implicitly overflow, a common source 
of bugs!). There have been proposals to change the behavior, but 
there's often disagreement on the pros and cons of 
implicit/explicit. On top of that, existing D code shouldn't be 
broken, and remain consistent with C. (D is designed so that 
expressions that are the same as C behave the same as C) So it's 
hard to design a solution for this.



More information about the Digitalmars-d-learn mailing list