View mode: basic / threaded / horizontal-split · Log in · Help
June 11, 2009
why implicitly allowing compare ubyte and byte sucks
ubyte func()
{
	return 255;
}

const byte VAR = cast(byte)0xff;
void main()
{

	assert(func == VAR);
	assert(255 == VAR);
}

even if you take a look at the ASM( if not carefully enough ), you might  
still be fooled in some chances.

testcmp.d:10    assert(func == VAR);
0040201b: e8f0ffffff              call 0x402010 testcmp.func testcmp.d:1
00402020: 0fb6c0                  movzx eax, al
00402023: 83f8ff                  cmp eax, 0xff
00402026: 740a                    jz 0x402032   _Dmain testcmp.d:11
00402028: b80a000000              mov eax, 0xa
0040202d: e80e000000              call 0x402040 testcmp.__assert
testcmp.d:11    assert(255 == VAR);
00402032: b80b000000              mov eax, 0xb
00402037: e804000000              call 0x402040 testcmp.__assert
testcmp.d:12 }
0040203c: 5d                      pop ebp
0040203d: c3                      ret

It seems that comparing two different operands with different size makes  
no sense. The compiler should issue an error against that.

Comparing ubyte to byte may lead one to think they are compared in the  
sense of the same size.

This behavior doesn't consist with int and uint:

	int j=-1;
	assert(j==uint.max); // this test passes

	byte k=-1;
	assert(k==ubyte.max); // this test fails

This inconsistent behavior is pretty nasty.

-- 
使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
June 11, 2009
Re: why implicitly allowing compare ubyte and byte sucks
davidl wrote:
> It seems that comparing two different operands with different size makes 
> no sense. The compiler should issue an error against that.

Consider:

   byte b;
   if (b == 1)

here you're comparing two different sizes, a byte and an int. 
Disallowing such (in its various incarnations) is a heavy burden, as the 
user will have to insert lots of ugly casts.

There really isn't any escaping from the underlying representation of 
2's complement arithmetic with its overflows, wrap-arounds, sign 
extensions, etc.
June 11, 2009
Re: why implicitly allowing compare ubyte and byte sucks
2009/6/11 Walter Bright <newshound1@digitalmars.com>:
> davidl wrote:
>>
>> It seems that comparing two different operands with different size makes
>> no sense. The compiler should issue an error against that.
>
> Consider:
>
>   byte b;
>   if (b == 1)
>
> here you're comparing two different sizes, a byte and an int. Disallowing
> such (in its various incarnations) is a heavy burden, as the user will have
> to insert lots of ugly casts.

Weren't polysemous types supposed to avoid all that?
June 11, 2009
Re: why implicitly allowing compare ubyte and byte sucks
Jarrett Billingsley wrote:
> Weren't polysemous types supposed to avoid all that?

It kept getting too complicated.
June 12, 2009
Re: why implicitly allowing compare ubyte and byte sucks
Walter Bright wrote:
> davidl wrote:
>> It seems that comparing two different operands with different size 
>> makes no sense. The compiler should issue an error against that.
> 
> Consider:
> 
>    byte b;
>    if (b == 1)
> 
> here you're comparing two different sizes, a byte and an int. 
> Disallowing such (in its various incarnations) is a heavy burden, as the 
> user will have to insert lots of ugly casts.
> 
> There really isn't any escaping from the underlying representation of 
> 2's complement arithmetic with its overflows, wrap-arounds, sign 
> extensions, etc.

Why is "1" an int? Can't it be treated similar to the way string 
literals are treated: "a string literal" can be string, wstring and dstring:

dstring test = "Asdf";
int main()
{
 return test == "asdf";
}

L.
June 12, 2009
Re: why implicitly allowing compare ubyte and byte sucks
Walter Bright wrote:
> davidl wrote:
>> It seems that comparing two different operands with different size 
>> makes no sense. The compiler should issue an error against that.
> 
> Consider:
> 
>    byte b;
>    if (b == 1)
> 
> here you're comparing two different sizes, a byte and an int. 
> Disallowing such (in its various incarnations) is a heavy burden, as the 
> user will have to insert lots of ugly casts.
> 
> There really isn't any escaping from the underlying representation of 
> 2's complement arithmetic with its overflows, wrap-arounds, sign 
> extensions, etc.

The problem is a lot more specific than that.
The unexpected behaviour comes from the method used to promote two types 
to a common type, when both are smaller than int, but of different 
signedness. Intuitively, you expect the common type of {byte, ubyte} to 
be ubyte, by analogy to {int, uint}->uint, and {long, ulong}->ulong. But 
instead, the common type is int!

The involvement of 'int' in the promotion process is kind of bizarre, 
really. It's a consequence of the fact that in C, short and char are 
second-class citizens, only really intended for saving space. The 
semantics of operations on two different space-saving types are a bit 
problematic.

I think it's true that

byte  == ubyte, byte  == ushort,
short == ubyte, short == ushort

are almost always errors. Could we just make those four illegal?
BTW, it just occured to me that these four (and only these four) are the 
cases where a "signed/unsigned mismatch" warning is actually helpful. A 
signed-unsigned warning involving 'int' is almost always spurious.

For bonus points:
June 12, 2009
Re: why implicitly allowing compare ubyte and byte sucks
Don wrote:
> For bonus points:
[end of message]

I guess nobody'll be getting those bonus points then... :P
June 12, 2009
Re: why implicitly allowing compare ubyte and byte sucks
Don wrote:
> Walter Bright wrote:
>> davidl wrote:
>>> It seems that comparing two different operands with different size 
>>> makes no sense. The compiler should issue an error against that.
>>
>> Consider:
>>
>>    byte b;
>>    if (b == 1)
>>
>> here you're comparing two different sizes, a byte and an int. 
>> Disallowing such (in its various incarnations) is a heavy burden, as 
>> the user will have to insert lots of ugly casts.
>>
>> There really isn't any escaping from the underlying representation of 
>> 2's complement arithmetic with its overflows, wrap-arounds, sign 
>> extensions, etc.
> 
> The problem is a lot more specific than that.
> The unexpected behaviour comes from the method used to promote two types 
> to a common type, when both are smaller than int, but of different 
> signedness. Intuitively, you expect the common type of {byte, ubyte} to 
> be ubyte, by analogy to {int, uint}->uint, and {long, ulong}->ulong. But 
> instead, the common type is int!
> 
> The involvement of 'int' in the promotion process is kind of bizarre, 
> really. It's a consequence of the fact that in C, short and char are 
> second-class citizens, only really intended for saving space. The 
> semantics of operations on two different space-saving types are a bit 
> problematic.
> 
> I think it's true that
> 
> byte  == ubyte, byte  == ushort,
> short == ubyte, short == ushort
> 
> are almost always errors. Could we just make those four illegal?
> BTW, it just occured to me that these four (and only these four) are the 
> cases where a "signed/unsigned mismatch" warning is actually helpful. A 
> signed-unsigned warning involving 'int' is almost always spurious.
> 
> For bonus points:

Yeah, where are zose :o).

Hey, please bugzillize everything. Walter is almost done with revamping 
integers support into a framework that is superior to both Java/C# and 
C/C++. I just found three bugs in phobos by using his alpha compiler.


Andrei
June 12, 2009
Re: why implicitly allowing compare ubyte and byte sucks
Andrei Alexandrescu:
> Hey, please bugzillize everything. Walter is almost done with revamping 
> integers support into a framework that is superior to both Java/C# and 
> C/C++. I just found three bugs in phobos by using his alpha compiler.

Walter is kind of magic, I see :-)) He brings toys.

Once the designer of Haskell has said to himself: "Avoid success at any cost". There's worst fate than not having success: maybe being a boring language? :-)

Bye,
bearophile
June 12, 2009
Re: why implicitly allowing compare ubyte and byte sucks
On Fri, 12 Jun 2009 02:08:14 +0200, Don wrote:

> Walter Bright wrote:
>> davidl wrote:
>>> It seems that comparing two different operands with different size 
>>> makes no sense. The compiler should issue an error against that.
>> 
>> Consider:
>> 
>>    byte b;
>>    if (b == 1)
>> 
>> here you're comparing two different sizes, a byte and an int. 
>> Disallowing such (in its various incarnations) is a heavy burden, as the 
>> user will have to insert lots of ugly casts.
>> 
>> There really isn't any escaping from the underlying representation of 
>> 2's complement arithmetic with its overflows, wrap-arounds, sign 
>> extensions, etc.
> 
> The problem is a lot more specific than that.
> The unexpected behaviour comes from the method used to promote two types 
> to a common type, when both are smaller than int, but of different 
> signedness. Intuitively, you expect the common type of {byte, ubyte} to 
> be ubyte, by analogy to {int, uint}->uint, and {long, ulong}->ulong. But 
> instead, the common type is int!

I think that the common type for byte and ubyte is short. Byte and ubyte
have overlapping ranges of values (-127 to 127) and (0 to 255) so a common
type would have to be able to hold both these ranges at least, and short
(16-bit signed integer) does that.

-- 
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home