What does a cast really do?
Steven Schveighoffer
schveiguy at gmail.com
Fri Feb 21 15:48:12 UTC 2025
On Friday, 21 February 2025 at 13:07:38 UTC, Paul Backus wrote:
> On Friday, 21 February 2025 at 07:44:54 UTC, Jonathan M Davis
> wrote:
>> I think that what it basically comes down to is that because
>> -1 fits in int, and int implicitly converts to uint, VRP is
>> fine with converting the long with a value of -1 to uint. So,
>> as long as the value fits in 32 bits, the conversion will work
>> even if gets screwed up by the conversion between signed and
>> unsigned.
>
> This has nothing to do with the value -1. You get the same
> result even if the value of x is completely unknown:
>
> void foo(uint) {}
>
> void example(int x)
> {
> foo(x); // compiles
> foo(long(x)); // compiles
> foo(cast(long) x); // compiles
> foo((() => cast(long) x)()); // Error: foo is not
> callable [...]
> }
>
> My best guess is that when VRP looks at `long(x)` or
> `cast(long) x`, it can see that x is an int, so it allows the
> value to be converted *back* to int (and then from int to
> uint). But that information is lost when you hide the cast
> expression inside a function call.
Yes, VRP is a "value range". In this case, it knows that the long
represented by the expression can only have the range int.min ..
int.max inclusive.
The issue seems to be that the type is irrelevant when
considering the conversion to unsigned. `uint` apparently can
accept any value from -int.min to uint.max, regardless of type,
which is an odd allowance.
But.... testing this, it doesn't make sense:
```d
uint x = long(-1); // OK
uint y = -1L; // Error: cannot implicitly convert expression
`-1L` of type `long` to `uint`
```
Surely something here is worthy of a bug report?
-Steve
More information about the Digitalmars-d-learn
mailing list