// REQUIRED_ARGS: -preview=dip1021 /* Should compile successfully */ struct Allocation { int* ptr; size_t length; } void canFind(scope Allocation); int* malloc(); void free(int*); void pitcher(); void borrow(scope int*); void borrow2c(const scope int*, const scope int*); void out1(out int*); /*****************************/ @live int* foo1(int* p) { return p; // consumes owner } @live int* foo2() { int* p = null; return p; // consumes owner } @live int* foo3(int* p) { scope int* q = p; // borrows from p return p; // use of p ends borrow in q } @live int* foo4(int* p) { scope int* bq = p; // borrow scope const int* cq = p; // const borrow return p; // ends both borrows } /*******************************/ @live void foo5() { auto p = malloc(); scope(exit) free(p); pitcher(); } /*******************************/ void deallocate(int* ptr, size_t length) @live { canFind(Allocation(ptr, length)); // canFind() borrows ptr free(ptr); } /*******************************/ @live int* test1() { auto p = malloc(); scope b = p; return p; } @live int* test2() { auto p = malloc(); auto q = p; return q; } @live void test3() { auto p = malloc(); free(p); } @live void test4() { auto p = malloc(); borrow(p); free(p); } @live void test5() { auto p = malloc(); scope q = p; borrow2c(p, p); free(p); } @live void test6() { int* p = void; out1(p); // initialize free(p); // consume } /*******************************/ void zoo1(int); @live void zoo2() { int* p = malloc(); zoo1(*p); // does not consume p free(p); } @live void zoo3() { int** p = cast(int**)malloc(); free(*p); // consumes p } @live void zoo4() { int[] a = malloc()[0 .. 1]; zoo1(a[0]); // does not consume a free(a.ptr); // consumes a } @live void zoo5() { int*[] a = (cast(int**)malloc())[0 .. 1]; free(a[0]); // consumes a } struct S { int i; int* p; } @live void zoo6() { S* s = cast(S*)malloc(); zoo1(s.i); // does not consume s free(cast(int*)s); } @live void zoo7() { S* s = cast(S*)malloc(); free(s.p); // consumes s }