On Tuesday, 4 November 2014 at 00:51:10 UTC, H. S. Teoh via
Digitalmars-d wrote:
On Mon, Nov 03, 2014 at 04:29:17PM -0800, Walter Bright via
Digitalmars-d wrote:
On 11/3/2014 10:03 AM, Nick Treleaven wrote:
>On 02/11/2014 20:33, Walter Bright wrote:
>>It's simply not workable to put a wall between them. Every
>>proposal
>>for it has entailed various unfortunate, ugly, and arbitrary
>>consequences.
>
>We need warnings like gcc has:
>
>"-Wsign-compare
> Warn when a comparison between signed and unsigned
> values could
> produce an incorrect result when the signed value is
> converted
> to unsigned.
>
>-Wconversion
> Warn for implicit conversions that may alter a value.
> This
> includes ... conversions between signed and unsigned,
> like
> unsigned ui = -1 ... Warnings about conversions between
> signed
> and unsigned integers can be disabled by using
> -Wno-sign-conversion.
>"
I find these to suffer from the same problems as all the
proposals to
"fix" the issue - they motivate the user to "fix" them with
unfortunate, ugly, and arbitrary consequences.
We need to be very careful with the idea of "just add a
warning".
Warnings are a sure sign of wishy-washy language design where
the
designers cannot make up their mind, so they dump it on the
user. One
person's warning become another person's must fix, and the
language
becomes balkanized, which is not good for portability,
comprehensibility, and best practices.
[...]
Don't add a warning, just make it outright illegal to assign
signed to
unsigned and vice versa unless an explicit cast is given. Code
that
*needs* to assign signed to unsigned *should* be
self-documented with a
cast indicating a reinterpretation of the bit representation of
the
value, and code that *unintentionally* mixes signs is buggy and
therefore *should* result in a compile error so that the
programmer can
fix the problem.
There are no "unfortunate", "ugly", or "arbitrary" consequences
here.
Much like the recent (or not-so-recent) change of prohibiting
implicit
conversion of a pointer to bool in an if-condition, or the
requirement
of a default case in a non-final switch, or so many other
improvements
in D over C/C++, such a change will (1) make problematic code
an error
so that it will get fixed, and (2) force users to rewrite
non-problematic code to be more self-documenting so that their
intent is
clearer. Sounds like a win-win situation to me.
Simply change the comparison to something that always works:
/// Returns negative value if a < b, 0 if they are equal or
positive value if a > b.
/// This will always yield a correct result, no matter which
integral types are compared.
/// It uses one extra comparison operation if and only if
/// one type is signed and the other unsigned but has bigger max.
/// For comparison with floating point values the buildin
/// operations have no problem, so we don't handle them here.
C opCmp(T, U)(const(T) a, const(U) b) pure @safe @nogc nothrow
if(isIntegral!T && isIntegral!U)
{
alias Signed!CommonType!(T, U) C;
static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof)
{
return (b > cast(U)T.max) ? -1 : cast(C)a - cast(C)b;
}
else static if(isUnsigned!T && isSigned!U && T.sizeof >=
U.sizeof)
{
return (a > cast(T)U.max) ? 1 : cast(C)a - cast(C)b;
}
else // both signed or both unsigned or the unsigned type is
smaller and can therefore be safely cast to the signed type
{
return cast(C)a - cast(C)b;
}
}