On Tue, Jul 7, 2009 at 11:15 AM, Jarrett Billingsley<[email protected]> wrote: > On Tue, Jul 7, 2009 at 1:48 AM, Andrei > Alexandrescu<[email protected]> 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.
