4 ms·
The Power of Lifetimes
- Rusky 8y ago> The use of a special kind of lifetime annotation, where the lifetime has to match exactly, can be used to get around this limitation. This is already expressible in Rust, using invariant lifetimes. You can hand someone an opaque invariant lifetime, let them build a mutable cyclic data structure with it, and then pass that data structure around. This use of invariant lifetimes, called "generativity," is described in more detail here (https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf https://raw.githubusercontent.com/Gankro/thesis/master/thesi...) in section 6.3, which describes a way to use lifetimes as unique tokens for all sorts of use cases. And even more closely aligned with what the article is talking about, Catherine West has put together a library that uses generativity to provide a safe interface to a garbage collected heap, as part of a reimplementation of Lua: the `gc-arena` crate in https://github.com/kyren/luster https://github.com/kyren/luster
- sanxiyn 8y agoGenerativity is truly the most mysterious part of Rust type system. Like template metaprogramming in C++, I see the great (ab)use potential in the future.
- WalterBright 8y agoThe D programming language now supports tracking of lexical lifetimes. For a simple example, int* foo() { int i; int* p = &i; int* q = p; return q; } is detected as an error. This tracking is even done across function calls: int* bar(scope int *p); // p doesn't escape bar() int* abc(return scope int* p); // p doesn't // escape abc() but is returned from it int* foo() { int i; return bar(&i); // ok return abc(&i); // error } The annotations can be explicit, or can be inferred by the compiler by analyzing the function bodies.
- Arnavion 8y agoThat's cool, though it doesn't seem to work through a level of indirection. https://d.godbolt.org/z/zkm39N https://d.godbolt.org/z/zkm39N (I don't know much about dlang. I got the compiler flags from googling and happening upon the test case in this PR https://github.com/dlang/dmd/pull/8504/files#diff-bb6a3ed8a54c32937449b30e34a2380c https://github.com/dlang/dmd/pull/8504/files#diff-bb6a3ed8a5... )
- WalterBright 8y agoThe code has to be annotated with `@safe:` and use the `-dip1000` compiler flag, which enables the checking. With such: test.d(9): Error: reference to local variable s assigned to non-scope s.i
- Arnavion 8y agoThanks. Indeed it needs the attribute like `@safe: S* foo() {` (and `-dip1000` seems to be unnecessary with it).
- Arnavion 8y agoTo correct my comment: `-dip1000` is still needed because `@safe` is overly restrictive. `@safe` prevents taking the address of `s` entirely regardless of how it's used, so `-dip1000` is needed to allow it when it's safe (such as using `&s` without letting it escape scope).