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