On Thursday, 2 June 2016 at 23:29:57 UTC, Timon Gehr wrote:


void foo(scope int* k){
    void bar(){
        scope int* x;
// need to check that lifetime of x ends not after lifetime of k
        assign(x,k);
    }
}

I.e. now we need a way to annotate 'assign' in order to specify the contract I have written down in the comments.
...
[1] It might be possible to get that example to pass the type checker with 'return' annotations only if I change 'ref' to 'out',

There needs to be additional syntax for specifying that an input reference escapes through another parameter, not through returning. For example:

void assign(S, T)(ref S a, T b return!a) {
    a = b;    // accepted, as specified in the signature
}

void foo(scope int* k) {
    void bar() {
        scope int* x;
        assign(x, k);  // accepted, because L(x) < L(k)
    }
}

(By the way, both the `return` annotation in `assign()` and the `scope` in the declaration of `x` don't need to be explicit, they can inferred because `assign()` is a template and `x` is a local variable.)

But AFAICS, the point about `out` vs `ref` isn't correct. `out` resets the parameter to its `.init` value. The specification currently doesn't say whether this is done by assignment or by destruction followed by blitting, but in any case, both `opAssign()` and `~this()` have access to the original reference; therefore using `out` doesn't help in the general case (not an issue for POD types, though).

but often more than two lifetimes are involved, and then it falls flat on its face.

Can you expand on that? With the addition of a provision for escaping by reference as suggested (and maybe for escaping by a global variable/heap), the `return` syntax should be able to express all lifetime relations that don't go more than one indirection deep.

Reply via email to