I've watched a great talk on distributed systems by Mae Milano and when talking about data races (starting at about 31m) she mentioned Rust and then talked about an alternative approach to handle mutability tracking. Instead of tracking lifetimes it defines linear regions and doesn't allow to send values between regions. In the talk it's achieved by using an iso keyword. There is also a proposal for Switf that works on the same principle, but to be honest I haven't got time to dig into the specifics.
Has something like this been ever discussed in context of Rust? I must admit, I haven't given it much thought, so it might be totally not feasible, but still, I'm very curious on what are thoughts on it from people that grasp languages design better than me.
Rust have started that revolution where people, finally, start applying affine type system and typestates (elaborate typestate system was removed from Rust but two states remain: variable may be “valid to access” and “invalid to access” and you can easily implement typestates on top of that in libraries… it's better to think as if typestate concept was moved from language to libraries in Rust, not removed entirely).
Lifetimes are viral: you couldn't just add them in some local procedure, you have to annotate everything you use, from standard library to all FFI bindings and all the code that you write!
That's why there are plenty of attempts to bring “simplified version” of lifetimes to languages which would catch some errors (less than what Rust may do!) but wouldn't need full rewrite of the whole codebase of large projects written in these projects.
I believe Swift would benefit from these attempts much more than C++, BTW. While in C++ they try to make language safe (and thus failure is almost imminent, it's almost impossible to add safety to unsafe language) Swift merely wants to use these for optimizations since it's already safe: Swift uses pervasive reference counting everywhere for correctness and that works, but is slow.
This may actually work fine for Swift, but it's absolutely not needed in Rust: Rust does have full-blown global tracking of lifetimes, why would it need reduced version of the same concept? It wouldn't make language more expressive, just more complex!
The way I understand Swift's solution, it's not an alternative to lifetimes (in the scoping/outlives sense). It's an alternative to Send vs !Send traits.
In Rust if something is not Send, then it can't be sent to any other thread, and it forever stuck staying on the same thread. What Swift does instead, when sending to another thread, it checks what objects are referenced from the object being sent. If everything that the object can access is sent to the same thread as well, then it concludes it can't cause a data race, and allows it. I think that's quite clever, and much more fine-grained than Rust's Send/not-Send. However, the way they compute these regions seems a bit magic to me, so I'm not sure how easy to use it will be in practice.
Her description at the end of "trees between regions, with graphs within a region" also, in my opinion, is effectively the same as how it's relatively normal in Rust to do most things with safe code (and tree-shaped data), but sometimes have an encapsulated unsafe collection with different access patterns.
Also, the idea that a doubly-linked list is a common and important data structure to support trivial implementations of is something a lot of Rust developers would dispute (on account of memory access patterns and architectural concerns). My day job is in a GCed language where it would be easier to implement one than in Rust and yet I've never seen anyone use a doubly-linked list.