April 12, 2007
Don Clugston wrote:
> James Dennett wrote:
>> Don Clugston wrote:
>>> Derek Parnell wrote:
>>>> On Mon, 09 Apr 2007 15:01:56 -0400, Frank Malone wrote:
>>>>
>>>>> dmd v1.010
>>>>>
>>>>> import std.stdio;
>>>>> void main() {
>>>>>         uint a = 3;
>>>>>         ubyte b = 3;
>>>>>         int c = -1;
>>>>>         writefln(c < a ? "true" : "false"); // outputs false
>>>>>         writefln(c < b ? "true" : "false"); // outputs true
>>>>> }
>>>> Yes, kind of ... it is undefined behaviour ... the compiler doesn't
>>>> know
>>>> what to do so it does something dumb instead. I believe that a warning
>>>> (a.k.a "error" in Walter-speak) should be issued by the compiler.
>>> I agree.
>>> I think we should seriously consider the possibility that literals
>>> should be treated differently to variables, as regards signed-unsigned
>>> mismatches.
>>> * If the value fits in the range 0..int.max, it should be implicitly
>>> convertible to int, or to uint. --> 100% guaranteed safe.
>>> * If it is outside that range, an error should be issued, since it is
>>> definitely a bug.
>>>
>>> My feeling is, that this would eliminate most of the annoying & useless signed/unsigned mismatch warnings, and catch many of the real bugs.
>>
>> It's a shame if a language can't make the code above
>> do the right thing, and the right thing is simple:
>> -1 is less than 3, report that.  Don't try to make
>> comparisons convert their arguments to a common type.
>>
>> With an int a and a uint b, "a<b" should give the
>> same result as "(a<0) || ((uint)a < b)" -- where the
>> conversion happens only in cases where it fits.  In
>> general, if the value of one side of the comparison
>> is out of range for the other side, the answer is
>> known without testing the other value.  Concretely,
>> for example, -3 < (uint)x for all x, and similarly
>> 257 > (ubyte)y for all y.
> I don't think that's necessarily true. -3 < (uint)x is quite likely to
> be a bug.

Except in generic code, where the uint is likely to
depend on a type parameter.

> I would want an error message if I ever wrote that -- it doesn't make sense.

In a language with generics, it makes sense.  (Even in
a language with code generation facilities, it makes
sense; however code might arise that does not know up
front which types it might be used with, the rule I
suggest makes code work smoothly across all types.)

-- James
April 12, 2007
James Dennett wrote:
> Don Clugston wrote:
>> James Dennett wrote:
>>> Don Clugston wrote:
>>>> Derek Parnell wrote:
>>>>> On Mon, 09 Apr 2007 15:01:56 -0400, Frank Malone wrote:
>>>>>
>>>>>> dmd v1.010
>>>>>>
>>>>>> import std.stdio;
>>>>>> void main() {
>>>>>>         uint a = 3;
>>>>>>         ubyte b = 3;
>>>>>>         int c = -1;
>>>>>>         writefln(c < a ? "true" : "false"); // outputs false
>>>>>>         writefln(c < b ? "true" : "false"); // outputs true
>>>>>> }
>>>>> Yes, kind of ... it is undefined behaviour ... the compiler doesn't
>>>>> know
>>>>> what to do so it does something dumb instead. I believe that a warning
>>>>> (a.k.a "error" in Walter-speak) should be issued by the compiler.
>>>> I agree.
>>>> I think we should seriously consider the possibility that literals
>>>> should be treated differently to variables, as regards signed-unsigned
>>>> mismatches.
>>>> * If the value fits in the range 0..int.max, it should be implicitly
>>>> convertible to int, or to uint. --> 100% guaranteed safe.
>>>> * If it is outside that range, an error should be issued, since it is
>>>> definitely a bug.
>>>>
>>>> My feeling is, that this would eliminate most of the annoying & useless signed/unsigned mismatch warnings, and catch many of the real bugs.
>>> It's a shame if a language can't make the code above
>>> do the right thing, and the right thing is simple:
>>> -1 is less than 3, report that.  Don't try to make
>>> comparisons convert their arguments to a common type.
>>>
>>> With an int a and a uint b, "a<b" should give the
>>> same result as "(a<0) || ((uint)a < b)" -- where the
>>> conversion happens only in cases where it fits.  In
>>> general, if the value of one side of the comparison
>>> is out of range for the other side, the answer is
>>> known without testing the other value.  Concretely,
>>> for example, -3 < (uint)x for all x, and similarly
>>> 257 > (ubyte)y for all y.
>> I don't think that's necessarily true. -3 < (uint)x is quite likely to
>> be a bug.
> 
> Except in generic code, where the uint is likely to
> depend on a type parameter.

Or the more common case: the function has an int and
a uint as variables that it wishes to compare.  (Sorry,
I didn't imagine people would think this was intended
for literal values, when I was writing about how
comparisons between types should work.)

It's perfectly reasonable to compare unknown values of
two different integral types.  It's *unreasonable* for
such a conversion to compile and then not follow the
rules I give, because it will lead to bugs.  It's been
tried (C, C++) and the consequences are fairly well
known -- bugs, compiler warnings to try to avoid the
bugs, casts to try to avoid the compiler warnings but
without fixing the bugs, and so on.

-- James
April 13, 2007
James Dennett wrote:
> James Dennett wrote:
>> Don Clugston wrote:
>>> James Dennett wrote:
>>>> Don Clugston wrote:
>>>>> Derek Parnell wrote:
>>>>>> On Mon, 09 Apr 2007 15:01:56 -0400, Frank Malone wrote:
>>>>>>
>>>>>>> dmd v1.010
>>>>>>>
>>>>>>> import std.stdio;
>>>>>>> void main() {
>>>>>>>         uint a = 3;
>>>>>>>         ubyte b = 3;
>>>>>>>         int c = -1;
>>>>>>>         writefln(c < a ? "true" : "false"); // outputs false
>>>>>>>         writefln(c < b ? "true" : "false"); // outputs true
>>>>>>> }
>>>>>> Yes, kind of ... it is undefined behaviour ... the compiler doesn't
>>>>>> know
>>>>>> what to do so it does something dumb instead. I believe that a warning
>>>>>> (a.k.a "error" in Walter-speak) should be issued by the compiler.
>>>>> I agree.
>>>>> I think we should seriously consider the possibility that literals
>>>>> should be treated differently to variables, as regards signed-unsigned
>>>>> mismatches.
>>>>> * If the value fits in the range 0..int.max, it should be implicitly
>>>>> convertible to int, or to uint. --> 100% guaranteed safe.
>>>>> * If it is outside that range, an error should be issued, since it is
>>>>> definitely a bug.
>>>>>
>>>>> My feeling is, that this would eliminate most of the annoying & useless
>>>>> signed/unsigned mismatch warnings, and catch many of the real bugs.
>>>> It's a shame if a language can't make the code above
>>>> do the right thing, and the right thing is simple:
>>>> -1 is less than 3, report that.  Don't try to make
>>>> comparisons convert their arguments to a common type.
>>>>
>>>> With an int a and a uint b, "a<b" should give the
>>>> same result as "(a<0) || ((uint)a < b)" -- where the
>>>> conversion happens only in cases where it fits.  In
>>>> general, if the value of one side of the comparison
>>>> is out of range for the other side, the answer is
>>>> known without testing the other value.  Concretely,
>>>> for example, -3 < (uint)x for all x, and similarly
>>>> 257 > (ubyte)y for all y.
>>> I don't think that's necessarily true. -3 < (uint)x is quite likely to
>>> be a bug. 
>> Except in generic code, where the uint is likely to
>> depend on a type parameter.

I think there's it is still likely to be a logical error, even in that situation.

> Or the more common case: the function has an int and
> a uint as variables that it wishes to compare.  (Sorry,
> I didn't imagine people would think this was intended
> for literal values, when I was writing about how
> comparisons between types should work.)

Ah, OK. I might agree with you when both are variables. But I strongly believe that comparing an unsigned variable with a negative literal shouldn't be optimised away, it should be an error.

Although I think that comparing two variables which differ in both size AND signedness is very suspicious behaviour.

Eg
uint a;
byte b;
if (a<b) ...

Suppose a=250. Intention is catch all values in the range 250-255.
But the coder has forgotten that 'byte' is a signed type; b should have been a ubyte. (And in the case where a is a constant, this bug is actually *likely*).
April 18, 2007
James Dennett wrote:
> It's a shame if a language can't make the code above
> do the right thing, and the right thing is simple:
> -1 is less than 3, report that.  Don't try to make
> comparisons convert their arguments to a common type.

My thoughts, exactly.

-- 
serg.
1 2
Next ›   Last »