dmd 1.046 and 2.031 releases
Jarrett Billingsley
jarrett.billingsley at gmail.com
Tue Jul 7 08:16:44 PDT 2009
On Tue, Jul 7, 2009 at 11:15 AM, Jarrett
Billingsley<jarrett.billingsley at gmail.com> wrote:
> On Tue, Jul 7, 2009 at 1:48 AM, Andrei
> Alexandrescu<SeeWebsiteForEmail at erdani.org> wrote:
>>
>> Walter has implemented an ingenious scheme for disallowing narrowing
>> conversions while at the same time minimizing the number of casts required.
>> He hasn't explained it, so I'll sketch an explanation here.
>>
>> The basic approach is "value range propagation": each expression is
>> associated with a minimum possible value and a maximum possible value. As
>> complex expressions are assembled out of simpler expressions, the ranges are
>> computed and propagated.
>>
>> For example, this code compiles:
>>
>> int x = whatever();
>> bool y = x & 1;
>>
>> The compiler figures that the range of x is int.min to int.max, the range of
>> 1 is 1 to 1, and (here's the interesting part), the range of x & 1 is 0 to
>> 1. So it lets the code go through. However, it won't allow this:
>>
>> int x = whatever();
>> bool y = x & 2;
>>
>> because x & 2 has range between 0 and 2, which won't fit in a bool.
>
> Very cool. :)
>
>> The approach generalizes to arbitrary complex expressions. Now here's the
>> trick though: the value range propagation is local, i.e. all ranges are
>> forgotten beyond one expression. So as soon as you move on to the next
>> statement, the ranges have been forgotten.
>>
>> Why? Simply put, increased implementation difficulties and increased
>> compiler memory footprint for diminishing returns. Both Walter and I noticed
>> that expression-level value range propagation gets rid of all dangerous
>> cases and the vast majority of required casts. Indeed, his test suite,
>> Phobos, and my own codebase required surprisingly few changes with the new
>> scheme. Moreover, we both discovered bugs due to the new feature, so we're
>> happy with the status quo.
>
> Sounds fairly reasonable.
>
>> Now consider your code:
>>
>> byte x,y,z;
>> z = x+y;
>>
>> The first line initializes all values to zero. In an intra-procedural value
>> range propagation, these zeros would be propagated to the next statement,
>> which would range-check. However, in the current approach, the ranges of x,
>> y, and z are forgotten at the first semicolon. Then, x+y has range
>> -byte.min-byte.min up to byte.max+byte.max as far as the type checker knows.
>> That would fit in a short (and by the way I just found a bug with that
>> occasion) but not in a byte.
>
> The only thing is: why doesn't _this_ fail, then?
>
> int x, y, z;
> z = x + y;
>
> I'm sure it's out of convenience, but what about in ten, fifteen years
> when 32-bit architectures are a historical relic and there's still
> this hole in the type system?
>
> The same argument applies for the implicit conversions between int and
> uint. If you're going to do that, why not have implicit conversions
> between long and ulong on 64-bit platforms?
>
I think I've confused the mailing list's threading algorithm.
More information about the Digitalmars-d-announce
mailing list