[Dlang-internal] DIP1000 discussion and testing
Martin Nowak via Dlang-internal
dlang-internal at puremagic.com
Fri Oct 21 03:11:28 PDT 2016
On Thursday, 20 October 2016 at 09:00:02 UTC, Walter Bright wrote:
>> I read that RC `opAssign` and `destroy` would remain unsafe
>> b/c destroying the
>> owner might leave a dangling ref parameter in `fun(ref RCS rc,
>> ref int ri)`.
>> It seems that unsafe assignment/destruction of RCs would be
>> very limiting.
>> Do we at least have an idea how to tackle this problem? In the
>> RCClass idea an
>> additional addRef/decRef call was proposed.
>> Also see
>> https://github.com/dlang/DIPs/pull/35#issuecomment-252345548.
>
> The solution to that has been proposed and forgotten a couple
> of times. It is to have the compiler insert code to
> preemptively increment the reference count, then reassigning
> the RC object will not invalidate references to its internals.
> This is beyond the scope of DIP1000, though. DIP1000 is
> necessary for memory safety even without reference counting.
Thought a bit more about this.
The essence of the problem is a simple pointer aliasing problem,
namely calling
void dangling(ref A a, ref B b)
is unsafe if A is a "container" that could own a B.
This does not only apply to RC but also things like arrays with
deterministic MM, unions/variants (changing type of b's pointee),
or implementations of Nullable/Optional using heap allocated
memory.
Fortunately any pointer aliasing through untyped memory/pointers
in A (ubyte[], void*) can only result in a dangling b pointer, if
doing unsafe operations on a (or incorrectly marked @trusted
ones).
For pointer aliasing through typed fields of A, the compiler can
detect a possible aliasing and mark the function call as unsafe.
That would allow operations on a that could free Bs to be
@trustable.
This aliasing problem seems only slightly related to scope/escape
analysis.
A container using scope in a @safe manner, should only escape
scoped references.
So the statement of the problem is actually
void dangling(ref A a, scope ref B b).
Copying a before the call couldn't solve all those problems, e.g.
Unique isn't copyable, a union/variant could be in a reference
type field of A.
But it seems that we can detect all such unsafe function calls
and the problem only scratches on scope b/c we want to know
whether the lifetime of b might be limited attached to a. So
seems indeed fair enough to leave this aside for now.
What would be the plan for RC.opAssign? Making it @trusted after
DIP1000 and implementing the aliasing detection later, @trusted
opAssign but conservatively @unsafe any call with multiple
references (at least one of which being scoped), or @system
opAssign and changing it to @trusted later?
It seems that the aliasing detect wouldn't be too hard to
implememt (even implementable as druntime template similar to
std.traits.hasAliasing). Am I right that conservatively detecting
the aliasing would allow a slightly limited subset of @safe RC
usage?
If so going w/ @trusted RC.opAssign and the aliasing detection
seems like a good milestone for 2.073.
More information about the Dlang-internal
mailing list