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
}

Reply via email to