DIP 1021--Argument Ownership and Function Calls--Community Review Round 1

Timon Gehr timon.gehr at gmx.ch
Fri Jul 19 16:39:51 UTC 2019


On 19.07.19 15:09, Nick Treleaven wrote:
> On Monday, 15 July 2019 at 15:23:32 UTC, Mike Parker wrote:
>> https://github.com/dlang/DIPs/blob/793f83911fdc8c88c6ef34e6a36b5e11e3e574e5/DIPs/DIP1021.md 
>>
> 
> OK, I think I have a practical example that this DIP enables. Here is a 
> RAII @nogc dynamic array that can be appended to, and exposes individual 
> elements by ref. Before the destructor and `append` could not be marked 
> @trusted because of `maybe_bad` - its ref parameter `i` may have 
> outlived a.data.ptr. Now all methods of Array can be @trusted AFAIK.
> 
> struct Array
> {
>      private int[] data;
>      import core.stdc.stdlib;
>      @nogc:
> 
>      void append(int e) @trusted
>      {   // inefficient but it works
>          const len = data.length + 1;
>          auto ptr = cast(int*)realloc(data.ptr, len * int.sizeof);
>          data = ptr[0..len];
>      }
> 
>      ref int get(size_t i) @trusted return
>      {
>          return data[i];
>      }
> 
>      ~this() @trusted
>      {
>          if (data.ptr) free(data.ptr);
>      }
> }
> 
> @safe:
> 
> void maybe_bad(ref Array a, ref int i)
> {
>      a = Array(); // frees a.data.ptr
>      i++;
> }
> 
> void main()
> {
>      Array a;
>      a.append(5);
>      // compiler knows result of `get` is owned by `a`
>      // error: Can't pass multiple mutable references owned by `a`
>      maybe_bad(a, a.get(0));
> }
> 
> Walter - is this correct?

Some problems with this code that don't relate to the DIP:
- It still has a default constructor, so you can call `Array(new 
int[](10))` and cause a free on a GC pointer.
- The copy constructor is neither implemented nor disabled, so you can 
easily cause a double free.


I don't think the DIP enables any more code to be @trusted (as it points 
out in the limitations section).

Consider:

@safe:
class C{
     Array a;
     this(Array a){ this.a=move(a); }
}

void maybe_bad(C c, ref int i){
     c.a = Array();
     i++;
}

void main(){
     auto c=new C(Array());
     c.a.append(5);
     auto d=c;
     maybe_bad(c,d.a.get());
}


More information about the Digitalmars-d mailing list