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.