
The Power of Lifetimes - Ygg2
http://pling.jondgoodwin.com/post/lifetimes/
======
Rusky
> 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/thesi...](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf))
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
Generativity 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
The 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
That'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-
bb6a3ed8a5...](https://github.com/dlang/dmd/pull/8504/files#diff-
bb6a3ed8a54c32937449b30e34a2380c) )

~~~
WalterBright
The 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
Thanks. Indeed it needs the attribute like `@safe: S* foo() {` (and `-dip1000`
seems to be unnecessary with it).

~~~
Arnavion
To 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).

