D needs first-class lifetimes before it can get ownership and borrowing

Nick Treleaven nick at geany.org
Sat Aug 10 17:38:43 UTC 2019


On Saturday, 10 August 2019 at 13:30:17 UTC, Olivier FAURE wrote:
> I've been trying to nail down the semantics of my in-progress 
> DIP for a `unique` qualifier, and I couldn't come up with 
> coherent rules for double-indirection.
>
> To give you an shortened example of the problem, contemplate 
> this:
>
>     int* gptr;
>
>     struct SmartPtr {
>         int* ptr;
>
>     @safe:
>         ~this() { reset(); }
>     @trusted:
>         void init() { ptr = cast(int*)malloc(int.sizeof); *ptr 
> = 0; }
>         void reset() { free(ptr); ptr = null; }
>
>     @safe:
>         ref int get() return { assert(ptr); return *ptr; }
>
>         void borrow() { gptr = this.ptr; }
>     }
>
>     @safe
>     void main() {
>         SmartPtr s;
>         s.init();
>         s.borrow();
>         s.reset();
>         *gptr = 1; 		// Memory corruption
>     }
>
> The problem above is that, under DIP-1000, the compiler assumes 
> `borrow()` doesn't escape any data, because it takes `this` by 
> ref; and yet it escapes this.ptr, because there's no way to 
> mark this.ptr as scope.

We could allow scope fields:

struct SmartPtr {
   scope int* ptr

> As long as borrow() is @safe, there's no way reset() can be 
> @trusted.

That use of @trusted requires @safe code inside the struct (and 
in the defining module due to field access) to form part of the 
@trusted contract.

scope fields would lessen the burden of @trusted and allow 
encapsulated pointers. But there still won't be an error if you 
don't use scope for the ptr field.


More information about the Digitalmars-d mailing list