My Reference Safety System (DIP???)

via Digitalmars-d digitalmars-d at puremagic.com
Sun Mar 1 06:40:52 PST 2015


On Sunday, 1 March 2015 at 05:29:19 UTC, Zach the Mystic wrote:
> On Saturday, 28 February 2015 at 20:49:22 UTC, Marc Sch├╝tz 
> wrote:
>> I encountered an ugly problem. Actually, I had already run 
>> into it in my first proposal, but Steven Schveighoffer just 
>> posted about it here, which made me aware again:
>>
>> http://forum.dlang.org/thread/mcqcor$aa$1@digitalmars.com#post-mcqk4s:246qb:241:40digitalmars.com
>>
>>    class T {
>>        void doSomething() scope;
>>    }
>>    struct S {
>>        RC!T t;
>>    }
>>    void main() {
>>        auto s = S(RC!T()); // `s.t`'s refcount is 1
>>        foo(s, s.t);        // borrowing, no refcount changes
>>    }
>>    void foo(ref S s, scope T t) {
>>        s.t = RC!T();       // drops the old `s.t`
>>        t.doSomething();    // oops, `t` is gone
>>    }
>
> One quick thing. I suggest a solution here:
>
> http://forum.dlang.org/post/jycylhdhdewtgumbavep@forum.dlang.org
>
> You do the checking and adding in the called function, not the 
> caller. The algorithm:
>
> 1. Keep a compile-time refcount per function. Does the 
> parameter get released, i.e. does the refcount ever go below 1? 
> If not, stop.
>
> 2. Can the parameter contain (as a member) a reference to a 
> refcounted struct of the types of any of the other parameters? 
> If not, stop.
>
> 3. Okay, you need to preserve the reference. Add a call to 
> opAdd at the beginning and one to opRelease at the end of the 
> function. Done.

I don't think a callee-based solution can work:

     class T {
         void doSomething() scope;
     }
     struct S {
         RC!T t;
     }
     void main() {
         auto s = S(RC!T()); // `s.t`'s refcount is 1
         T t = s.t;          // borrowing from the RC wrapper
         foo(s);
         t.doSomething();    // oops, `t` is gone
     }
     void foo(ref S s) {
         s.t = RC!T();       // drops the old `s.t`
     }

`foo()` has no idea whether there are still `scope` borrowings to 
`s.t`.

Therefore, if there _is_ a solution, it needs to work inside the 
caller. You second idea [1] goes in the right direction. 
Unfortunately, it is DIP74 specific; in this form, it cannot be 
applied to user-defined struct-based RC wrappers. (DIP25 is also 
affected by this problem, by the way.)

To keep the compiler agnostic about the purpose of the structs in 
question, I'm afraid the only solution is uniqueness tracking. If 
`@unique` we're a property of references, we could either 
automatically make those references `const` when more than one 
reference exists, or disallow passing these values to functions 
if the corresponding parameter is annotated @unique.

Unfortunately, this is likely to be a very invasive change, in 
contrast to `scope` :-(

[1] 
http://forum.dlang.org/post/bghjqvvrdcfqmoiyyuqz@forum.dlang.org


More information about the Digitalmars-d mailing list