C `restrict` keyword in D

Uknown via Digitalmars-d digitalmars-d at puremagic.com
Sun Sep 3 08:39:58 PDT 2017


On Sunday, 3 September 2017 at 12:59:25 UTC, Moritz Maxeiner 
wrote:
> [...]
> The main issue I see is that pointers/references can change at 
> runtime, so I don't think a static analysis in the compiler can 
> cover this in general (which, I think, is also why the C99 
> keyword is an optimization hint only).

Well, I thought about it, I have to agree with you, as far as 
pointers go. There seems to be no simple way in which the 
compiler can safely ensure that the two restrict pointers point 
to the same data. But fir references, it seems trivial.

In order to do so, RCArray would have to first annotate it's 
opIndex, opSlice and any other data returning member functions 
with the restrict keyword. e.g.
struct RCArray(T) @safe
{
	private T[] _payload;
	/+some other functions needed to implement RCArray correctly+/
	restrict ref T opIndex(size_t i) {
		//implimentation as usual
		return _payload[i];
	}
	restrict ref T opIndex() {
		return _payload;
	}
	//opSlice and the rest defined similary
}

void main() @safe
{
	RCArray!int my_array;
	...
	auto t = my_array[0];//error: my_array.opIndex(0) is defined as 
restrict
	//This essentialy prevents a second reference from existing in 
the same scope
	foo(arr, arr[0]);
	//error: call to foo introduces `restrict` data from the same 
container
         //into the scope of foo
}

void foo(ref RCArray!int arr, ref int val) @safe
{
	{
		auto copy = arr; //arr's (and copy's) reference counts are both 
2
		arr = RCArray!int([]); // There is another owner, so arr
		// forgets about the old payload
	} // Last owner of the array ('copy') gets destroyed and happily
	// frees the payload.
	val = 3;//No longer an issue!
}

This is now no longer like the C99 keyword in behaviour, but on 
the bright side, with one annotation to the return types, RCArray 
suddenly doesn't need to worry about escaped references. Also, no 
modifications would be needed to the foo function.
This is potentially useful for other owning container types. The 
compiler could still use the information gainer from the restrict 
annotation for optimizations, although such optimizations would 
be much less aggressive than in C.

Coming back to pointers, the only way I can see (short of 
bringing Rust's borrow checker to D) is to add additional 
annotations to function return values. The problem comes with 
code like this :

int * foo() @safe
{
	static int[1] data;
	return &data[0];
}
void main()
{
         int * restrict p1 = foo();
         int * restrict p2 = foo();//Should be error, but the 
compiler can't figure
                                   //this out without further 
annotations
}


More information about the Digitalmars-d mailing list