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/jycylhdhdewtgumba...@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/bghjqvvrdcfqmoiyy...@forum.dlang.org

Reply via email to