RFC: Value range propagation for if-else
H. S. Teoh via Digitalmars-d
digitalmars-d at puremagic.com
Wed Jun 18 20:07:00 PDT 2014
On Wed, Jun 18, 2014 at 10:08:06PM +0000, bearophile via Digitalmars-d wrote:
[...]
> D language is designed to allow you to create data structures in
> library code able to act a lot like built-in features (so there's a
> refined operator overloading, opCall, static opCall, and even more
> unusual things like opDispatch),
opDispatch is extremely powerful; I think we've only barely begun to tap
into what it can do. Like my recent safe-dereference template function.
;-)
> but there are built-in features that can't yet be reproduced in
> library code, observe:
>
> void main() {
> int[5] arr;
> auto x = arr[7];
> }
>
>
> dmd 2.066alpha gives a compile error:
>
> test.d(3,14): Error: array index 7 is out of bounds arr[0 .. 5]
>
>
> In D there is opIndex to overload the [ ], but its arguments are
> run-time values, so I think currently they have no way to give a
> compile-time error if you use an index that is known statically to be
> outside the bounds. So currently you can't reproduce that behavour
> with library code. Propagating the value range information to the
> constructor, plus the new __trait(valueRange, exp), allow to solve
> this problem. And indeed this allows to implement nice ranged values
> like in Ada, and to do what the Static_Predicate of Ada does.
It seems like ultimately, we want to have some kind of uniformity
between built-in compiler intrinsics and user-defined types, such as
allowing user-defined types to access internal compiler knowledge like
value range and many other things.
One very useful thing to have would be a way to tell if a particular
symbol has a compile-time known value. You could then do things like
custom constant-folding on user-defined types by automatically
simplifying expressions at compile-time.
Hmm. Maybe this is already possible to some extent?
template hasCompileTimeValue(alias Sym) {
alias hasCompileTimeValue = __traits(compiles, (){
enum val = Sym;
});
}
int x = 10, y;
// Will this work? (I don't know)
assert(hasCompileTimeValue!x);
assert(!hasCompileTimeValue!y);
> Another common example of what you currently can't do with library
> code:
>
> void main() {
> import std.bigint;
> BigInt[] arr = [10, 20];
>
> import std.numeric;
> alias I10 = Bound!(int, 0, 10);
> I10[] arr = [8, 6, 20];
> }
>
>
> (In theory the compiler should also catch at compile time that bug,
> because 20 is outside the valid bounds of I10.)
[...]
This is a different instance of the same problem as above, isn't it?
If Bound has access to compiler knowledge about value ranges, then it
would be able to statically reject out-of-range values.
T
--
"I'm not childish; I'm just in touch with the child within!" - RL
More information about the Digitalmars-d
mailing list