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