On Sunday, 3 September 2017 at 15:39:58 UTC, Uknown wrote:
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.

References are just non-null syntax for pointers that take addresses implicitly on function call. Issues not related to null that pertain to pointers translate to references, as any (non-null) pointer can be turned into a reference (and vice versa):

---
void foo(int* a, bool b)
{
    if (b) bar(a);
    else baz(*a);
}

void bar(int* a) {}
void baz(ref int a) { bar(&a); }
---


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
}
[...]

Note: There's no need to attribute the RCArray template as @safe (other than for debugging when developing the template). The compiler will derive it for each member if they are indeed @safe.

W.r.t. the rest: I don't think treating references as different from pointers can be done correctly, as any pointers/references can be interchanged at runtime.


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
}

Dealing with pointer aliasing in a generic way is a hard problem :p


Reply via email to