dmd 1.046 and 2.031 releases

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Jul 6 22:48:41 PDT 2009


Robert Jacques wrote:
> On Mon, 06 Jul 2009 01:05:10 -0400, Walter Bright 
> <newshound1 at digitalmars.com> wrote:
> 
>> Something for everyone here.
>>
>>
>> http://www.digitalmars.com/d/1.0/changelog.html
>> http://ftp.digitalmars.com/dmd.1.046.zip
>>
>>
>> http://www.digitalmars.com/d/2.0/changelog.html
>> http://ftp.digitalmars.com/dmd.2.031.zip
> 
> Thanks for another great release.
> 
> Also, I'm not sure if this is a bug or a feature with regard to the new 
> integer rules:
> 
>    byte x,y,z;
>    z = x+y;    // Error: cannot implicitly convert expression 
> (cast(int)x + cast(int)y) of type int to byte
> 
> which makes sense, in that a byte can overflow, but also doesn't make 
> sense, since integer behaviour is different.

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.

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.

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.

> BTW: The fact that in my original code base DMD gave me the line, inside 
> the string, inside the mixin, inside the template, inside the mixin, 
> inside the struct was just awesome.
> 
> P.S. There's a bunch of functions in phobos (like std.math.lrint) which 
> return a long and should also have (at least) an integer version as 
> well. (Maybe rndto!T() ?)

Sounds like Don's area. Don?


Andrei


More information about the Digitalmars-d-announce mailing list