+1 on making Phobos GC-free.
On Sunday, 2 February 2014 at 07:35:21 UTC, Andrei Alexandrescu
wrote:
On 2/1/14, 10:00 PM, Frank Bauer wrote:
On Sunday, 2 February 2014 at 05:41:53 UTC, Andrei
Alexandrescu wrote:
Sure. While you're young typecheck this:
class A {
auto stuff() { ...; return this; }
}
Andrei
It would be a Borrowed!A, I would say, no matter how an A is
allocated.
A GC!A, an ARC!A and an Owning!A convert equally well to a
Borrowed!A.
As long as the Borrowed!A is in use (i.e. scope) after stuff()
returns,
the A object must not be freed (compiler enforced). Would that
make sense?
No.
What I'm driving at is that right now the type is A, as is in a
variety of other situations. It would be a whole different
language that would be wholly incompatible with D.
Andrei
Why is that? I propose the new memory regime to be 100%
compatible with all existing D code. It is way more powerful than
anything scope can do. And it seems a lot less work to me than
going through GC optimization and custom allocator tracing hell.
Let's see how far we can get if we require none of the existing D
code to break.
Example: this is current D code that runs unchanged and with the
same semantics under the new memory regime. GC(T) and Borrowed(T)
remain under the hood:
class A {
A foo() { return this; } // returns Borrowed!A
}
void main () {
A m1 = new A; // m1 is a GC!A
A m2 = m1; // m2 is a Borrowed!A
A m3; // Borrowed!A
m3 = m1; // fine: assignment from GC!A to Borrowed!A
m3 = bar(m1); // fine: m1 converted from GC!A to
Borrowed!A, assignment from Borrowed!A to Borrowed!A
m3 = bar(m2); // fine: m2 already Borrowed!A, assignment
from Borrowed!A to Borrowed!A
m1 = new A; // fine: can reasssign GC!A although there
are outstanding references
m1 = m2; // fine: can reassign GC!A to a Borrowed!A
}
A bar(A a) { // takes and returns Borrowed!A
A b1 = a;
return b1;
}
Now here it comes: if, on the other hand, I replace the first
'new' with, say e.g., 'newOwning' (or '~', whatever), I get
GC-free code:
A m1 = newOwning A; // m1 is an Owning!A, allocating on the heap
and freeing when it goes out of scope
Then these lines above would be in error:
m1 = new A; // error: can't reassign to m1 because m2 and
m3 still referencing m1 (same for newOwning)
m1 = m2; // error: can't assign Borrowed!A to Owning!A
ARC(T) could be implemented similarly.
Nothing changes one bit for those who want to use the GC as
before. ARC(T) and Owning(T) would be *ADDED* on top of the
existing language spec.
Emplacement new, as Adam mentioned, is not a problem: you always
get to the emplaced object with a Borrowed!T. The underlying
memory is managed separately and automatically as a GC!M, ARC!M
or Owning!M (M could be an array of bytes, e.g.).