User:Schuetzm/isolated

From D Wiki
Jump to: navigation, search

(Warning: not well thought through yet)

Isolated islands

Currently, this works:

void main() {
    immutable int* p = new int;
}

This doesn't:

struct S {
    int* p;
}

void main() {
    auto tmp = new S;
    tmp.p = new int;
    immutable S* s = tmp;    // Error: cannot implicitly convert expression (tmp) of type S* to immutable(S*)
}

But if we wrap the construction in a pure function, it does work:

struct S {
    int* p;
}

S* makeS() pure {
    auto tmp = new S;
    tmp.p = new int;
    return tmp;
}

void main() {
    immutable S* s = makeS();
}

By utilizing deadalnix' "isolated" idea, we can make the second example work, too. This will be useful for incremental construction of complex immutable data structures, as well as data structures that should be transferred to another thread.

TODO: specify the rules (islands concept)

Isolated across function boundaries

Currently, values are inferred to be unique when they originate from certain types of expressions, most importantly `new` and calls to strongly pure functions (or weakly pure functions with parameters having incompatible types with the return value). But there are some functions that are known to return unique values by the programmer, but the compiler cannot know this. std.typecons.Unique.release is a good example. On the other hand, functions might require a unique argument, without casting it to immutable. Again, std.typecons.Unique's constructor comes to mind.

An @isolated annotation is proposed to express this intent. Applied to a parameter (or after the function for `this`), the function can only be called with unique arguments for that parameter. Applied on the left side of a function declaration, the function will be treated as returning a unique value. Additionally, aggregate members can be designated with it.

The compiler statically verifies that values assigned to @isolated variables are unique, and treats values read from @isolated variables as such. Anything written to an @isolated variable becomes inaccessible; when an @isolated variable is read from, it also becomes inaccessible (exception: const scope). @isolated members can only be read from an @isolated aggregate; this ensures that the entire aggregate will become inaccessible in the calling function.

With this tool, not only can std.typecons.Unique be implemented more safely, but it's now also possible to safely transfer ownership of mutable data structures across threads.