DIP1000: Scoped Pointers (Discussion)

deadalnix via Digitalmars-d digitalmars-d at puremagic.com
Sat Aug 13 09:16:57 PDT 2016


On Saturday, 13 August 2016 at 14:35:09 UTC, Andrei Alexandrescu 
wrote:
>> You have the detail in your inbox for close to 2 years now.
>
> Thanks. Do you have a date or title of the thread? -- Andrei

In the very thread that ended up with DIP1000 .

I suggested various changes int he DIP, which I'm copying bellow. 
You can read it in context digging around the 26/11/2014 .

Copying the proposed changes to DIP 1000:
=========================================

Ok, resurrecting the thread, I'd like to propose another way to 
specify this. The end result should be very close but should 
provide a simpler/clearer mental model.

Every expression has now has a lifetime associated with it, and 
can be marked as "scope". It is only possible to assign b to a if 
b has a lifetime equal or greater than a's.

An infinite lifetime is a lifetime greater or equal than any 
other lifetime. Expression of infinite lifetime are:
  - literals
  - GC heap allocated objects
  - statics and enums.
  - rvalues of type that do not contain indirections.
  - non scope rvalues.

Dereference share the lifetime of the dereferenced expression (ie 
infinite lifetime unless the expression is scope). Address of 
expression shared the lifetime of the base expression, and in 
addition gain the scope flag.

Comment: Using these rule, we basically define any indirection 
being of infinite lifetime by default, and we propagate the 
lifetime when scope. The addition of the scope flag for address 
of is necessary to disallow taking address->dereference to yield 
an infinite lifetime.

Variables delcarations (including parameters) have the lifetime 
of the block they are declared in (2 pitfalls here, I don't have 
good solution, and the original spec do not as well : #1 
destructor, finally, scope statement and #2 closures). Use of 
these variables shared the lifetime of the variable, unless they 
qualify for infinite lifetime. Parameter's lifetime are 
unordered, meaning smaller than infinite, greater than the 
function's scope, but not equal to each other nor greater/smaller 
than each others.

Working from there, I'd like to define properly the pitfalls #1 
and #2 . These are the great absent from what is discussed so far.

const scope works for Rust, but isn't gonna fly for D. That is a 
good idea, but not worth the cost.

I'd like to discuss the pro and cons of such a definition 
(compared to rust for instance):
  - We can't specify explicit lifetime for parameters. I'm not 
sure how limiting it is. This is something we can extend toward 
anyway in the future, so I suggest we put that asside for now.
  - We can't define lifetime of indirections explicitly. This 
clearly limit the expressiveness compared to Rust, but I it allow 
for scope to be a storage class rather than a type qualifier, and 
I think this is a winner when looking at the complexity / 
expressiveness ratio.
  - In D, mutability and burrowing are decoupled, which i think is 
a plus compared to Rust. That prevent us to go for things like 
the proposed const scope, but simply the concept of both 
mutabilities and burrowing in D, while allowing some pattern that 
aren't easy to get in Rust (multiple writable reference to one 
object in a single thread for instance, is trivial in D).

Maybe I'm convincing myself, but I think we have a winner here.

Andrei, what do you have in mind when you say scope should be the 
default ? I do think this is a sensible default, but I fail to 
see how this is gonna translate with existing code in a nice 
manner.


More information about the Digitalmars-d mailing list