On Thursday, February 20, 2025 6:02:26 PM MST Quirin Schroll via Digitalmars-d-learn wrote: > It seems a cast does more than change the static type and VRP. > ```d > void foo(uint) { } > > int x = -1; > foo(x); // compiles (debatable) > foo(long(x)); // compiles(!) > foo(cast(long)x); // compiles(!) > foo((() => cast(long)x)()); // Error: foo is not callable using > argument types […] > ``` > > Why do the latter two work? Their static type is `long` which > normally rules out conversion to `uint`. However, if VRP can > prove the value is definitely in the range of `uint`, the > implicit conversion to `uint` is possible. However, VRP shouldn’t > say that that’s the case, since `int` supports negative numbers > and `uint` doesn’t.
I don't think that VRP cares about negative vs positive due to the fact that the compiler implicitly converts between negative and positive integer types of the same size. For instance, uint i = -1; compiles just fine. 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. - Jonathan M Davis