Common type of ubyte and const ubyte is int
Don Allen
donaldcallen at gmail.com
Sun May 5 13:46:41 UTC 2024
On Sunday, 5 May 2024 at 04:13:16 UTC, Jonathan M Davis wrote:
> On Friday, May 3, 2024 1:40:36 PM MDT Walter Bright via
> Digitalmars-d wrote:
>> On 5/1/2024 7:42 AM, Steven Schveighoffer wrote:
>> > It seems rule 2 would apply instead of rule 6? but I don't
>> > like it.
>>
>> ```
>> #include <stdio.h>
>>
>> void main()
>> {
>> char u;
>> const char v;
>> printf("%ld %ld\n", sizeof(u), sizeof(1?u:v));
>> }
>> ```
>>
>> This prints "1 4". D follows the same integral promotion
>> rules, and the reason is if one translates C code to D, one
>> doesn't get an unpleasant hidden surprise.
>
> Sure, but are there actually any unpleasant surprises if C code
> using the ternary operator is converted to D? If you have
>
> uint8_t left;
> const uint8_t right;
>
> uint8_t result = cond ? left : right;
>
> whether integer promotion occurs or not is irrelevant, because
> no arithmetic is happening, and C will happily downcast an int
> to a uint8_t. So, whether the ternary operator results in
> uint8_t or int doesn't affect the result at all.
>
> On the flip side, if you assign the result to an int,
>
> uint8_t left;
> const uint8_t right;
>
> int result = cond ? left : right;
>
> whether integer promotion occurred is again irrelevant, because
> no arithmetic is occurring, and both results will fit in an int
> whether the ternary operator converted the result to int or
> left it as uint8_t.
>
> And since char in C is the same as either uint8_t or int8_t
> depending on the platform, using char in those two examples
> would have the same result.
>
> So, as far as I can tell, the C code does not care whether
> integer promotion occurs with the ternary operator or not. It
> would care if it had type inference via something like D's
> auto, but it doesn't. The value of the result is the same
> whether integer promotion occurs or not, and that's all that C
> actually cares about unless you're doing something like sizeof
> on the expression, which is not exactly a typical thing to be
> doing. And that's probably why C++ was perfectly fine with
> changing the behavior. It doesn't actually break code in
> practice.
>
> This issue only comes up in D, because we have auto, and we
> make downcasting with integer types illegal. So, promoting byte
> to int when no arithmetic is actually occurring just because
> the other branch of the ternary used const is highly surprising
> and increases the chances of code breakage due to downcasting
> not being legal.
>
> It's also pretty terrible for generic code, because with almost
> all types if you have
>
> T left;
> const T right;
>
> auto result = cond ? left : right;
>
> the result will be const T, whereas with smaller integer types,
> it would be int, which almost no one will expect. And unless
> VRP kicks in
>
> T left;
> const T right;
>
> const T result = cond ? left : right;
>
> will fail to compile for small integer types while it compiles
> for every other type in the language.
>
> So, from what I can tell, we're not going to break C code
> whether the ternary operator does integer promotion or not, but
> it _does_ cause problems for D code that integer promotion
> occurs even though there is no arithmetic expression involved.
>
> And on top of that, by changing D to not do integer promotion
> with the ternary operator, we would be more compatible with C++
> where the difference _does_ matter, because they have their own
> auto, and they have function overloading.
>
> So, I don't see how sticking to the C behavior in this case
> helps at all, and it clearly hurts us for both straight up D
> code and for porting C++ code to D.
>
> - Jonathan M Davis
I think Jonathan, Steve and others have made a strong case for
fixing this language anomaly.The terms "unpleasant surprise" and
"no one would expect" are not what you want to read in
descriptions of your language. We all expect to have a mental
model of what the code we are writing does. Discovering the hard
way that, despite reasonable diligence, our model was wrong tends
to drive people away. This is the Principle of Least Surprise.
Have any of you written any PL-1? No? Here's an example of why
(this may not be syntactically correct; I haven't written any
PL-1 in over 50 years):
````
declare foo bit(1)
foo = 1
````
What is the value of foo after this executes? The answer is 0.
Why? 1 is a decimal constant with precision (p) of 1. To do the
assignment, it is first converted to a binary constant of length
p+3: 0001. This is converted to the bit string '0001' of length
4, which is then assigned to foo, a bit string of length 1.
Assignment of longer to shorter bit strings is done high order
bit first.
A lot of other issues contributed to PL-1's ultimate lack of
success, but things like this certainly did not help.
More information about the Digitalmars-d
mailing list