Hi all.
I'm currently doing OpenGL type binding, and I noticed one assumption in the @safe code.
@safe, scope work only with explicit reference types, if your structure does not have such fields, then checks do not work.
In opengl, and in other APIs, we work with resources not through memory references, but through an integer descriptor.
@safe:
struct BufferView {
GLuint id;
//...
void destroy() @trusted scope {
//...
}
}
void doSmthScope(scope BufferRef buf) {...}
void doSmthGlobal(BufferRef buf) {...}
void test() {
scope BufferView buffer = createBuffer();
//we also could use generic RAII Handle type with view method
scope(exit) buffer.dispose();
doSmth1(buffer); //ok
doSmth2(buffer); //ok????
}
A hack that can solve the problem is this:
struct BufferView {
union {
protected uint _id;
protected void* _hack;
}
auto id() @trusted => _id;
}
There are two problems here:
- This is a stinky hack.
- We have an unnecessary memory overhead. 2 bytes became 4 bytes.
I suggest this solution:
import core.attributes: saferes; //SAFE RESource
@saferes
struct BufferView {
protected uint id;
}
All checks for live, scope, safe, etc. must consider structures marked with core.attributes.saferes as a memory reference.
I don't understand the internals of the compiler, so I can't implement it myself. I just saw that there are few occurrences of hasPointers, so this function is not that difficult to implement.
It also doesn't break backwards compatibility.
You can only add @saferes at the parser level.
I don't think that DIP is needed for this function, if it is needed, then I can't write it myself, because I'm bad with English.
What do you think about this?